Skip to content

Commit d34566e

Browse files
authored
[promote-production]: May 5, 10:38 PM (#43)
* chore: Update GitHub Actions workflow to specify node version for code checkout and Docker login (#37) * chore: updating node version GitHub action (#39) * [promote-production]: May 3, 10:50 AM (#24) * [Client]: Refactoring Register UI & Adding more UI components (#17) * [client]: refactoring register ui * Add Zustand state management library * [Client]: Adding more UI components (#19) * Update README.md * fixing build issues * Update README.md * [Client]: UI Adjustments (#21) * [client]: integrating sign-in with api (#22) * Update README.md * chore: Update GitHub Actions workflow to specify node version for code checkout and Docker login * [client]: updating favicon (#41) * [client]: updating login and register forms (#42)
1 parent 17cd67e commit d34566e

File tree

10 files changed

+150
-104
lines changed

10 files changed

+150
-104
lines changed

client/index.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html lang="en" class="h-full bg-white">
33
<head>
44
<meta charset="UTF-8" />
5-
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
5+
<link rel="icon" href="/favicon.ico" />
66
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
77
<title>
88
Job Portal

client/public/favicon.ico

33.7 KB
Binary file not shown.

client/public/vite.svg

-1
This file was deleted.

client/src/forms/auth/LoginForm/LoginForm.tsx

+86-76
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,106 @@
11
import { Link } from "react-router-dom";
22
import useLoginForm from "./useLoginForm";
33
import FieldError from "@/components/core-ui/FieldError";
4+
import Alert from "@/components/core-ui/Alert";
45

56
const LoginForm = () => {
6-
const { form } = useLoginForm();
7+
const { form, loginError } = useLoginForm();
78

89
return (
9-
<form className="space-y-6" onSubmit={form.handleSubmit} noValidate>
10-
<div>
11-
<label
12-
htmlFor="email"
13-
className="block text-sm font-medium leading-6 text-gray-900"
14-
>
15-
Email address
16-
<span className="text-red-500">*</span>
17-
</label>
18-
<div className="mt-2">
19-
<input
20-
id="email"
21-
name="email"
22-
type="email"
23-
autoComplete="email"
24-
required
25-
className="block w-full rounded-md border-0 py-1.5 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
26-
readOnly={form.isSubmitting}
27-
value={form.values.email}
28-
onChange={form.handleChange}
29-
/>
30-
{form.errors.email && <FieldError error={form.errors.email} />}
10+
<>
11+
{loginError && (
12+
<div className="mb-4">
13+
<Alert type="error" message={loginError} />
3114
</div>
32-
</div>
33-
34-
<div>
35-
<label
36-
htmlFor="password"
37-
className="block text-sm font-medium leading-6 text-gray-900"
38-
>
39-
Password
40-
<span className="text-red-500">*</span>
41-
</label>
42-
<div className="mt-2">
43-
<input
44-
id="password"
45-
name="password"
46-
type="password"
47-
autoComplete="current-password"
48-
required
49-
className="block w-full rounded-md border-0 py-1.5 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
50-
readOnly={form.isSubmitting}
51-
value={form.values.password}
52-
onChange={form.handleChange}
53-
/>
54-
{form.errors.password && <FieldError error={form.errors.password} />}
15+
)}
16+
<form className="space-y-6" onSubmit={form.handleSubmit} noValidate>
17+
<div>
18+
<label
19+
htmlFor="email"
20+
className="block text-sm font-medium leading-6 text-gray-900"
21+
>
22+
Email address
23+
<span className="text-red-500">*</span>
24+
</label>
25+
<div className="mt-2">
26+
<input
27+
id="email"
28+
name="email"
29+
type="email"
30+
autoComplete="email"
31+
required
32+
className="block w-full rounded-md border-0 py-1.5 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
33+
readOnly={form.isSubmitting}
34+
value={form.values.email}
35+
onChange={form.handleChange}
36+
/>
37+
{form.errors.email && <FieldError error={form.errors.email} />}
38+
</div>
5539
</div>
56-
</div>
5740

58-
<div className="flex items-center justify-between">
59-
<div className="flex items-center">
60-
<input
61-
id="remember-me"
62-
name="remember-me"
63-
type="checkbox"
64-
className="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-600"
65-
/>
41+
<div>
6642
<label
67-
htmlFor="remember-me"
68-
className="ml-3 block text-sm leading-6 text-gray-700"
43+
htmlFor="password"
44+
className="block text-sm font-medium leading-6 text-gray-900"
6945
>
70-
Remember me
46+
Password
47+
<span className="text-red-500">*</span>
7148
</label>
49+
<div className="mt-2">
50+
<input
51+
id="password"
52+
name="password"
53+
type="password"
54+
autoComplete="current-password"
55+
required
56+
className="block w-full rounded-md border-0 py-1.5 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
57+
readOnly={form.isSubmitting}
58+
value={form.values.password}
59+
onChange={form.handleChange}
60+
/>
61+
{form.errors.password && (
62+
<FieldError error={form.errors.password} />
63+
)}
64+
</div>
7265
</div>
7366

74-
<div className="text-sm leading-6">
75-
<Link
76-
to="/forgot-password"
77-
className="font-semibold text-indigo-600 hover:text-indigo-500"
78-
>
79-
Forgot password?
80-
</Link>
67+
<div className="flex items-center justify-between">
68+
<div className="flex items-center">
69+
<input
70+
id="remember-me"
71+
name="remember-me"
72+
type="checkbox"
73+
className="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-600"
74+
/>
75+
<label
76+
htmlFor="remember-me"
77+
className="ml-3 block text-sm leading-6 text-gray-700"
78+
>
79+
Remember me
80+
</label>
81+
</div>
82+
83+
<div className="text-sm leading-6">
84+
<Link
85+
to="/forgot-password"
86+
className="font-semibold text-indigo-600 hover:text-indigo-500"
87+
>
88+
Forgot password?
89+
</Link>
90+
</div>
8191
</div>
82-
</div>
8392

84-
<div>
85-
<button
86-
type="submit"
87-
className="flex w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
88-
disabled={form.isSubmitting}
89-
>
90-
Sign in
91-
</button>
92-
</div>
93-
</form>
93+
<div>
94+
<button
95+
type="submit"
96+
className="flex w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
97+
disabled={form.isSubmitting}
98+
>
99+
Sign in
100+
</button>
101+
</div>
102+
</form>
103+
</>
94104
);
95105
};
96106

client/src/forms/auth/LoginForm/useLoginForm.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { ILoginPayload } from "@/interfaces/models";
22
import { useAuth } from "@/providers";
33
import useAuthStore from "@/stores/auth.store";
44
import { useFormik } from "formik";
5+
import { useEffect } from "react";
56
import { useNavigate } from "react-router-dom";
67
import * as Yup from "yup";
78

@@ -13,8 +14,10 @@ const FORM_INITIAL_VALUES = {
1314
const useLoginForm = () => {
1415
const { login: setLogin } = useAuth();
1516
const navigate = useNavigate();
16-
const { login } = useAuthStore((state) => ({
17+
const { loginError, login, clearLoginError } = useAuthStore((state) => ({
1718
login: state.login,
19+
loginError: state.loginError,
20+
clearLoginError: state.clearLoginError,
1821
}));
1922

2023
const validationSchema = Yup.object({
@@ -50,8 +53,15 @@ const useLoginForm = () => {
5053
},
5154
});
5255

56+
useEffect(() => {
57+
return () => {
58+
clearLoginError();
59+
};
60+
}, [clearLoginError]);
61+
5362
return {
5463
form,
64+
loginError,
5565
};
5666
};
5767

client/src/forms/auth/RegisterForm/RegisterForm.tsx

+6-7
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,27 @@ import useRegisterForm from "./useRegisterForm";
33
import TermsAndConditionsDialog from "@/components/dialogs/TermsAndConditionsDialog";
44
import FieldError from "@/components/core-ui/FieldError";
55
import Alert from "@/components/core-ui/Alert";
6-
import { RequestStatus } from "@/enums";
76

87
const RegisterForm = () => {
98
const {
109
form,
11-
registerStatus,
12-
registerMessage,
10+
registerSuccessMessage,
11+
registerErrorMessage,
1312
termsConditionsModalOpen,
1413
handleOnOpenTermsConditionsModal,
1514
handleOnCloseTermsConditionsModal,
1615
} = useRegisterForm();
1716

1817
return (
1918
<>
20-
{registerStatus === RequestStatus.SUCCESS && (
19+
{registerSuccessMessage && (
2120
<div className="mb-4">
22-
<Alert type="success" message={registerMessage} />
21+
<Alert type="success" message={registerSuccessMessage} />
2322
</div>
2423
)}
25-
{registerStatus === RequestStatus.ERROR && (
24+
{registerErrorMessage && (
2625
<div className="mb-4">
27-
<Alert type="error" message={registerMessage} />
26+
<Alert type="error" message={registerErrorMessage} />
2827
</div>
2928
)}
3029
<form onSubmit={form.handleSubmit} className="space-y-6" noValidate>

client/src/forms/auth/RegisterForm/useRegisterForm.ts

+15-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { IRegisterPayload } from "@/interfaces/models";
22
import useAuthStore from "@/stores/auth.store";
33
import { useFormik } from "formik";
4+
import { useEffect } from "react";
45
import * as Yup from "yup";
56

67
const FORM_INITIAL_VALUES = {
@@ -13,17 +14,19 @@ const FORM_INITIAL_VALUES = {
1314

1415
const useRegisterForm = () => {
1516
const {
16-
registerStatus,
17-
registerMessage,
17+
registerSuccessMessage,
18+
registerErrorMessage,
1819
termsConditionsModalOpen,
1920
setTermsConditionsModalOpen,
2021
register,
22+
clearRegisterMessages,
2123
} = useAuthStore((state) => ({
22-
registerStatus: state.registerStatus,
23-
registerMessage: state.registerMessage,
24+
registerSuccessMessage: state.registerSuccessMessage,
25+
registerErrorMessage: state.registerErrorMessage,
2426
termsConditionsModalOpen: state.termsConditionsModalOpen,
2527
setTermsConditionsModalOpen: state.setTermsConditionsModalOpen,
2628
register: state.register,
29+
clearRegisterMessages: state.clearRegisterMessages,
2730
}));
2831

2932
const validationSchema = Yup.object({
@@ -76,10 +79,16 @@ const useRegisterForm = () => {
7679
setTermsConditionsModalOpen(false);
7780
};
7881

82+
useEffect(() => {
83+
return () => {
84+
clearRegisterMessages();
85+
};
86+
}, [clearRegisterMessages]);
87+
7988
return {
8089
form,
81-
registerStatus,
82-
registerMessage,
90+
registerSuccessMessage,
91+
registerErrorMessage,
8392
termsConditionsModalOpen,
8493
handleOnOpenTermsConditionsModal,
8594
handleOnCloseTermsConditionsModal,
+5-3
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
import { IModels } from "..";
2-
import { IRequestStatus } from "../http-client/IRequestStatus";
32
import { ILoginResponse } from "../models";
43

54
export interface IAuthStore {
65
termsConditionsModalOpen: boolean;
76
setTermsConditionsModalOpen: (value: boolean) => void;
87

98
isLogging: boolean;
9+
loginError: string;
1010
login: (
1111
payload: IModels.ILoginPayload,
1212
options?: any
1313
) => Promise<ILoginResponse>;
14+
clearLoginError: () => void;
1415

15-
registerStatus: IRequestStatus;
16-
registerMessage: string;
16+
registerSuccessMessage?: string;
17+
registerErrorMessage?: string;
1718
register: (payload: IModels.IRegisterPayload, options?: any) => Promise<void>;
19+
clearRegisterMessages: () => void;
1820
}

0 commit comments

Comments
 (0)