From a6a4d4aafd2f131246335bc3812da12e918833d0 Mon Sep 17 00:00:00 2001 From: iqbalalayubbi Date: Sun, 18 Aug 2024 21:49:29 +0700 Subject: [PATCH 01/41] feat: slicing form design ui bb-9 --- apps/frontend/src/assets/css/auth.css | 109 ++++++++++++++++++ apps/frontend/src/assets/css/buttons.css | 13 +++ apps/frontend/src/assets/css/circle.css | 13 +++ apps/frontend/src/assets/css/scaffolding.css | 18 +++ apps/frontend/src/assets/css/styles.css | 3 + apps/frontend/src/assets/icons/eye.png | Bin 0 -> 575 bytes .../src/assets/img/auth-ilustration-left.svg | 25 ++++ .../src/assets/img/auth-ilustration-right.svg | 35 ++++++ apps/frontend/src/libs/components/app/app.tsx | 9 +- .../src/libs/components/button/button.tsx | 8 +- .../src/libs/components/input/input.tsx | 22 +++- .../src/libs/components/link/link.tsx | 11 +- apps/frontend/src/pages/auth/auth.tsx | 29 ++++- .../components/sign-up-form/sign-up-form.tsx | 59 ++++++++-- package.json | 1 + 15 files changed, 328 insertions(+), 27 deletions(-) create mode 100644 apps/frontend/src/assets/css/auth.css create mode 100644 apps/frontend/src/assets/css/buttons.css create mode 100644 apps/frontend/src/assets/css/circle.css create mode 100644 apps/frontend/src/assets/icons/eye.png create mode 100644 apps/frontend/src/assets/img/auth-ilustration-left.svg create mode 100644 apps/frontend/src/assets/img/auth-ilustration-right.svg diff --git a/apps/frontend/src/assets/css/auth.css b/apps/frontend/src/assets/css/auth.css new file mode 100644 index 000000000..061f0dcf6 --- /dev/null +++ b/apps/frontend/src/assets/css/auth.css @@ -0,0 +1,109 @@ +.auth-container { + display: flex; + width: 100vw; + height: 100vh; + background-color: var(--blue-background); +} + +.logo-container { + display: flex; + gap: 8px; + align-items: center; +} + +.form-container { + display: flex; + flex-basis: 40%; + flex-direction: column; + padding: 80px 160px; + margin: 16px; + font-family: var(--nunito-font); + background-color: white; + border-radius: 32px; +} + +.form-container .input-groups { + display: flex; + flex-direction: column; + gap: 16px; + margin: 24px 0; +} + +.form-container .auth-info { + font-family: inherit; + font-weight: 600; +} + +.form-container .title-form { + font-weight: 700; +} + +.auth-info .link-info { + color: #00c2fc; + text-decoration: none; +} + +.ilustration-container { + position: relative; + display: flex; + flex-basis: 60%; + align-items: center; + justify-content: center; + color: white; +} + +.ilustration-container .title { + font-size: 48px; +} + +.ilustration-container .img-left { + position: absolute; + left: 0; + z-index: 0; + width: 70%; + margin-top: -300px; + margin-left: -300px; +} + +.ilustration-container .img-right { + position: absolute; + right: 0; + bottom: 0; + z-index: 0; + width: 90%; + margin-right: -100px; + margin-bottom: -200px; +} + +.input-container { + display: flex; + flex-direction: column; + font-family: var(--nunito-font); +} + +.input-container .input-content { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 8px; + border: 1px solid #e0e0e0; + border-radius: 8px; +} + +.input-container .label { + margin-bottom: 8px; + font-family: inherit; + font-size: 16px; + font-weight: 600; +} + +.input-container .input { + width: 80%; + padding: 16px; + font-family: inherit; + border: none; +} + +.input-container .input:focus { + outline: none; +} diff --git a/apps/frontend/src/assets/css/buttons.css b/apps/frontend/src/assets/css/buttons.css new file mode 100644 index 000000000..b20ce12e1 --- /dev/null +++ b/apps/frontend/src/assets/css/buttons.css @@ -0,0 +1,13 @@ +.btn { + width: 100%; + padding: 16px 0; /* Mengganti em dengan rem */ + font-family: var(--nunito-font); + font-weight: 700; + color: white; + border: none; + border-radius: 32px; /* Mengganti em dengan rem */ +} + +.btn-dark { + background-color: var(--dark); +} diff --git a/apps/frontend/src/assets/css/circle.css b/apps/frontend/src/assets/css/circle.css new file mode 100644 index 000000000..902909613 --- /dev/null +++ b/apps/frontend/src/assets/css/circle.css @@ -0,0 +1,13 @@ +.circle { + width: 30px; + height: 30px; + border-radius: 100%; +} + +.circle-blue { + background: var(--primary-gradient); +} + +.circle-pink { + background: var(--pink-gradient); +} diff --git a/apps/frontend/src/assets/css/scaffolding.css b/apps/frontend/src/assets/css/scaffolding.css index 4bc32b520..55b3a881d 100644 --- a/apps/frontend/src/assets/css/scaffolding.css +++ b/apps/frontend/src/assets/css/scaffolding.css @@ -1,7 +1,25 @@ +@import url("https://fonts.googleapis.com/css2?family=Nunito:ital,wght@0,200..1000;1,200..1000&family=Righteous&family=Ubuntu:ital,wght@0,300;0,400;0,500;0,700;1,300;1,400;1,500;1,700&display=swap"); + * { box-sizing: border-box; } +:root { + --primary-gradient: linear-gradient( + 325deg, + hsl(184deg 100% 50%) 0%, + hsl(209deg 100% 50%) 100% + ); + --pink-gradient: linear-gradient( + 325deg, + hsl(338deg 100% 67%) 0%, + hsl(299deg 100% 72%) 100% + ); + --blue-background: #76acec; + --dark: #000000; + --nunito-font: "Nunito", sans-serif; +} + body { display: flex; flex-direction: column; diff --git a/apps/frontend/src/assets/css/styles.css b/apps/frontend/src/assets/css/styles.css index 098c8fc0e..2c85e2188 100644 --- a/apps/frontend/src/assets/css/styles.css +++ b/apps/frontend/src/assets/css/styles.css @@ -1 +1,4 @@ @import url("./scaffolding.css"); +@import url("./auth.css"); +@import url("./circle.css"); +@import url("./buttons.css"); diff --git a/apps/frontend/src/assets/icons/eye.png b/apps/frontend/src/assets/icons/eye.png new file mode 100644 index 0000000000000000000000000000000000000000..650712c5ca4d72fcf51ec4869551c3bf51537134 GIT binary patch literal 575 zcmV-F0>J%=P){0i*%V3i4Hyn_I&cZxfCG^CoE1^PKqkk4 zW_Bd)zJ1!&uB6m`{QF^D15_#%7t=F@b3SphtZ2XAN0`Uc>2&m`1B7^>NiU2T63k|^ zVVcoCR=BR~l*{EFmJ=Z-K^O7}5{t6kZj0FaVk72Nd@g4|^37&5LHY&AlEm}*ypL>1 zGN2yU;y^}Nw{ciptyWvR-L510D3i(5!Z2K>X0TeV5)wuRa8Z*(_s;W4LLBxUb+n-d zePZcD-}QR^mU=}1GYU`At}(hKMa$|5@i3dsKJcoz79DG(1X~kd7uVHF%b+2IZB4GD zm1V%xX+xAPu@y8 + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/frontend/src/assets/img/auth-ilustration-right.svg b/apps/frontend/src/assets/img/auth-ilustration-right.svg new file mode 100644 index 000000000..0abf464e0 --- /dev/null +++ b/apps/frontend/src/assets/img/auth-ilustration-right.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/frontend/src/libs/components/app/app.tsx b/apps/frontend/src/libs/components/app/app.tsx index e708cbc79..2b6915af9 100644 --- a/apps/frontend/src/libs/components/app/app.tsx +++ b/apps/frontend/src/libs/components/app/app.tsx @@ -1,5 +1,6 @@ -import reactLogo from "~/assets/img/react.svg"; -import { Link, RouterOutlet } from "~/libs/components/components.js"; +// import reactLogo from "~/assets/img/react.svg"; +// import { Link, RouterOutlet } from "~/libs/components/components.js"; +import { RouterOutlet } from "~/libs/components/components.js"; import { AppRoute } from "~/libs/enums/enums.js"; import { useAppDispatch, @@ -27,7 +28,7 @@ const App: React.FC = () => { return ( <> - logo + {/* logo
  • @@ -40,7 +41,7 @@ const App: React.FC = () => { Sign up
-

Current path: {pathname}

+

Current path: {pathname}

*/}
diff --git a/apps/frontend/src/libs/components/button/button.tsx b/apps/frontend/src/libs/components/button/button.tsx index 6c6cea05d..ce81e46a7 100644 --- a/apps/frontend/src/libs/components/button/button.tsx +++ b/apps/frontend/src/libs/components/button/button.tsx @@ -1,11 +1,17 @@ type Properties = { + className: string; label: string; type?: "button" | "submit"; }; const Button: React.FC = ({ + className, label, type = "button", -}: Properties) => ; +}: Properties) => ( + +); export { Button }; diff --git a/apps/frontend/src/libs/components/input/input.tsx b/apps/frontend/src/libs/components/input/input.tsx index 108a8eedc..85f7d943d 100644 --- a/apps/frontend/src/libs/components/input/input.tsx +++ b/apps/frontend/src/libs/components/input/input.tsx @@ -8,8 +8,11 @@ import { import { useFormController } from "~/libs/hooks/hooks.js"; type Properties = { + className: string; control: Control; errors: FieldErrors; + hasIcon?: string; + iconSrc?: string; label: string; name: FieldPath; placeholder?: string; @@ -17,8 +20,11 @@ type Properties = { }; const Input = ({ + className, control, errors, + hasIcon, + iconSrc, label, name, placeholder = "", @@ -30,10 +36,18 @@ const Input = ({ const hasError = Boolean(error); return ( -
); diff --git a/apps/frontend/src/pages/auth/components/sign-in-form/sign-in-form.tsx b/apps/frontend/src/pages/auth/components/sign-in-form/sign-in-form.tsx index f014d976b..583f4507f 100644 --- a/apps/frontend/src/pages/auth/components/sign-in-form/sign-in-form.tsx +++ b/apps/frontend/src/pages/auth/components/sign-in-form/sign-in-form.tsx @@ -8,7 +8,7 @@ const SignInForm: React.FC = () => ( <>

Sign In

-
); diff --git a/apps/frontend/src/libs/components/input/input.tsx b/apps/frontend/src/libs/components/input/input.tsx index d42a3b721..42c27b8fa 100644 --- a/apps/frontend/src/libs/components/input/input.tsx +++ b/apps/frontend/src/libs/components/input/input.tsx @@ -17,6 +17,7 @@ type Properties = { label: string; name: FieldPath; placeholder?: string; + required?: string; type?: "email" | "password" | "text"; }; @@ -30,6 +31,7 @@ const Input = ({ label, name, placeholder = "", + required, type = "text", }: Properties): JSX.Element => { const { field } = useFormController({ control, name }); @@ -45,6 +47,7 @@ const Input = ({ className="input" {...field} placeholder={placeholder} + required={Boolean(required) || true} type={type} /> {hasError && {error as string}} diff --git a/apps/frontend/src/modules/auth/slices/auth.slice.ts b/apps/frontend/src/modules/auth/slices/auth.slice.ts index ec2a9a9aa..9ff7647a7 100644 --- a/apps/frontend/src/modules/auth/slices/auth.slice.ts +++ b/apps/frontend/src/modules/auth/slices/auth.slice.ts @@ -1,4 +1,5 @@ import { createSlice } from "@reduxjs/toolkit"; +import { UserSignUpResponseDto as DataUser } from "shared"; import { DataStatus } from "~/libs/enums/enums.js"; import { type ValueOf } from "~/libs/types/types.js"; @@ -7,10 +8,15 @@ import { signUp } from "./actions.js"; type State = { dataStatus: ValueOf; + user: DataUser | null; }; const initialState: State = { dataStatus: DataStatus.IDLE, + user: { + email: "", + id: 0, + }, }; const { actions, name, reducer } = createSlice({ @@ -18,8 +24,9 @@ const { actions, name, reducer } = createSlice({ builder.addCase(signUp.pending, (state) => { state.dataStatus = DataStatus.PENDING; }); - builder.addCase(signUp.fulfilled, (state) => { + builder.addCase(signUp.fulfilled, (state, action) => { state.dataStatus = DataStatus.FULFILLED; + state.user = action.payload; }); builder.addCase(signUp.rejected, (state) => { state.dataStatus = DataStatus.REJECTED; diff --git a/apps/frontend/src/assets/css/auth.css b/apps/frontend/src/pages/auth/assets/css/auth.css similarity index 100% rename from apps/frontend/src/assets/css/auth.css rename to apps/frontend/src/pages/auth/assets/css/auth.css diff --git a/apps/frontend/src/pages/auth/assets/img/auth-ilustration-left.svg b/apps/frontend/src/pages/auth/assets/img/auth-ilustration-left.svg new file mode 100644 index 000000000..4d4b71fab --- /dev/null +++ b/apps/frontend/src/pages/auth/assets/img/auth-ilustration-left.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/frontend/src/pages/auth/assets/img/auth-ilustration-right.svg b/apps/frontend/src/pages/auth/assets/img/auth-ilustration-right.svg new file mode 100644 index 000000000..0abf464e0 --- /dev/null +++ b/apps/frontend/src/pages/auth/assets/img/auth-ilustration-right.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/frontend/src/pages/auth/auth.tsx b/apps/frontend/src/pages/auth/auth.tsx index 8f169807d..0241b1b45 100644 --- a/apps/frontend/src/pages/auth/auth.tsx +++ b/apps/frontend/src/pages/auth/auth.tsx @@ -10,6 +10,7 @@ import { import { actions as authActions } from "~/modules/auth/auth.js"; import { type UserSignUpRequestDto } from "~/modules/users/users.js"; +import "./assets/css/auth.css"; import { SignInForm, SignUpForm } from "./components/components.js"; const Auth: React.FC = () => { diff --git a/apps/frontend/src/pages/auth/components/sign-up-form/sign-up-form.tsx b/apps/frontend/src/pages/auth/components/sign-up-form/sign-up-form.tsx index 2066c457b..0822a65d6 100644 --- a/apps/frontend/src/pages/auth/components/sign-up-form/sign-up-form.tsx +++ b/apps/frontend/src/pages/auth/components/sign-up-form/sign-up-form.tsx @@ -29,9 +29,6 @@ const SignUpForm: React.FC = ({ onSubmit }: Properties) => { [handleSubmit, onSubmit], ); - // const [showPassword, setShowPassword] = useState(false); - // const [passwordIcon, setPasswordIcon] = useState(slashEyeIcon) - // const [confirmPasswordIcon, setConfirmPasswordIcon] = useState(slashEyeIcon) type InputType = { icon: string; type: "password" | "text"; From eef6fb32f5f1ede8e2de283ceccf88a3a0ceaf4d Mon Sep 17 00:00:00 2001 From: iqbalalayubbi Date: Mon, 19 Aug 2024 21:37:57 +0700 Subject: [PATCH 05/41] feat: make validation confirm password bb-9 --- apps/frontend/src/assets/css/scaffolding.css | 4 ++ .../src/assets/img/auth-ilustration-left.svg | 25 ------- .../src/assets/img/auth-ilustration-right.svg | 35 ---------- apps/frontend/src/assets/img/react.svg | 1 - .../src/libs/components/button/button.tsx | 9 ++- .../src/libs/components/input/input.tsx | 24 ++++++- .../auth}/assets/icons/eye-slash.svg | 0 .../src/{ => pages/auth}/assets/icons/eye.svg | 0 apps/frontend/src/pages/auth/auth.tsx | 4 +- .../components/sign-up-form/sign-up-form.tsx | 66 ++++++++++++++----- 10 files changed, 83 insertions(+), 85 deletions(-) delete mode 100644 apps/frontend/src/assets/img/auth-ilustration-left.svg delete mode 100644 apps/frontend/src/assets/img/auth-ilustration-right.svg delete mode 100644 apps/frontend/src/assets/img/react.svg rename apps/frontend/src/{ => pages/auth}/assets/icons/eye-slash.svg (100%) rename apps/frontend/src/{ => pages/auth}/assets/icons/eye.svg (100%) diff --git a/apps/frontend/src/assets/css/scaffolding.css b/apps/frontend/src/assets/css/scaffolding.css index 81a43ed91..c13668f5e 100644 --- a/apps/frontend/src/assets/css/scaffolding.css +++ b/apps/frontend/src/assets/css/scaffolding.css @@ -65,3 +65,7 @@ body { .btn-dark { background-color: var(--dark); } + +.btn:disabled { + background-color: #e0e0e0; +} diff --git a/apps/frontend/src/assets/img/auth-ilustration-left.svg b/apps/frontend/src/assets/img/auth-ilustration-left.svg deleted file mode 100644 index 4d4b71fab..000000000 --- a/apps/frontend/src/assets/img/auth-ilustration-left.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/frontend/src/assets/img/auth-ilustration-right.svg b/apps/frontend/src/assets/img/auth-ilustration-right.svg deleted file mode 100644 index 0abf464e0..000000000 --- a/apps/frontend/src/assets/img/auth-ilustration-right.svg +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/frontend/src/assets/img/react.svg b/apps/frontend/src/assets/img/react.svg deleted file mode 100644 index 6c87de9bb..000000000 --- a/apps/frontend/src/assets/img/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/apps/frontend/src/libs/components/button/button.tsx b/apps/frontend/src/libs/components/button/button.tsx index adbf3cb62..03af5005c 100644 --- a/apps/frontend/src/libs/components/button/button.tsx +++ b/apps/frontend/src/libs/components/button/button.tsx @@ -1,6 +1,7 @@ type Properties = { className: string; clickBtn?: (event_: React.BaseSyntheticEvent) => void; + isDisabled?: boolean; label: string; type?: "button" | "submit"; }; @@ -8,10 +9,16 @@ type Properties = { const Button: React.FC = ({ className, clickBtn, + isDisabled, label, type = "button", }: Properties) => ( - ); diff --git a/apps/frontend/src/libs/components/input/input.tsx b/apps/frontend/src/libs/components/input/input.tsx index 42c27b8fa..58ca86d85 100644 --- a/apps/frontend/src/libs/components/input/input.tsx +++ b/apps/frontend/src/libs/components/input/input.tsx @@ -5,7 +5,7 @@ import { type FieldValues, } from "react-hook-form"; -import { useFormController } from "~/libs/hooks/hooks.js"; +import { useCallback, useFormController } from "~/libs/hooks/hooks.js"; type Properties = { className: string; @@ -14,6 +14,7 @@ type Properties = { errors: FieldErrors; hasIcon?: string; iconSrc?: string; + inputChange?: (event_: React.BaseSyntheticEvent) => void; label: string; name: FieldPath; placeholder?: string; @@ -28,6 +29,7 @@ const Input = ({ errors, hasIcon, iconSrc, + inputChange, label, name, placeholder = "", @@ -39,6 +41,16 @@ const Input = ({ const error = errors[name]?.message; const hasError = Boolean(error); + const handleChange = useCallback( + (event: React.BaseSyntheticEvent) => { + field.onChange(event); + if (inputChange) { + inputChange(event); + } + }, + [field, inputChange], + ); + return (