Skip to content

Commit 1731a1b

Browse files
drbarzagaAlabao
andauthored
[promote-production] May 4, 2:12 PM (#30)
* [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 * Readme install changes and .gitignore config for IDEs. (#25) * Add .gitignore ides config folders * Add to readme yarn install version and one npm command. * [client-server]: general adjustments (#28) * Update README.md (#29) --------- Co-authored-by: Rubier Sorio <[email protected]>
1 parent 3ca0d8d commit 1731a1b

File tree

27 files changed

+217
-81
lines changed

27 files changed

+217
-81
lines changed

client/src/App.tsx

+30-21
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,47 @@
11
import { lazy } from "react";
2-
import { PrivateRoute } from "@/components/routers";
32
import HomePage from "@/pages/HomePage";
4-
import { BrowserRouter, Route, Routes } from "react-router-dom";
3+
import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom";
54
import AppWrapper from "./AppWrapper";
5+
import { useAuth } from "./providers";
66

77
const LoginPage = lazy(() => import("@/pages/AuthPages/LoginPage"));
88
const RegisterPage = lazy(() => import("@/pages/AuthPages/RegisterPage"));
99
const ForgotPasswordPage = lazy(
1010
() => import("@/pages/AuthPages/ForgotPasswordPage")
1111
);
12+
const MyJobsPage = lazy(() => import("@/pages/MyJobsPage"));
13+
const SavedJobsPage = lazy(() => import("@/pages/SavedJobsPage"));
14+
const MessagesPage = lazy(() => import("@/pages/MessagesPage"));
15+
const ProfilePage = lazy(() => import("@/pages/ProfilePage"));
1216

1317
function App() {
18+
const { isAuthenticated } = useAuth();
1419
return (
1520
<BrowserRouter>
16-
<Routes>
17-
<Route element={<AppWrapper />}>
18-
{/* Public routes */}
19-
<Route path="/" element={<HomePage />} />
20-
<Route path="/login" element={<LoginPage />} />
21-
<Route path="/register" element={<RegisterPage />} />
22-
<Route path="/forgot-password" element={<ForgotPasswordPage />} />
23-
24-
{/* Private route using PrivateRoute component */}
25-
<Route path="/" element={<PrivateRoute />}>
26-
{/* <Route path="/" element={<HomePage />} /> */}
27-
<Route path="/my-jobs" element={<div>My Jobs</div>} />
28-
<Route path="/saved-jobs" element={<div>Saved Jobs</div>} />
29-
<Route path="/messages" element={<div>Messages</div>} />
21+
{isAuthenticated ? (
22+
<Routes>
23+
<Route path="/" element={<AppWrapper />}>
24+
<Route index element={<HomePage />} />
25+
<Route path="/my-jobs" element={<MyJobsPage />} />
26+
<Route path="/saved-jobs" element={<SavedJobsPage />} />
27+
<Route path="/messages" element={<MessagesPage />} />
28+
<Route path="/profile" element={<ProfilePage />} />
29+
<Route path="/login" element={<Navigate to="/" />} />
30+
<Route path="/register" element={<Navigate to="/" />} />
31+
<Route path="/forgot-password" element={<Navigate to="/" />} />
3032
</Route>
31-
32-
{/* 404 route */}
33-
<Route path="*" element={<div>Not found page!</div>} />
34-
</Route>
35-
</Routes>
33+
</Routes>
34+
) : (
35+
<Routes>
36+
<Route path="/" element={<AppWrapper />}>
37+
<Route index element={<HomePage />} />
38+
<Route path="/login" element={<LoginPage />} />
39+
<Route path="/register" element={<RegisterPage />} />
40+
<Route path="/forgot-password" element={<ForgotPasswordPage />} />
41+
<Route path="*" element={<Navigate to="/login" />} />
42+
</Route>
43+
</Routes>
44+
)}
3645
</BrowserRouter>
3746
);
3847
}

client/src/components/layouts/portal/PortalLayout.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const PortalLayout: FC<Props> = ({ title, children }) => {
1515
<div className="flex flex-col bg-gray-50">
1616
<Header />
1717

18-
<div className="mx-auto flex w-full items-start gap-x-8 px-4 py-10 sm:px-6 lg:px-8">
18+
<div className="mx-auto flex w-full items-start gap-x-8 px-4 py-10 sm:px-6 lg:px-8 h-full">
1919
{children}
2020
</div>
2121

client/src/components/layouts/portal/components/Footer/Footer.tsx

+9-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,15 @@ const Footer = () => {
8080
</div>
8181
<div className="mt-8 md:order-1 md:mt-0">
8282
<p className="text-center text-xs leading-5 text-gray-500">
83-
&copy; {new Date().getFullYear()} Job Portal. All rights reserved.
83+
&copy; {new Date().getFullYear()} Job Portal. Made with ❤️ by all
84+
the{" "}
85+
<a
86+
href="https://github.com/drbarzaga/JobPortal?tab=readme-ov-file#our-contributors-"
87+
className="font-semibold text-indigo-600 hover:text-gray-900"
88+
target="_blank"
89+
>
90+
Contributors
91+
</a>
8492
</p>
8593
</div>
8694
</div>

client/src/components/layouts/portal/components/Header/Header.tsx

+64-30
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@ import {
55
XMarkIcon,
66
HomeIcon,
77
BriefcaseIcon,
8-
DocumentTextIcon,
9-
BookmarkIcon,
108
ChatBubbleLeftRightIcon,
119
UserIcon,
1210
Cog8ToothIcon,
1311
ArrowLeftStartOnRectangleIcon,
12+
BookmarkIcon,
1413
} from "@heroicons/react/24/outline";
1514
import { Dialog, Menu, Transition } from "@headlessui/react";
1615
import { useAuth } from "@/providers";
@@ -24,11 +23,10 @@ const Header = () => {
2423
const navigation = useMemo(() => {
2524
if (isAuthenticated) {
2625
return [
27-
{ name: "Home", href: "#", icon: HomeIcon },
28-
{ name: "Find Jobs", href: "#", icon: BriefcaseIcon },
29-
{ name: "My Jobs", href: "#", icon: DocumentTextIcon },
30-
{ name: "Saved Jobs", href: "#", icon: BookmarkIcon },
31-
{ name: "Messages", href: "#", icon: ChatBubbleLeftRightIcon },
26+
{ name: "Home", href: "/", icon: HomeIcon },
27+
{ name: "My Jobs", href: "/my-jobs", icon: BriefcaseIcon },
28+
{ name: "Saved Jobs", href: "/saved-jobs", icon: BookmarkIcon },
29+
{ name: "Messages", href: "/messages", icon: ChatBubbleLeftRightIcon },
3230
];
3331
}
3432

@@ -56,14 +54,18 @@ const Header = () => {
5654
</div>
5755
<div className="hidden lg:flex lg:gap-x-12">
5856
{navigation.map((item) => (
59-
<a
57+
<Link
6058
key={item.name}
61-
href={item.href}
62-
className="text-sm font-semibold leading-6 text-gray-900 flex items-center gap-x-2"
59+
to={item.href}
60+
className={`text-sm font-semibold leading-6 text-gray-900 flex items-center gap-x-2 ${
61+
window.location.pathname === item.href
62+
? "text-indigo-600"
63+
: "hover:text-indigo-600"
64+
}`}
6365
>
6466
{item.icon && <item.icon className="h-6 w-6" />}
6567
{item.name}
66-
</a>
68+
</Link>
6769
))}
6870
</div>
6971
{isAuthenticated ? (
@@ -191,14 +193,10 @@ const Header = () => {
191193
<div className="fixed inset-0 z-10" />
192194
<Dialog.Panel className="fixed inset-y-0 right-0 z-10 w-full overflow-y-auto bg-white px-6 py-6 sm:max-w-sm sm:ring-1 sm:ring-gray-900/10">
193195
<div className="flex items-center justify-between">
194-
<a href="#" className="-m-1.5 p-1.5">
195-
<span className="sr-only">Your Company</span>
196-
<img
197-
className="h-8 w-auto"
198-
src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=600"
199-
alt=""
200-
/>
201-
</a>
196+
<div className="-m-1.5 p-1.5">
197+
<span className="sr-only">JobPortal</span>
198+
<Logo />
199+
</div>
202200
<button
203201
type="button"
204202
className="-m-2.5 rounded-md p-2.5 text-gray-700"
@@ -210,24 +208,60 @@ const Header = () => {
210208
</div>
211209
<div className="mt-6 flow-root">
212210
<div className="-my-6 divide-y divide-gray-500/10">
213-
<div className="space-y-2 py-6">
211+
<div className="">
214212
{navigation.map((item) => (
215-
<a
213+
<Link
216214
key={item.name}
217-
href={item.href}
218-
className="-mx-3 block rounded-lg px-3 py-2 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50"
215+
to={item.href}
216+
className={`-mx-3 block rounded-lg px-3 py-2 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50 ${
217+
window.location.pathname === item.href
218+
? "text-indigo-600"
219+
: ""
220+
}`}
219221
>
220222
{item.name}
221-
</a>
223+
</Link>
222224
))}
223225
</div>
224226
<div className="py-6">
225-
<a
226-
href="#"
227-
className="-mx-3 block rounded-lg px-3 py-2.5 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50"
228-
>
229-
Log in
230-
</a>
227+
{!isAuthenticated ? (
228+
<>
229+
<Link
230+
to="/login"
231+
className="-mx-3 block rounded-lg px-3 py-2.5 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50"
232+
>
233+
Log in
234+
</Link>
235+
<Link
236+
to="/register"
237+
className="-mx-3 block rounded-lg px-3 py-2.5 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50"
238+
>
239+
Sign up
240+
</Link>
241+
</>
242+
) : (
243+
<>
244+
<Link
245+
to="/profile"
246+
className="-mx-3 block rounded-lg px-3 py-2.5 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50"
247+
>
248+
Profile
249+
</Link>
250+
<Link
251+
to="/register"
252+
className="-mx-3 block rounded-lg px-3 py-2.5 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50"
253+
>
254+
Settings
255+
</Link>
256+
<Link
257+
to="/"
258+
className="-mx-3 block rounded-lg px-3 py-2.5 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50"
259+
onClick={logout}
260+
>
261+
Sign out
262+
</Link>
263+
</>
264+
)}
231265
</div>
232266
</div>
233267
</div>

client/src/components/routers/PrivateRoute.tsx

-9
This file was deleted.

client/src/components/routers/index.ts

-1
This file was deleted.

client/src/core/http.service.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import axios, { AxiosInstance, AxiosResponse, AxiosRequestConfig } from "axios";
33

44
import { HttpMethod } from "@/enums";
55
import { IService } from "@/interfaces";
6+
import StorageService from "./storage.service";
67

78
export default class HttpService {
89
private http: AxiosInstance;
@@ -18,7 +19,7 @@ export default class HttpService {
1819

1920
// Get authorization token from cookies
2021
private get getAuthorization() {
21-
const accessToken = Cookies.get("AccessToken") || "";
22+
const accessToken = StorageService.getItem("access_token") || "";
2223
return accessToken ? { Authorization: `Bearer ${accessToken}` } : {};
2324
}
2425

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

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Link } from "react-router-dom";
22
import useLoginForm from "./useLoginForm";
3+
import FieldError from "@/components/core-ui/FieldError";
34

45
const LoginForm = () => {
56
const { form } = useLoginForm();
@@ -26,6 +27,7 @@ const LoginForm = () => {
2627
value={form.values.email}
2728
onChange={form.handleChange}
2829
/>
30+
{form.errors.email && <FieldError error={form.errors.email} />}
2931
</div>
3032
</div>
3133

@@ -49,6 +51,7 @@ const LoginForm = () => {
4951
value={form.values.password}
5052
onChange={form.handleChange}
5153
/>
54+
{form.errors.password && <FieldError error={form.errors.password} />}
5255
</div>
5356
</div>
5457

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ const useLoginForm = () => {
3838
email: values.email,
3939
password: values.password,
4040
};
41-
const { token } = await login(payload);
42-
setLogin(token);
41+
const { token, user } = await login(payload);
42+
setLogin(token, user);
4343
form.resetForm();
4444
navigate("/");
4545
} catch (error) {

client/src/interfaces/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
export * as IService from "./http-client";
2-
export * as IModels from "./models/auth";
2+
export * as IModels from "./models";
33
export * as IStores from "./stores";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { IUserAccount } from "../user-account";
2+
3+
export interface IUserAccountResponse {
4+
user: IUserAccount;
5+
}

client/src/interfaces/models/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export * from "./auth";
2+
export * from "./user-account";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export interface IUserAccount {
2+
_id: string;
3+
user_type_id: string;
4+
email: string;
5+
password: string;
6+
sms_notification_active: boolean;
7+
email_notification_active: boolean;
8+
registration_date: Date;
9+
createdAt: Date;
10+
updatedAt: Date;
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./IUserAccount";

client/src/pages/HomePage/HomePage.tsx

+2-4
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,7 @@ const HomePage = () => {
9898
<aside className="sticky top-24 hidden w-80 shrink-0 xl:block">
9999
<div className="overflow-hidden rounded-lg bg-white shadow">
100100
<div className="px-4 py-5 sm:p-6">
101-
<h4 className="text-lg font-semibold text-gray-900 mb-2">
102-
Filters
103-
</h4>
101+
<h4 className="text-lg font-semibold text-gray-900">Filters</h4>
104102

105103
<div className="py-5">
106104
<Divider />
@@ -313,7 +311,7 @@ const HomePage = () => {
313311
</div>
314312

315313
{/* Jobs List Grid extra-large - 5 columns , large - 4 columns, medium - 3 columns, small - 2 columns */}
316-
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
314+
<div className="grid grid-cols-1 md:grid-cols-2 2xl:grid-cols-3 gap-6">
317315
{jobs.map((job, index) => (
318316
<div
319317
key={job.id}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import PortalLayout from "@/components/layouts/portal/PortalLayout";
2+
3+
const MessagesPage = () => {
4+
return <PortalLayout title="Messages">MessagesPage</PortalLayout>;
5+
};
6+
7+
export default MessagesPage;
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from "./MessagesPage";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import PortalLayout from "@/components/layouts/portal/PortalLayout";
2+
3+
const MyJobsPage = () => {
4+
return <PortalLayout title="My Jobs">"My Jobs Page</PortalLayout>;
5+
};
6+
7+
export default MyJobsPage;

client/src/pages/MyJobsPage/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from "./MyJobsPage";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import PortalLayout from "@/components/layouts/portal/PortalLayout";
2+
3+
const ProfilePage = () => {
4+
return <PortalLayout title="My Profile">ProfilePage</PortalLayout>;
5+
};
6+
7+
export default ProfilePage;

client/src/pages/ProfilePage/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from "./ProfilePage";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import PortalLayout from "@/components/layouts/portal/PortalLayout";
2+
3+
const SavedJobsPage = () => {
4+
return <PortalLayout title="Saved Jobs">SavedJobsPage</PortalLayout>;
5+
};
6+
7+
export default SavedJobsPage;
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from "./SavedJobsPage";

0 commit comments

Comments
 (0)