Skip to content
This repository has been archived by the owner on Oct 6, 2021. It is now read-only.

Commit

Permalink
feat: tracer registration page (#42)
Browse files Browse the repository at this point in the history
* feat: implement content board component

* feat: implement form title

* feat: implement base form text input

* feat: add checkbox

* feat: import button from wargabantuwarga.com

* feat: implement form and register page

* feat: implement registration

* fix: add isGroupItem to inputtext

* fix: apply suggestions from code review

* fix: apply suggestions from code review

* refactor: finalise signup form design

* fix: `b` -> `strong

* fix: use correct components, add tests

* fix: `/register` -> `/registration`

* test: fixed tests

* fix: use `defaultValue` instead of `selected`

Co-authored-by: Aditya Purwa <adityapurwa@windowslive.com>
Co-authored-by: Muhammad Al Faris <muhammad.abdulmajid@efishery.com>
Co-authored-by: Resi Respati <resir014@gmail.com>
Co-authored-by: Zain Fathoni <me@zainf.dev>
  • Loading branch information
5 people committed Aug 12, 2021
1 parent 1bd6b1c commit b037f1e
Show file tree
Hide file tree
Showing 18 changed files with 669 additions and 5 deletions.
19 changes: 19 additions & 0 deletions __tests__/pages/registration.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { render, screen } from "@testing-library/react";
import RegistrationPage from "~/pages/registration";

jest.mock("next/router", () => require("next-router-mock"));

describe("RegistrationPage", () => {
it("renders correctly", () => {
render(<RegistrationPage />);

const title = screen.getByText(/Pendaftaran Tracer/i);
expect(title).toBeVisible();

const subtitle = screen.getByText(/Isi dengan lengkap dan ingat Nama ID dan Kata Sandi Anda/i);
expect(subtitle).toBeVisible();

const registerButton = screen.getByRole("button", { name: /daftar/i });
expect(registerButton).toBeVisible();
});
});
143 changes: 143 additions & 0 deletions components/registration/registration-form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import React from "react";
import { InformationCircleIcon, EyeIcon } from "@heroicons/react/outline";

import {
FormGroup,
FormLabel,
InputCheckboxCustom,
InputText,
InputSelect,
} from "~/components/ui/forms";
import { PrimaryButton as Button } from "~/components/ui/button";

export function RegistrationForm() {
return (
<div className="space-y-6">
<div className="space-y-2">
<FormLabel>Nama Lengkap</FormLabel>
<InputText />
</div>
<div className="space-y-2">
<FormLabel>Nomor Whatsapp yang aktif</FormLabel>
<FormGroup>
<span className="inline-flex items-center px-3 first:rounded-l-md last:rounded-r-md border border-r-0 border-gray-300 bg-gray-50 text-gray-500 sm:text-sm">
+62
</span>
<InputText
className="block w-full sm:text-sm"
isGroupItem
placeholder="838xxxxxxx"
type="text"
/>
</FormGroup>
</div>
<div className="space-y-2">
<FormLabel>Provinsi</FormLabel>
<InputSelect defaultValue="" title="Urut berdasarkan">
<option disabled hidden value="">
-Masukkan Provinsi-
</option>
<option>A</option>
<option>B</option>
<option>C</option>
</InputSelect>
</div>
<div className="space-y-2">
<FormLabel>Kabupaten</FormLabel>
<InputSelect defaultValue="" title="Urut berdasarkan">
<option disabled hidden value="">
-Masukkan Kabupaten-
</option>
<option>A</option>
<option>B</option>
<option>C</option>
</InputSelect>
</div>
<div className="space-y-2">
<FormLabel>Kecamatan</FormLabel>
<InputSelect defaultValue="" title="Urut berdasarkan">
<option disabled hidden value="">
-Masukkan Kecamatan-
</option>
<option>A</option>
<option>B</option>
<option>C</option>
</InputSelect>
</div>
<div className="space-y-2">
<FormLabel>PKM</FormLabel>
<InputSelect defaultValue="" title="Urut berdasarkan">
<option disabled hidden value="">
-Masukkan PKM-
</option>
<option>A</option>
<option>B</option>
<option>C</option>
</InputSelect>
</div>
<div className="space-y-2">
<FormLabel>Instansi Asal</FormLabel>
<div>
<InputCheckboxCustom className="mr-4 w-3/12" name="instance">
TNI
</InputCheckboxCustom>
<InputCheckboxCustom className="mr-4 w-3/12" name="instance">
Polri
</InputCheckboxCustom>
<InputCheckboxCustom className="w-3/12" name="instance">
Puskesmas
</InputCheckboxCustom>
</div>
</div>
<div className="space-y-2">
<FormLabel>Nama ID / Username</FormLabel>
<div className="text-red-500 italic text-sm">
<div className="flex">
<div className="mr-1">
<InformationCircleIcon className="w-5 h-5" />
</div>
<span>
<strong>Nama ID</strong> ini akan digunakan untuk login. Harap di ingat!
</span>
</div>
</div>
<InputText placeholder="Masukkan Nama ID" />
<span className="block text-gray-500">* Tidak Boleh ada spasi minimal 5 karakter</span>
</div>
<div className="space-y-2">
<FormLabel>Kata Sandi / Password</FormLabel>
<div className="text-red-500 italic text-sm">
<div className="flex">
<div className="mr-1">
<InformationCircleIcon className="w-5 h-5" />
</div>
<div>
<strong>Kata Sandi</strong> ini akan digunakan untuk login. Harap di ingat!
</div>
</div>
</div>
<div className="relative rounded-md shadow-sm">
<InputText hasTrailingIcon placeholder="Masukkan Kata Sandi" type="password" />
<div className="absolute inset-y-0 right-0 flex items-center">
<button
className="focus:ring-silacak-500 focus:border-silacak-500 h-full py-0 pl-2 pr-3 border-transparent bg-transparent text-gray-500 sm:text-sm rounded-md"
type="button"
>
<span className="sr-only">Tunjukkan / Sembunyikan Sandi</span>
<EyeIcon aria-hidden className="w-5 h-5 text-silacak-500" />
</button>
</div>
</div>
<span className="block text-gray-500">* Tidak Boleh ada spasi minimal 5 karakter</span>
</div>
<div className="space-y-4">
<p>
Tekan tombol <strong>Daftar</strong> untuk melanjutkan proses pendaftaran.
</p>
<Button block={true} className="w-full uppercase">
Daftar
</Button>
</div>
</div>
);
}
17 changes: 17 additions & 0 deletions components/registration/registration-info-message.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from "react";

export function RegistrationInfoMessage() {
return (
<div className="bg-green-100 p-3 border-l-4 border-green-500">
<div>
Mengalami kesulitan?{" "}
<a className="text-green-500 underline" href="#">
Hubungi Help Desk
</a>
</div>
<em>
Jam Operasional Helpdesk <strong>08:00 - 17:00</strong> WIB
</em>
</div>
);
}
21 changes: 21 additions & 0 deletions components/ui/board/content-board-subtitle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as React from "react";
import clsx from "clsx";

export type ContentBoardSubtitleProps = React.ComponentPropsWithoutRef<"h2">;

/**
* Subtitle used to label a form. This is to be used in conjunction with FormTitle.
* @param props
* @constructor
*/
export const ContentBoardSubtitle = React.forwardRef<HTMLHeadingElement, ContentBoardSubtitleProps>(
({ children, className, ...rest }, ref) => {
return (
<h2 className={clsx("text-center text-gray-700", className)} ref={ref} {...rest}>
{children}
</h2>
);
}
);

ContentBoardSubtitle.displayName = "ContentBoardSubtitle";
28 changes: 28 additions & 0 deletions components/ui/board/content-board-title.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import * as React from "react";
import clsx from "clsx";

export type ContentBoardTitleProps = React.ComponentPropsWithoutRef<"h1">;

/**
* Title element used to label a form.
* @param props
* @constructor
*/
export const ContentBoardTitle = React.forwardRef<HTMLHeadingElement, ContentBoardTitleProps>(
({ children, className, ...rest }, ref) => {
return (
<h1
className={clsx(
"form-title text-2xl uppercase text-center text-silacak-500 font-medium",
className
)}
ref={ref}
{...rest}
>
{children}
</h1>
);
}
);

ContentBoardTitle.displayName = "ContentBoardTitle";
29 changes: 29 additions & 0 deletions components/ui/board/content-board.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import * as React from "react";
import clsx from "clsx";

export type ContentBoardProps = React.ComponentPropsWithoutRef<"div">;

/**
* Display a white content board that can contains any content
* Note: By default, the board is not padded.
* @param props
* @constructor
*/
export const ContentBoard = React.forwardRef<HTMLDivElement, ContentBoardProps>(
({ children, className, ...rest }, ref) => {
return (
<div
className={clsx(
"content-board mx-auto max-w-2xl w-full bg-white border rounded-md border-gray-300",
className
)}
ref={ref}
{...rest}
>
{children}
</div>
);
}
);

ContentBoard.displayName = "ContentBoard";
2 changes: 2 additions & 0 deletions components/ui/button/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./primary-button";
export * from "./utils";
67 changes: 67 additions & 0 deletions components/ui/button/primary-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import * as React from "react";

import clsx from "clsx";
import { Spinner } from "../spinner";
import {
buttonBlockStyles,
ButtonProps,
buttonRoundedStyles,
buttonSizes,
disabledStyles,
primaryButtonColors,
renderButtonIcon,
} from "./utils";

/**
* Button component used for primary actions.
*
* @link https://tailwindui.com/components/application-ui/elements/buttons#component-80fd0d5ac7982f1a83b171bb0fb9e116
*/
export const PrimaryButton = React.forwardRef<HTMLButtonElement, ButtonProps>(
(
{
className,
style,
type,
block,
size = "md",
color = "green",
rounded,
icon,
iconPosition = "left",
isLoading,
loadingText = "Memuat...",
disabled,
children,
...rest
},
ref
) => (
<button
className={clsx(
buttonBlockStyles(block, iconPosition),
buttonSizes(size),
buttonRoundedStyles(rounded, size),
"items-center justify-center border border-transparent font-medium shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2",
primaryButtonColors(color),
disabledStyles,
className
)}
disabled={isLoading ?? disabled}
ref={ref}
style={style}
type={type ?? "button"}
{...rest}
>
{renderButtonIcon({
icon: isLoading ? Spinner : icon,
size,
additionalClasses: isLoading ? "animate-spin" : undefined,
iconPosition,
})}
{isLoading ? loadingText : children}
</button>
)
);

PrimaryButton.displayName = "PrimaryButton";
Loading

0 comments on commit b037f1e

Please sign in to comment.