Skip to content

Commit

Permalink
fix: fix leaky abstraction
Browse files Browse the repository at this point in the history
  • Loading branch information
qamarq committed Dec 14, 2024
1 parent bbc454e commit ba08005
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 78 deletions.
64 changes: 51 additions & 13 deletions frontend/src/app/plans/edit/[id]/page.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,28 +114,66 @@ export function CreateNewPlanPage({

const handleCreateOnlinePlan = async () => {
firstTime.current = false;
const result = await createOnlinePlan(plan);
if ("error" in result) {
if (result.error === "NOT_LOGGED_IN") {
setOfflineAlert(true);
} else {
toast.error("Nie udało się utworzyć planu w wersji online", {
description: result.message,
duration: 10000,
});
}
} else if ("success" in result) {
const res = await createOnlinePlan(plan);

if (res.status === "SUCCESS") {
const { updatedAt, onlineId } = res;
plan.setPlan((prev) => ({
...prev,
synced: true,
updatedAt: new Date(updatedAt),
onlineId: onlineId,
}));

toast.success("Utworzono plan");
} else if (res.status === "NOT_LOGGED_IN") {
setOfflineAlert(true);
} else {
toast.error("Nie udało się utworzyć planu w wersji online", {
description: res.message,
duration: 10000,
});
}
};

const handleSyncPlan = async () => {
await syncPlan(plan, refetchOnlinePlan, setSyncing);
setSyncing(true);
const res = await syncPlan(plan);

if (res.status === "SUCCESS") {
await refetchOnlinePlan();

plan.setPlan((prev) => ({
...prev,
synced: true,
updatedAt: res.updatedAt ? new Date(res.updatedAt) : new Date(),
}));
} else {
toast.error(res.message, {
duration: 10000,
});
}
};

const handleUpdateLocalPlan = async () => {
firstTime.current = false;
await updateLocalPlan(onlinePlan, plan, coursesFn);
const res = await updateLocalPlan(onlinePlan, coursesFn);

if (res.status === "SUCCESS") {
const { updatedRegistrations, updatedCourses, updatedAt } = res;
plan.setPlan({
...plan,
registrations: updatedRegistrations,
courses: updatedCourses,
synced: true,
toCreate: false,
updatedAt,
});
} else {
toast.error(res.message, {
duration: 10000,
});
}
};

const bounceAlert = () => {
Expand Down
29 changes: 16 additions & 13 deletions frontend/src/lib/usePlan.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { SetStateAction } from "jotai";
import { useAtom } from "jotai";
import type { Dispatch } from "react";

import { type ExtendedCourse, planFamily } from "@/atoms/planFamily";

Expand All @@ -16,21 +17,23 @@ export interface PlanState {
toCreate: boolean;
createdAt: Date;
updatedAt: Date;
setPlan: (
args_0: SetStateAction<{
id: string;
name: string;
courses: ExtendedCourse[];
registrations: Registration[];
createdAt: Date;
updatedAt: Date;
onlineId: string | null;
toCreate: boolean;
synced: boolean;
}>,
) => void;
setPlan: setPlanType;
}

export type setPlanType = Dispatch<
SetStateAction<{
id: string;
name: string;
courses: ExtendedCourse[];
registrations: Registration[];
createdAt: Date;
updatedAt: Date;
onlineId: string | null;
toCreate: boolean;
synced: boolean;
}>
>;

export const usePlan = ({ planId }: { planId: string }) => {
const [plan, setPlan] = useAtom(planFamily({ id: planId }));

Expand Down
35 changes: 25 additions & 10 deletions frontend/src/lib/utils/createOnlinePlan.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,25 @@
import { createNewPlan } from "@/actions/plans";
import type { PlanState } from "@/lib/usePlan";

export const createOnlinePlan = async (plan: PlanState) => {
type CreateOnlinePlanResult =
| {
status: "NOT_LOGGED_IN" | "UNKNOWN";
message: string;
}
| {
status: "SUCCESS";
updatedAt: Date;
onlineId: string;
};

/**
* Creates a new plan online in database on user account.
* @param plan **plan** object from useAtom()
* @returns Objects: ```{ status: "NOT_LOGGED_IN" | "UNKNOWN", message: string }``` or ```{ status: "SUCCESS" }```
*/
export const createOnlinePlan = async (
plan: PlanState,
): Promise<CreateOnlinePlanResult> => {
try {
const courses = plan.courses
.filter((c) => c.isChecked)
Expand All @@ -18,21 +36,18 @@ export const createOnlinePlan = async (plan: PlanState) => {
groups,
});

plan.setPlan((prev) => ({
...prev,
synced: true,
return {
status: "SUCCESS",
updatedAt: new Date(res.schedule.updatedAt),
onlineId: res.schedule.id.toString(),
}));

return { success: true };
};
} catch (err) {
if (err instanceof Error && "message" in err) {
if (err.message === "Not logged in") {
return { error: "NOT_LOGGED_IN", message: err.message };
return { status: "NOT_LOGGED_IN", message: err.message };
}
return { error: "UNKNOWN", message: err.message };
return { status: "UNKNOWN", message: err.message };
}
return { error: "UNKNOWN", message: "Wystąpił nieoczekiwany błąd" };
return { status: "UNKNOWN", message: "Wystąpił nieoczekiwany błąd" };
}
};
49 changes: 24 additions & 25 deletions frontend/src/lib/utils/syncPlan.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
import { toast } from "sonner";

import { updatePlan } from "@/actions/plans";
import type { PlanState } from "@/lib/usePlan";

export const syncPlan = async <T>(
plan: PlanState,
refetchOnlinePlan: () => Promise<T>,
setSyncing: (value: boolean) => void,
): Promise<T | null> => {
setSyncing(true);
type SyncPlanResult =
| {
status: "ERROR";
message: string;
}
| {
status: "SUCCESS";
updatedAt: string;
};

/**
* Updates a plan online in database on user account.
* @param plan **plan** object from useAtom()
* @returns Objects ```{ status: "ERROR", message: string }``` or ```{ status: "SUCCESS", updatedAt: string }```
*/

export const syncPlan = async (plan: PlanState): Promise<SyncPlanResult> => {
try {
const res = await updatePlan({
id: Number(plan.onlineId),
Expand All @@ -23,24 +32,14 @@ export const syncPlan = async <T>(
});

if (!res.success) {
toast.error("Nie udało się zaktualizować planu");
return null;
return {
status: "ERROR",
message: "Nie udało się zaktualizować planu",
};
}

await refetchOnlinePlan();

plan.setPlan((prev) => ({
...prev,
synced: true,
updatedAt: res.schedule.updatedAt
? new Date(res.schedule.updatedAt)
: new Date(),
}));
} catch {
toast.error("Nie udało się zaktualizować planu");
return null;
} finally {
setSyncing(false);
return { status: "SUCCESS", updatedAt: res.schedule.updatedAt };
} catch (err) {
return { status: "ERROR", message: "Nie udało się zaktualizować planu" };
}
return null;
};
48 changes: 31 additions & 17 deletions frontend/src/lib/utils/updateLocalPlan.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,40 @@
import type { UseMutationResult } from "@tanstack/react-query";
import { toast } from "sonner";

import type { ExtendedCourse, ExtendedGroup } from "@/atoms/planFamily";
import type { PlanState } from "@/lib/usePlan";
import type { LessonType } from "@/services/usos/types";
import type { CourseType, PlanResponseType } from "@/types";

import type { Registration } from "../types";

type UpdateLocalPlanResult =
| {
status: "ERROR";
message: string;
}
| {
status: "SUCCESS";
updatedRegistrations: Registration[];
updatedCourses: ExtendedCourse[];
updatedAt: Date;
};

/**
* Updates local plan with online plan data.
* @param onlinePlan Online plan data
* @param coursesFn Function to fetch courses
* @returns Objects ```{ status: "ERROR", message: string }``` or ```{ status: "SUCCESS", updatedRegistrations: Registration[], updatedCourses: ExtendedCourse[], updatedAt: Date }```
*/

export const updateLocalPlan = async (
onlinePlan: PlanResponseType | null | undefined,
plan: PlanState,
coursesFn: UseMutationResult<CourseType, Error, string>,
): Promise<boolean> => {
): Promise<UpdateLocalPlanResult> => {
if (!onlinePlan) {
return false;
return { status: "ERROR", message: "Nie udało się pobrać planu online" };
}

let updatedRegistrations: typeof plan.registrations = [];
let updatedCourses: typeof plan.courses = [];
let updatedRegistrations: Registration[] = [];
let updatedCourses: ExtendedCourse[] = [];

for (const registration of onlinePlan.registrations) {
try {
Expand Down Expand Up @@ -64,18 +82,14 @@ export const updateLocalPlan = async (
array.findIndex((t) => t.id === course.id) === index,
);
} catch {
toast.error("Nie udało się pobrać kursów");
return { status: "ERROR", message: "Nie udało się pobrać kursów" };
}
}

plan.setPlan({
...plan,
registrations: updatedRegistrations,
courses: updatedCourses,
synced: true,
toCreate: false,
return {
status: "SUCCESS",
updatedRegistrations,
updatedCourses,
updatedAt: new Date(onlinePlan.updatedAt),
});

return true;
};
};

0 comments on commit ba08005

Please sign in to comment.