Skip to content

Commit

Permalink
Added stats page
Browse files Browse the repository at this point in the history
Fixed extension not scrolling to top when capturing
  • Loading branch information
ncpleslie committed Mar 31, 2024
1 parent 5ae3a05 commit df566d8
Show file tree
Hide file tree
Showing 14 changed files with 221 additions and 19 deletions.
9 changes: 5 additions & 4 deletions backend/models/responses/stats.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
package responses

type Stats struct {
TotalJobs int `json:"totalJobs"`
Current StatTrack `json:"current"`
Historical StatTrack `json:"historical"`
Total int `json:"total"`
Current Stat `json:"current"`
Historical Stat `json:"historical"`
}

type StatTrack struct {
type Stat struct {
Applied int `json:"applied"`
Interview int `json:"interview"`
Offer int `json:"offer"`
Rejected int `json:"rejected"`
Other int `json:"other"`
Accepted int `json:"accepted"`
Withdrawn int `json:"withdrawn"`
}
11 changes: 8 additions & 3 deletions backend/services/job_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,11 @@ func (s *JobService) CreateNewJob(ctx context.Context, userId string, job reques
errChan <- err
return
}
mimeType = "png"
mimeType = "image/png"
}

filename := fmt.Sprintf("%s/%s.%s", userId, jobEntity.Id, mimeType)
extension := strings.Split(mimeType, "/")[1]
filename := fmt.Sprintf("%s/%s.%s", userId, jobEntity.Id, extension)
downloadUrl, err := s.Storage.UploadFile(ctx, filename, b)
if err != nil {
log.Println("Error uploading image: ", err)
Expand Down Expand Up @@ -236,6 +237,8 @@ func (s *JobService) GetStats(ctx context.Context, userId string) (responses.Sta
stats.Current.Rejected++
case "accepted":
stats.Current.Accepted++
case "withdrawn":
stats.Current.Withdrawn++
default:
stats.Current.Other++
}
Expand All @@ -256,13 +259,15 @@ func (s *JobService) GetStats(ctx context.Context, userId string) (responses.Sta
stats.Historical.Rejected++
case "accepted":
stats.Historical.Accepted++
case "withdrawn":
stats.Historical.Withdrawn++
default:
stats.Historical.Other++
}
}
}

stats.TotalJobs = len(jobs)
stats.Total = len(jobs)
return stats, nil
}

Expand Down
7 changes: 5 additions & 2 deletions extension/src/pages/popup/hooks/use-screenshot.hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ const useScreenshot = () => {

await chrome.scripting.executeScript({
target: { tabId: activeTab.id },
function: () => window.scrollTo(0, 0),
function: async () => {
window.scrollTo({ top: 0, left: 0, behavior: "instant" });
await new Promise((resolve) => setTimeout(resolve, 100));
},
});

async function captureScreenshot() {
Expand Down Expand Up @@ -63,7 +66,7 @@ const useScreenshot = () => {
}
}

captureScreenshot();
await captureScreenshot();
setCapturing(false);
}

