Skip to content
Snippets Groups Projects
Commit 5326fa53 authored by Fatih20's avatar Fatih20
Browse files

Applying theoretically working.

parent 306a8d11
Branches
Tags
No related merge requests found
import NavWrapper from "@/components/NavWrapper";
import { useUser } from "@/utils/context/AuthProvider";
import GymApplicationProvider from "@/utils/context/GymApplicationProvider";
import GymProvider from "@/utils/context/GymProvider";
import { useEffect, useState } from "react";
import { useNavigate, Outlet } from "react-router-dom";
......@@ -29,7 +30,9 @@ function ProtectedLayout() {
return (
<NavWrapper>
<GymProvider>
<Outlet />
<GymApplicationProvider>
<Outlet />
</GymApplicationProvider>
</GymProvider>
</NavWrapper>
);
......
import { useGymApplications } from "@/utils/context/GymApplicationProvider";
import useField from "@/utils/hooks/useField";
import { GymReturned } from "@/utils/validationSchema/gym";
import validate from "@/utils/validationSchema/validate";
import { useState } from "react";
import { z } from "zod";
import ErrorLabel from "../ErrorLabel";
import { useMutation, useQueryClient } from "react-query";
import {
GymApplicationReturned,
GymApplicationSent,
} from "@/utils/validationSchema/gymApplication";
import { useUser } from "@/utils/context/AuthProvider";
import { applyToGym } from "@/utils/api/gymApplication";
function GymApplication({ gym }: { gym: GymReturned }) {
const { gymApplications, gymApplicationsStatus } = useGymApplications();
const {
field: description,
fieldError: descriptionError,
setField: setDescription,
validate: validateDescription,
} = useField((description) => validate(z.string().min(1), description), "");
const [disabled, setDisabled] = useState(false);
const [applyError, setApplyError] = useState("");
const queryClient = useQueryClient();
const { status, user } = useUser();
const { mutateAsync: applyMutation } = useMutation({
mutationFn: async (payload: GymApplicationSent) => {
if (status !== "success" || user === undefined) {
return;
}
return await applyToGym(payload);
},
onMutate: async (addedApplication: GymApplicationSent) => {
await queryClient.cancelQueries({ queryKey: ["applications"] });
const previousGymApplications = gymApplications;
queryClient.setQueryData<GymApplicationReturned[] | undefined>(
["applications"],
(oldGymApplications) => {
console.log("Previous gym applications", oldGymApplications);
if (!oldGymApplications) {
return oldGymApplications;
}
return [
...oldGymApplications,
{
acceptance: 0,
description: addedApplication.application_description,
gymId: addedApplication.gym_id,
gymName: addedApplication.gym_name,
},
];
}
);
return { previousGymApplications };
},
onError(_, __, context) {
queryClient.setQueryData(
["applications"],
context?.previousGymApplications
);
},
onSuccess() {
console.log("Application", queryClient.getQueryData(["applications"]));
// queryClient.invalidateQueries(["applications"]);
},
});
async function handleSubmit() {
setDisabled(true);
if (descriptionError || user === undefined) {
return;
}
try {
await applyMutation({
application_description: description,
gym_id: gym.id,
gym_name: gym.name,
trainer_description: user.description,
trainer_name: user.name,
username: user.username,
});
setDescription("");
} catch (err: unknown) {
const error = err as { response: { data: { error: string } } };
setApplyError(error.response.data.error);
}
setDisabled(false);
}
if (gymApplicationsStatus !== "success") {
return <p>Loading...</p>;
}
if (!gymApplications) {
return <p>Something wrong happened</p>;
}
if (gymApplications.find(({ gymId }) => gymId === gym.id)) {
return (
<button className="btn btn-disabled" disabled>
Applied
</button>
);
}
return (
<>
<form
className="form-control gap-4 w-full"
onSubmit={(e) => {
e.preventDefault();
handleSubmit();
}}
>
<div className="flex flex-col">
<label className="label" htmlFor="description">
Description
</label>
<textarea
disabled={disabled}
id="description"
className="textarea textarea-bordered textarea-primary"
value={description}
onChange={(e) => {
setDescription(e.target.value);
validateDescription(e.target.value);
}}
/>
<ErrorLabel error={descriptionError} />
</div>
<button className="btn btn-primary">Apply</button>
</form>
<ErrorLabel error={applyError} />
</>
);
}
export default GymApplication;
import GymApplication from "@/components/gym/GymApplication";
import config from "@/utils/config";
import { useGym } from "@/utils/context/GymProvider";
import { useParams } from "react-router-dom";
function GymIndividual() {
const { id } = useParams();
const { data, status } = useGym(Number(id ?? 1));
if (!data || status !== "success") {
const { data: gym, status } = useGym(Number(id ?? 1));
if (status !== "success") {
return "Loading...";
}
if (!gym) {
return "Gym does not exist";
}
return (
<div className="w-full flex flex-col max-w-7xl mx-auto">
<p>{data.name}</p>
<div className="w-full flex flex-col max-w-5xl mx-auto py-6 gap-4">
<img
src={`${config.GYM_MEDIA_URL}/${gym.pictureId}.jpg`}
className="w-full"
/>
<div className="flex flex-col items-start justify-start text-left">
<h1>{gym.name}</h1>
<p>{gym.monthlyPrice} / month</p>
<p>{gym.averageRating} stars</p>
<p>{gym.cityName}</p>
<p>{gym.description}</p>
</div>
<GymApplication gym={gym} />
</div>
);
}
......
import {
GymApplicationFetched,
GymApplicationReturned,
GymApplicationSent,
} from "../validationSchema/gymApplication";
export async function getGymApplication(): Promise<GymApplicationReturned[]> {
......@@ -8,25 +9,46 @@ export async function getGymApplication(): Promise<GymApplicationReturned[]> {
const myPromise = new Promise<GymApplicationFetched[]>(function (myResolve) {
myResolve([
{
acceptance: true,
acceptance: 0,
application_description: "This is an application",
gym_name: "BruhBruh",
gym_id: 1,
},
{
acceptance: true,
acceptance: 0,
application_description: "This is an application as well",
gym_name: "BruhBruhBruh",
gym_id: 2,
},
]);
});
return (await myPromise).map(
({ acceptance, application_description, gym_name }) => {
({ acceptance, application_description, gym_name, gym_id }) => {
return {
acceptance,
description: application_description,
gymName: gym_name,
gymId: gym_id,
};
}
);
}
export async function applyToGym({
application_description,
gym_id,
gym_name,
}: GymApplicationSent): Promise<GymApplicationReturned> {
// return (await axios.get(`${config.NODE_JS_API}/api/gym/`, header)).data;
const myPromise = new Promise<GymApplicationReturned>(function (myResolve) {
myResolve({
acceptance: 0,
description: application_description,
gymId: gym_id,
gymName: gym_name,
});
});
return myPromise;
}
......@@ -15,7 +15,7 @@ export function useGymApplications() {
return useContext(GymApplicationsContext);
}
function GymProvider({ children }: { children: ReactNode }) {
function GymApplicationProvider({ children }: { children: ReactNode }) {
const { status: gymApplicationsStatus, data: gymApplications } = useQuery(
["applications"],
getGymApplication,
......@@ -37,4 +37,4 @@ function GymProvider({ children }: { children: ReactNode }) {
);
}
export default GymProvider;
export default GymApplicationProvider;
......@@ -23,7 +23,16 @@ export function useAllGyms() {
export function useGym(id: number | null) {
return useQuery(
["gyms", String(id)],
async () => (id ? await getGymById({ id }) : undefined),
async () => {
if (!id) {
return undefined;
}
try {
return await getGymById({ id });
} catch (error) {
return undefined;
}
},
{
cacheTime: 300000,
retry: 3,
......
......@@ -2,17 +2,30 @@ import { z } from "zod";
const gymApplicationFetchedSchema = z.object({
gym_name: z.string(),
acceptance: z.boolean(),
gym_id: z.number(),
acceptance: z.number().max(2),
application_description: z.string(),
});
const gymApplicationReturnedSchema = z.object({
gymName: z.string(),
acceptance: z.boolean(),
gymId: z.number(),
acceptance: z.number().max(2),
description: z.string(),
});
const gymApplicationSentSchema = gymApplicationFetchedSchema
.extend({
trainer_name: z.string().max(50),
trainer_description: z.string().max(255),
username: z.string().max(50),
})
.omit({
acceptance: true,
});
export type GymApplicationFetched = z.infer<typeof gymApplicationFetchedSchema>;
export type GymApplicationReturned = z.infer<
typeof gymApplicationReturnedSchema
>;
export type GymApplicationSent = z.infer<typeof gymApplicationSentSchema>;
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment