Commit
·
807aefa
1
Parent(s):
ab5962a
View My Applications.
Browse files- frontend/app/components/application-card.tsx +7 -3
- frontend/app/components/sidebar-provider.tsx +2 -1
- frontend/app/routes.ts +2 -0
- frontend/app/routes/jobs.$jid.assessments.$aid.applications.$id.tsx +1 -1
- frontend/app/routes/my-applications.$id.tsx +80 -0
- frontend/app/routes/my-applications.tsx +69 -0
- frontend/app/services/useGetJobAssessmentApplicationByID.ts +1 -1
- frontend/app/services/useGetJobAssessmentApplications.ts +1 -1
- frontend/app/services/useGetMyApplicationByID.ts +14 -0
- frontend/app/services/useGetMyApplications.ts +31 -0
frontend/app/components/application-card.tsx
CHANGED
|
@@ -1,18 +1,22 @@
|
|
| 1 |
import { cn } from "~/lib/utils";
|
| 2 |
import { Avatar } from "radix-ui";
|
| 3 |
import { useNavigate } from "react-router";
|
|
|
|
| 4 |
import type { Application } from "~/services/useGetJobAssessmentApplications";
|
| 5 |
|
| 6 |
-
export function ApplicationCard({ application, aid, jid, isStatic = false } : { application: Application, jid: string, aid: string, isStatic?: boolean }) {
|
| 7 |
const Navigate = useNavigate();
|
| 8 |
|
| 9 |
return (
|
| 10 |
<div
|
| 11 |
tabIndex={isStatic ? -1 : 0}
|
| 12 |
className={cn("p-4 flex flex-wrap justify-between gap-4 place-items-center", isStatic ? "" : "border rounded bg-indigo-100 dark:bg-gray-700 [:is(:hover,:focus)]:shadow-lg [:is(:hover,:focus)]:scale-101 transition-all cursor-pointer")}
|
| 13 |
-
onClick={() => isStatic || Navigate(`/jobs/${jid}/assessments/${aid}/applications/${application.id}`)}
|
| 14 |
>
|
| 15 |
-
<
|
|
|
|
|
|
|
|
|
|
| 16 |
<div className="group-data-[collapsible=icon]:-mx-4 flex gap-2">
|
| 17 |
<Avatar.Avatar className="shrink-0 cursor-pointer" tabIndex={0}>
|
| 18 |
<Avatar.AvatarFallback className="rounded-full bg-indigo-200 dark:bg-gray-800 size-10 group-data-[collapsible=icon]:size-8 flex items-center justify-center">
|
|
|
|
| 1 |
import { cn } from "~/lib/utils";
|
| 2 |
import { Avatar } from "radix-ui";
|
| 3 |
import { useNavigate } from "react-router";
|
| 4 |
+
import type { MyApplication } from "~/services/useGetMyApplications";
|
| 5 |
import type { Application } from "~/services/useGetJobAssessmentApplications";
|
| 6 |
|
| 7 |
+
export function ApplicationCard({ application, aid, jid, isStatic = false, safeRoute = false } : { application: Application & { job?: MyApplication["job"] }, jid: string, aid: string, isStatic?: boolean, safeRoute?: boolean }) {
|
| 8 |
const Navigate = useNavigate();
|
| 9 |
|
| 10 |
return (
|
| 11 |
<div
|
| 12 |
tabIndex={isStatic ? -1 : 0}
|
| 13 |
className={cn("p-4 flex flex-wrap justify-between gap-4 place-items-center", isStatic ? "" : "border rounded bg-indigo-100 dark:bg-gray-700 [:is(:hover,:focus)]:shadow-lg [:is(:hover,:focus)]:scale-101 transition-all cursor-pointer")}
|
| 14 |
+
onClick={() => isStatic || Navigate(safeRoute ? `/my-applications/${application.id}` : `/jobs/${jid}/assessments/${aid}/applications/${application.id}`)}
|
| 15 |
>
|
| 16 |
+
<header className="flex flex-col gap-2 w-full grow">
|
| 17 |
+
<h1 className={cn("font-bold", isStatic ? "text-3xl" : "text-xl")}>{application.assessment_details.title}</h1>
|
| 18 |
+
{application.job && <p className="text-gray-500 dark:text-gray-200">{application.job.title}</p>}
|
| 19 |
+
</header>
|
| 20 |
<div className="group-data-[collapsible=icon]:-mx-4 flex gap-2">
|
| 21 |
<Avatar.Avatar className="shrink-0 cursor-pointer" tabIndex={0}>
|
| 22 |
<Avatar.AvatarFallback className="rounded-full bg-indigo-200 dark:bg-gray-800 size-10 group-data-[collapsible=icon]:size-8 flex items-center justify-center">
|
frontend/app/components/sidebar-provider.tsx
CHANGED
|
@@ -4,13 +4,14 @@ import { toast } from "react-toastify";
|
|
| 4 |
import { Link, useLocation } from "react-router";
|
| 5 |
import { HTTPManager } from "~/managers/HTTPManager";
|
| 6 |
import { useGetMyUser } from "~/services/useGetMyUser";
|
| 7 |
-
import { Building2Icon, LayoutDashboardIcon } from "lucide-react";
|
| 8 |
import { Popover, PopoverContent, PopoverTrigger } from "./ui/popover";
|
|
|
|
| 9 |
import { Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarInset, SidebarProvider as SidebarProvider_ } from "./ui/sidebar";
|
| 10 |
|
| 11 |
const LINKS = [
|
| 12 |
{ title: "Jobs", to: "/jobs", icon: Building2Icon },
|
| 13 |
{ title: "Dashboard", to: "/dashboard", icon: LayoutDashboardIcon, role: "hr" },
|
|
|
|
| 14 |
]
|
| 15 |
|
| 16 |
export function SidebarProvider({ children }: { children: React.ReactNode }) {
|
|
|
|
| 4 |
import { Link, useLocation } from "react-router";
|
| 5 |
import { HTTPManager } from "~/managers/HTTPManager";
|
| 6 |
import { useGetMyUser } from "~/services/useGetMyUser";
|
|
|
|
| 7 |
import { Popover, PopoverContent, PopoverTrigger } from "./ui/popover";
|
| 8 |
+
import { Building2Icon, FilesIcon, LayoutDashboardIcon } from "lucide-react";
|
| 9 |
import { Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarInset, SidebarProvider as SidebarProvider_ } from "./ui/sidebar";
|
| 10 |
|
| 11 |
const LINKS = [
|
| 12 |
{ title: "Jobs", to: "/jobs", icon: Building2Icon },
|
| 13 |
{ title: "Dashboard", to: "/dashboard", icon: LayoutDashboardIcon, role: "hr" },
|
| 14 |
+
{ title: "My Applications", to: "/my-applications", icon: FilesIcon, role: "applicant" },
|
| 15 |
]
|
| 16 |
|
| 17 |
export function SidebarProvider({ children }: { children: React.ReactNode }) {
|
frontend/app/routes.ts
CHANGED
|
@@ -9,6 +9,8 @@ export default [
|
|
| 9 |
route("jobs/:jid/assessments/:id", "routes/jobs.$jid.assessments.$id.tsx"),
|
| 10 |
route("jobs/:jid/assessments/:aid/applications", "routes/jobs.$jid.assessments.$aid.applications.tsx"),
|
| 11 |
route("jobs/:jid/assessments/:aid/applications/:id", "routes/jobs.$jid.assessments.$aid.applications.$id.tsx"),
|
|
|
|
|
|
|
| 12 |
route("dashboard", "routes/dashboard.tsx"),
|
| 13 |
route("registration", "routes/registration.tsx"),
|
| 14 |
] satisfies RouteConfig;
|
|
|
|
| 9 |
route("jobs/:jid/assessments/:id", "routes/jobs.$jid.assessments.$id.tsx"),
|
| 10 |
route("jobs/:jid/assessments/:aid/applications", "routes/jobs.$jid.assessments.$aid.applications.tsx"),
|
| 11 |
route("jobs/:jid/assessments/:aid/applications/:id", "routes/jobs.$jid.assessments.$aid.applications.$id.tsx"),
|
| 12 |
+
route("my-applications", "routes/my-applications.tsx"),
|
| 13 |
+
route("my-applications/:id", "routes/my-applications.$id.tsx"),
|
| 14 |
route("dashboard", "routes/dashboard.tsx"),
|
| 15 |
route("registration", "routes/registration.tsx"),
|
| 16 |
] satisfies RouteConfig;
|
frontend/app/routes/jobs.$jid.assessments.$aid.applications.$id.tsx
CHANGED
|
@@ -75,5 +75,5 @@ export default function ApplicationDetailsRoute() {
|
|
| 75 |
/>
|
| 76 |
))}
|
| 77 |
</main>
|
| 78 |
-
)
|
| 79 |
}
|
|
|
|
| 75 |
/>
|
| 76 |
))}
|
| 77 |
</main>
|
| 78 |
+
);
|
| 79 |
}
|
frontend/app/routes/my-applications.$id.tsx
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { useParams } from "react-router";
|
| 2 |
+
import { Loader2Icon } from "lucide-react";
|
| 3 |
+
import type { Route } from "./+types/my-applications";
|
| 4 |
+
import { QuestionCard } from "~/components/question-card";
|
| 5 |
+
import { ApplicationCard } from "~/components/application-card";
|
| 6 |
+
import { useGetMyApplicationByID } from "~/services/useGetMyApplicationByID";
|
| 7 |
+
import type { DetailedApplication } from "~/services/useGetJobAssessmentApplicationByID";
|
| 8 |
+
|
| 9 |
+
export function meta({}: Route.MetaArgs) {
|
| 10 |
+
return [
|
| 11 |
+
{ title: "My Application Details" },
|
| 12 |
+
{
|
| 13 |
+
name: "description",
|
| 14 |
+
content: "Detailed view of the selected application, including candidate information and assessment results.",
|
| 15 |
+
},
|
| 16 |
+
];
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
export default function MyApplicationDetailsRoute() {
|
| 20 |
+
const { id } = useParams();
|
| 21 |
+
const { data: application, isLoading, isError, refetch } = useGetMyApplicationByID({ id: id || "" });
|
| 22 |
+
|
| 23 |
+
if (isLoading) {
|
| 24 |
+
return (
|
| 25 |
+
<main className="container mx-auto p-4 flex flex-col gap-2 place-items-center">
|
| 26 |
+
<div className="flex flex-col gap-2 place-items-center">
|
| 27 |
+
<Loader2Icon className="animate-spin" />
|
| 28 |
+
<p>Loading application...</p>
|
| 29 |
+
</div>
|
| 30 |
+
</main>
|
| 31 |
+
);
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
if (isError) {
|
| 35 |
+
return (
|
| 36 |
+
<main className="container mx-auto p-4 flex flex-col gap-2">
|
| 37 |
+
<div className="bg-red-100 text-red-700 dark:bg-red-900 dark:text-red-100 p-4 rounded flex flex-col gap-2 place-items-center">
|
| 38 |
+
<p className="text-center">Failed to load application<br />Please try again</p>
|
| 39 |
+
<button
|
| 40 |
+
onClick={() => refetch()}
|
| 41 |
+
className="ml-4 px-3 py-1 cursor-pointer bg-red-500 text-white dark:bg-red-200 dark:text-red-700 rounded"
|
| 42 |
+
>
|
| 43 |
+
Retry
|
| 44 |
+
</button>
|
| 45 |
+
</div>
|
| 46 |
+
</main>
|
| 47 |
+
);
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
const totalWeights = application.answers.reduce((weights, answer) => weights + answer.weight, 0);
|
| 51 |
+
|
| 52 |
+
return (
|
| 53 |
+
<main className="container mx-auto p-4 flex flex-col gap-4">
|
| 54 |
+
<ApplicationCard application={application} aid={application.assessment.id || ""} jid={application.job.id || ""} isStatic />
|
| 55 |
+
{application.answers.map((answer: DetailedApplication["answers"][number]) => (
|
| 56 |
+
<QuestionCard
|
| 57 |
+
key={answer.question_id}
|
| 58 |
+
isStatic
|
| 59 |
+
displayCheckboxMessage
|
| 60 |
+
question={{
|
| 61 |
+
type: answer.type,
|
| 62 |
+
weight: answer.weight,
|
| 63 |
+
id: answer.question_id,
|
| 64 |
+
text: answer.question_text,
|
| 65 |
+
options: answer.question_options,
|
| 66 |
+
correct_options: answer.correct_options,
|
| 67 |
+
skill_categories: answer.skill_categories,
|
| 68 |
+
}}
|
| 69 |
+
answers={application.answers.reduce((accumulator, current) => ({
|
| 70 |
+
...accumulator,
|
| 71 |
+
[current.question_id]: current.type == "text_based" ? current.text : current.type == "choose_one" ? current.options : current.options,
|
| 72 |
+
}), {})}
|
| 73 |
+
setAnswers={() => {}}
|
| 74 |
+
totalWeights={totalWeights}
|
| 75 |
+
rationale={answer.rationale}
|
| 76 |
+
/>
|
| 77 |
+
))}
|
| 78 |
+
</main>
|
| 79 |
+
);
|
| 80 |
+
}
|
frontend/app/routes/my-applications.tsx
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { Loader2Icon } from "lucide-react";
|
| 2 |
+
import { Paginator } from "~/components/paginator";
|
| 3 |
+
import type { Route } from "./+types/my-applications";
|
| 4 |
+
import { useGetMyUser } from "~/services/useGetMyUser";
|
| 5 |
+
import { ApplicationCard } from "~/components/application-card";
|
| 6 |
+
import { useGetMyApplications } from "~/services/useGetMyApplications";
|
| 7 |
+
|
| 8 |
+
export function meta({}: Route.MetaArgs) {
|
| 9 |
+
return [
|
| 10 |
+
{ title: "My Applications" },
|
| 11 |
+
{
|
| 12 |
+
name: "description",
|
| 13 |
+
content: "View and manage your job applications, track their status, and review feedback from assessments.",
|
| 14 |
+
},
|
| 15 |
+
];
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
export default function MyApplicationsRoute() {
|
| 19 |
+
const { data: myUser, isLoading: isMyUserLoading, isError: isMyUserError, refetch: refetchMyUser } = useGetMyUser();
|
| 20 |
+
const { data: { data: applications, total } = { data: [] }, isLoading: isApplicationsLoading, isError: isApplicationsError, refetch: refetchApplications } = useGetMyApplications();
|
| 21 |
+
|
| 22 |
+
const isError = isMyUserError || isApplicationsError;
|
| 23 |
+
const isLoading = isMyUserLoading || isApplicationsLoading;
|
| 24 |
+
const refetch = () => (refetchMyUser(), refetchApplications());
|
| 25 |
+
|
| 26 |
+
if (isLoading) {
|
| 27 |
+
return (
|
| 28 |
+
<main className="container mx-auto p-4 flex flex-col gap-2 place-items-center">
|
| 29 |
+
<div className="flex flex-col gap-2 place-items-center">
|
| 30 |
+
<Loader2Icon className="animate-spin" />
|
| 31 |
+
<p>Loading Applications...</p>
|
| 32 |
+
</div>
|
| 33 |
+
</main>
|
| 34 |
+
);
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
if (isError) {
|
| 38 |
+
return (
|
| 39 |
+
<main className="container mx-auto p-4 flex flex-col gap-2">
|
| 40 |
+
<div className="bg-red-100 text-red-700 dark:bg-red-900 dark:text-red-100 p-4 rounded flex flex-col gap-2 place-items-center">
|
| 41 |
+
<p className="text-center">Failed to load applications<br />Please try again</p>
|
| 42 |
+
<button
|
| 43 |
+
onClick={() => refetch()}
|
| 44 |
+
className="ml-4 px-3 py-1 cursor-pointer bg-red-500 text-white dark:bg-red-200 dark:text-red-700 rounded"
|
| 45 |
+
>
|
| 46 |
+
Retry
|
| 47 |
+
</button>
|
| 48 |
+
</div>
|
| 49 |
+
</main>
|
| 50 |
+
);
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
return (
|
| 55 |
+
<main className="container mx-auto p-4 flex flex-col gap-8">
|
| 56 |
+
<section className="flex flex-col gap-4">
|
| 57 |
+
<h3 className="text-xl font-semibold">Assessment's Applications</h3>
|
| 58 |
+
<div className="grid grid-cols-[repeat(auto-fill,minmax(400px,1fr))] gap-4">
|
| 59 |
+
{applications.length === 0 ? (
|
| 60 |
+
<p>No applications found.<br/>Start applying now!</p>
|
| 61 |
+
) : applications.map(application => (
|
| 62 |
+
<ApplicationCard key={application.id} application={{...application, user: myUser, passing_score: application.assessment.passing_score, assessment_details: application.assessment}} jid={application.job.id || ""} aid={application.assessment.id || ""} safeRoute />
|
| 63 |
+
))}
|
| 64 |
+
</div>
|
| 65 |
+
{total != null && total > 0 && <Paginator total={total} />}
|
| 66 |
+
</section>
|
| 67 |
+
</main>
|
| 68 |
+
);
|
| 69 |
+
}
|
frontend/app/services/useGetJobAssessmentApplicationByID.ts
CHANGED
|
@@ -32,7 +32,7 @@ export type DetailedApplication = {
|
|
| 32 |
};
|
| 33 |
|
| 34 |
export const useGetJobAssessmentApplicationByID = ({ jid, aid, id }: { jid: string, aid: string, id: string }) => useQuery({
|
| 35 |
-
queryKey: [GET_JOB_ASSESSMENT_APPLICATION_BY_ID_KEY, jid, id],
|
| 36 |
queryFn: async () =>
|
| 37 |
HTTPManager.get<DetailedApplication>(
|
| 38 |
`/applications/jobs/${jid}/assessment_id/${aid}/applications/${id}`,
|
|
|
|
| 32 |
};
|
| 33 |
|
| 34 |
export const useGetJobAssessmentApplicationByID = ({ jid, aid, id }: { jid: string, aid: string, id: string }) => useQuery({
|
| 35 |
+
queryKey: [GET_JOB_ASSESSMENT_APPLICATION_BY_ID_KEY, jid, aid, id],
|
| 36 |
queryFn: async () =>
|
| 37 |
HTTPManager.get<DetailedApplication>(
|
| 38 |
`/applications/jobs/${jid}/assessment_id/${aid}/applications/${id}`,
|
frontend/app/services/useGetJobAssessmentApplications.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { HTTPManager } from "~/managers/HTTPManager";
|
|
| 4 |
import type { Pagination } from "~/types/pagination";
|
| 5 |
import { usePagination } from "~/hooks/use-pagination";
|
| 6 |
|
| 7 |
-
export const GET_JOB_ASSESSMENT_APPLICATION_KEY = "job-assessments-
|
| 8 |
|
| 9 |
export type Application = {
|
| 10 |
id: string;
|
|
|
|
| 4 |
import type { Pagination } from "~/types/pagination";
|
| 5 |
import { usePagination } from "~/hooks/use-pagination";
|
| 6 |
|
| 7 |
+
export const GET_JOB_ASSESSMENT_APPLICATION_KEY = "job-assessments-applications";
|
| 8 |
|
| 9 |
export type Application = {
|
| 10 |
id: string;
|
frontend/app/services/useGetMyApplicationByID.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { useQuery } from "@tanstack/react-query";
|
| 2 |
+
import { HTTPManager } from "~/managers/HTTPManager";
|
| 3 |
+
import type { MyApplication } from "./useGetMyApplications";
|
| 4 |
+
import type { DetailedApplication } from "./useGetJobAssessmentApplicationByID";
|
| 5 |
+
|
| 6 |
+
export const GET_JOB_ASSESSMENT_APPLICATION_BY_ID_KEY = "job-assessment-application-by-id";
|
| 7 |
+
|
| 8 |
+
export type DetailedMyApplication = MyApplication & DetailedApplication;
|
| 9 |
+
|
| 10 |
+
export const useGetMyApplicationByID = ({ id }: { id: string }) => useQuery({
|
| 11 |
+
queryKey: [GET_JOB_ASSESSMENT_APPLICATION_BY_ID_KEY, id],
|
| 12 |
+
queryFn: async () =>
|
| 13 |
+
HTTPManager.get<DetailedMyApplication>(`/applications/my-applications/${id}`).then((response) => response.data),
|
| 14 |
+
});
|
frontend/app/services/useGetMyApplications.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { useQuery } from "@tanstack/react-query";
|
| 2 |
+
import { HTTPManager } from "~/managers/HTTPManager";
|
| 3 |
+
import type { Pagination } from "~/types/pagination";
|
| 4 |
+
import { usePagination } from "~/hooks/use-pagination";
|
| 5 |
+
|
| 6 |
+
export const GET_MY_APPLICATIONS_KEY = "job-my-applications";
|
| 7 |
+
|
| 8 |
+
export type MyApplication = {
|
| 9 |
+
id: string;
|
| 10 |
+
score: number;
|
| 11 |
+
job: {
|
| 12 |
+
id: string;
|
| 13 |
+
title: string;
|
| 14 |
+
description: string;
|
| 15 |
+
seniority: "intern" | "junior" | "mid" | "senior";
|
| 16 |
+
};
|
| 17 |
+
assessment: {
|
| 18 |
+
id: string;
|
| 19 |
+
title: string;
|
| 20 |
+
passing_score: number;
|
| 21 |
+
};
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
export const useGetMyApplications = () => {
|
| 25 |
+
const { page, limit } = usePagination();
|
| 26 |
+
const searchParams = new URLSearchParams({ page: String(page), limit: String(limit) });
|
| 27 |
+
return useQuery({
|
| 28 |
+
queryKey: [GET_MY_APPLICATIONS_KEY, page, limit],
|
| 29 |
+
queryFn: async () => HTTPManager.get<Pagination<MyApplication>>(`/applications/my-applications?` + searchParams.toString()).then(response => response.data),
|
| 30 |
+
});
|
| 31 |
+
}
|