Expand Down
11 changes: 8 additions & 3 deletions extension/src/pages/popup/routes/jobs/add.lazy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,26 @@ import {
import { createLazyFileRoute } from "@tanstack/react-router";
import useMessage from "@pages/popup/hooks/use-message.hook";
import useScreenshot from "@pages/popup/hooks/use-screenshot.hook";
import { Aperture } from "lucide-react";
import { Aperture, Loader2 } from "lucide-react";
import { useState } from "react";

export const Route = createLazyFileRoute("/jobs/add")({
component: AddJob,
});

function AddJob() {
const [capturing, setCapturing] = useState(false);
const { captureFullPageScreenshot, canvasRef } = useScreenshot();

const { data: token } = useMessage({ type: "userToken" });
const { onSubmit, onClose, setJobImage, jobImage, isPending } =
useAddJob(token);

const onCapture = () => {
setCapturing(true);
captureFullPageScreenshot((dataUrl) => {
setJobImage(dataUrl);
setCapturing(false);
});
};

Expand All @@ -38,12 +42,13 @@ function AddJob() {
<Button type="submit">Add</Button>
<Button
variant={jobImage ? "outline" : "secondary"}
disabled={Boolean(jobImage)}
disabled={Boolean(jobImage) || capturing}
type="button"
onClick={onCapture}
title="Capture screenshot of the job posting"
>
<Aperture className="h-6 w-6" />
{!capturing && <Aperture className="h-6 w-6" />}
{capturing && <Loader2 className="animate-spin h-6 w-6" />}
</Button>
<Button variant="secondary" type="button" onClick={onClose}>
Cancel
Expand Down
1 change: 1 addition & 0 deletions extension/src/pages/popup/routes/jobs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ const AllJobsTableAsync: React.FC<AllJobsTableAsyncProps> = ({ token }) => {
onUpdateJob={onUpdateJob}
isPendingDelete={isPendingDelete}
jobs={jobs}
addNewJobUrl="/jobs/add"
/>
</div>
);
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/components/AllJobsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -269,11 +269,13 @@ interface AllJobsTableProps {
onViewJob: (job: JobResponse) => void;
onUpdateJob: (job: JobResponse) => void;
isPendingDelete: boolean;
addNewJobUrl: "/jobs/add/modal" | "/jobs/add";
}

const AllJobsTable: React.FC<AllJobsTableProps> = ({
jobs,
isPendingDelete,
addNewJobUrl,
onDeleteJob,
onDeleteJobs,
onViewJob,
Expand Down Expand Up @@ -305,7 +307,7 @@ const AllJobsTable: React.FC<AllJobsTableProps> = ({
</CardHeader>
<CardContent className="flex w-full justify-center">
<Button variant="outline" asChild>
<Link to="/jobs/add/modal">
<Link to={addNewJobUrl}>
<PlusSquare className="mr-2 h-6 w-6" />
New Job
</Link>
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/AllJobsTableAsync.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const AllJobsTableAsync = () => {
onUpdateJob={onUpdateJob}
isPendingDelete={isPendingDelete}
jobs={jobs}
addNewJobUrl="/jobs/add/modal"
/>
);
};
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/constants/job-form.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ export default class JobFormConstants {
id: "rejected",
label: "Rejected",
},
{
id: "withdrawn",
label: "Withdrawn",
},
];

public static readonly DisabledJobStatuses = "rejected";
Expand Down
5 changes: 2 additions & 3 deletions frontend/src/hooks/use-query.hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { auth } from "@/constants/firebase";
import { useIdToken } from "react-firebase-hooks/auth";
import { env } from "@/env";
import AppConstants from "@/constants/app.constants";
import StatsResponse from "@/models/responses/stats.response";

const getBaseUrl = () => {
if (import.meta.env.MODE === "production") {
Expand Down Expand Up @@ -290,9 +291,7 @@ export const useGetJobStatsQuery = () => {
);
}

console.log(await response.json());

return await response.json();
return new StatsResponse(await response.json());
},
});
};
47 changes: 47 additions & 0 deletions frontend/src/models/responses/stats.response.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
export type StatsResponseJson = {
total: number;
current: StatResponseJson;
historical: StatResponseJson;
};

export type StatResponseJson = {
applied: number;
interview: number;
offer: number;
rejected: number;
other: number;
accepted: number;
withdrawn: number;
};

export default class StatsResponse {
constructor(data: StatsResponseJson) {
this.total = data.total;
this.current = new StatResponse(data.current);
this.historical = new StatResponse(data.historical);
}

public total: number;
public current: StatResponse;
public historical: StatResponse;
}

export class StatResponse {
constructor(data: StatResponseJson) {
this.applied = data.applied;
this.interview = data.interview;
this.offer = data.offer;
this.rejected = data.rejected;
this.other = data.other;
this.accepted = data.accepted;
this.withdrawn = data.withdrawn;
}

public applied: number;
public interview: number;
public offer: number;
public rejected: number;
public other: number;
public accepted: number;
public withdrawn: number;
}
16 changes: 15 additions & 1 deletion frontend/src/routeTree.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { Route as IndexImport } from './routes/index'
const JobsLazyImport = createFileRoute('/jobs')()
const JobsAddLazyImport = createFileRoute('/jobs/add')()
const JobsJobIdLazyImport = createFileRoute('/jobs/$jobId')()
const JobsStatsLazyImport = createFileRoute('/jobs/stats')()
const JobsAddModalLazyImport = createFileRoute('/jobs/add/modal')()
const JobsJobIdModalLazyImport = createFileRoute('/jobs/$jobId/modal')()

Expand All @@ -45,6 +46,11 @@ const JobsJobIdLazyRoute = JobsJobIdLazyImport.update({
getParentRoute: () => rootRoute,
} as any).lazy(() => import('./routes/jobs_.$jobId.lazy').then((d) => d.Route))

const JobsStatsLazyRoute = JobsStatsLazyImport.update({
path: '/stats',
getParentRoute: () => JobsLazyRoute,
} as any).lazy(() => import('./routes/jobs.stats.lazy').then((d) => d.Route))

const JobsAddModalLazyRoute = JobsAddModalLazyImport.update({
path: '/add/modal',
getParentRoute: () => JobsLazyRoute,
Expand All @@ -71,6 +77,10 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof JobsLazyImport
parentRoute: typeof rootRoute
}
'/jobs/stats': {
preLoaderRoute: typeof JobsStatsLazyImport
parentRoute: typeof JobsLazyImport
}
'/jobs/$jobId': {
preLoaderRoute: typeof JobsJobIdLazyImport
parentRoute: typeof rootRoute
Expand All @@ -94,7 +104,11 @@ declare module '@tanstack/react-router' {

export const routeTree = rootRoute.addChildren([
IndexRoute,
JobsLazyRoute.addChildren([JobsJobIdModalLazyRoute, JobsAddModalLazyRoute]),
JobsLazyRoute.addChildren([
JobsStatsLazyRoute,
JobsJobIdModalLazyRoute,
JobsAddModalLazyRoute,
]),
JobsJobIdLazyRoute,
JobsAddLazyRoute,
])
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/routes/__root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ const Root = () => {
Jobs
</Link>
</Button>
<Button variant="outline" asChild>
<Link to="/jobs/stats" className="[&.active]:font-bold">
Stats
</Link>
</Button>
</div>
<div className="flex gap-2">
<Button
Expand Down
2 changes: 0 additions & 2 deletions frontend/src/routes/jobs.lazy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@ import { LoadingDialog } from "@/components/ui/loading-dialog";
import { Suspense } from "react";
import AllJobsTableAsync from "@/components/AllJobsTableAsync";
import useHead from "@/hooks/use-head.hook";
import { useGetJobStatsQuery } from "@/hooks/use-query.hook";

export const Route = createLazyFileRoute("/jobs")({
component: Index,
});

function Index() {
useHead("Jobs");
const { data } = useGetJobStatsQuery();

return (
<div className="mb-8">
Expand Down
Loading

0 comments on commit df566d8

Please sign in to comment.