Skip to content

Commit

Permalink
i am back babey🤖
Browse files Browse the repository at this point in the history
- application submissions
- missing: prompt for name and mail address
  • Loading branch information
dheidemann committed Sep 21, 2024
1 parent 0ab58df commit d399e26
Show file tree
Hide file tree
Showing 16 changed files with 2,340 additions and 142 deletions.
2 changes: 2 additions & 0 deletions frontend/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import {Toaster} from "@/components/ui/sonner";

const inter = Inter({ subsets: ["latin"] });

Expand All @@ -17,6 +18,7 @@ export default function RootLayout({
return (
<html lang="en">
<body className={inter.className}>{children}</body>
<Toaster />
</html>
);
}
107 changes: 83 additions & 24 deletions frontend/app/registration/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

import { useRouter } from "next/navigation";
import {
AddStudentApplicationForEventDocument,
AddStudentApplicationForEventMutation,
AddStudentApplicationForEventMutationVariables,
NewQuestionResponsePair,
NewUserToEventApplication,
QuestionType,
RegistrationFormDocument,
RegistrationFormQuery,
Expand Down Expand Up @@ -32,6 +37,7 @@ import {
FormItem,
FormMessage,
} from "@/components/ui/form";
import { Toaster, toast } from "sonner";

type Props = {
searchParams: {
Expand Down Expand Up @@ -66,11 +72,17 @@ const Home = ({ searchParams }: Props) => {
const [index, setIndex] = useState(0);
const [loading, setLoading] = useState(true);
const router = useRouter();
const [responses, setResponses] = useState<NewQuestionResponsePair[]>([]);

useEffect(() => {
const fetchData = async () => {
const eventID = searchParams.e;
if (responses.length > 0) {
onSubmit();
}
}, [responses]);

const eventID = searchParams.e;
useEffect(() => {
const fetchData = async () => {
const vars: RegistrationFormQueryVariables = {
eventID: parseInt(eventID),
};
Expand All @@ -92,7 +104,7 @@ const Home = ({ searchParams }: Props) => {
};

fetchData();
}, [searchParams.e, router]);
}, [router]);

useEffect(() => {
if (regForm) {
Expand All @@ -101,14 +113,18 @@ const Home = ({ searchParams }: Props) => {
}, [index, regForm]);

const mcForm = useForm<z.infer<ReturnType<typeof MultipleChoiceFormSchema>>>({
resolver: zodResolver(MultipleChoiceFormSchema(regForm?.questions[index].required!)),
resolver: zodResolver(
MultipleChoiceFormSchema(regForm?.questions[index].required!)
),
defaultValues: {
multipleChoice: [],
},
});

const scForm = useForm<z.infer<ReturnType<typeof SingleChoiceFormSchema>>>({
resolver: zodResolver(SingleChoiceFormSchema(regForm?.questions[index].required!)),
resolver: zodResolver(
SingleChoiceFormSchema(regForm?.questions[index].required!)
),
defaultValues: {
singleChoice: undefined,
},
Expand All @@ -118,36 +134,79 @@ const Home = ({ searchParams }: Props) => {
router.push("/");
}

const FooterButtons = () => (
<div className="flex justify-between w-full">
<Button onClick={handleQuit} variant="outline" className="w-auto">
Abbrechen
</Button>
<Button type="submit" className="w-auto">
{regForm?.questions.length !== index + 1 ? "Nächste Frage" : "Anmelden"}
</Button>
</div>
);

function onSubmit() {
const onSubmit = async () => {
if (regForm?.questions.length !== index + 1) {
setIndex((prevIndex) => prevIndex + 1);
return;
}
}

await new Promise((resolve) => setTimeout(resolve, 250));

const application: NewUserToEventApplication = {
// TODO
userMail: "[email protected]",
eventID: +eventID,
answers: responses,
};

const vars: AddStudentApplicationForEventMutationVariables = {
application: application,
};

try {
await client.request<AddStudentApplicationForEventMutation>(
AddStudentApplicationForEventDocument,
vars
);
toast("Anmeldung abgeschickt!");
handleQuit();
} catch (err) {
toast("Ein Fehler ist aufgetreten");
console.error(err)
}
};

function onScaleSubmit() {
onSubmit();
const res: NewQuestionResponsePair = {
questionID: regForm?.questions[index].ID || 0,
value: String(sliderValue),
};
setResponses((prevResponses) => [...prevResponses, res]);

setSliderValue(0);
}

function onMCSubmit(data: z.infer<ReturnType<typeof MultipleChoiceFormSchema>>) {
onSubmit();
function onMCSubmit(
data: z.infer<ReturnType<typeof MultipleChoiceFormSchema>>
) {
const newResponses = data.multipleChoice!.map((id) => ({
questionID: regForm?.questions[index].ID || 0,
answerID: id,
}));
setResponses((prevResponses) => [...prevResponses, ...newResponses]);
}

function onSCSubmit(data: z.infer<ReturnType<typeof SingleChoiceFormSchema>>) {
onSubmit();
function onSCSubmit(
data: z.infer<ReturnType<typeof SingleChoiceFormSchema>>
) {
const res: NewQuestionResponsePair = {
questionID: regForm?.questions[index].ID || 0,
answerID: data.singleChoice!,
};
setResponses((prevResponses) => [...prevResponses, res]);
}

const FooterButtons = () => (
<div className="flex justify-between w-full">
<Button onClick={handleQuit} variant="outline" className="w-auto">
Abbrechen
</Button>
<Button type="submit" className="w-auto">
{regForm?.questions.length !== index + 1 ? "Nächste Frage" : "Anmelden"}
</Button>
</div>
);

if (loading) {
return <div>Loading...</div>;
}
Expand Down Expand Up @@ -195,7 +254,7 @@ const Home = ({ searchParams }: Props) => {
onCheckedChange={(checked) => {
return checked
? field.onChange([
...field.value || [],
...(field.value || []),
answer.ID,
])
: field.onChange(
Expand Down
31 changes: 31 additions & 0 deletions frontend/components/ui/sonner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"use client"

import { useTheme } from "next-themes"
import { Toaster as Sonner } from "sonner"

type ToasterProps = React.ComponentProps<typeof Sonner>

const Toaster = ({ ...props }: ToasterProps) => {
const { theme = "system" } = useTheme()

return (
<Sonner
theme={theme as ToasterProps["theme"]}
className="toaster group"
toastOptions={{
classNames: {
toast:
"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
description: "group-[.toast]:text-muted-foreground",
actionButton:
"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
cancelButton:
"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
},
}}
{...props}
/>
)
}

export { Toaster }
9 changes: 7 additions & 2 deletions frontend/lib/gql/generated/gql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/
* Therefore it is highly recommended to use the babel or swc plugin for production.
*/
const documents = {
"mutation addStudentApplicationForEvent($application: NewUserToEventApplication!) {\n addStudentApplicationForEvent(application: $application) {\n fn\n }\n}": types.AddStudentApplicationForEventDocument,
"mutation addTutor($firstName: String!, $lastName: String!, $email: String!, $eventsAvailable: [Int!]!) {\n addTutor(\n tutor: {fn: $firstName, sn: $lastName, mail: $email}\n availability: {userMail: $email, eventID: $eventsAvailable}\n ) {\n fn\n }\n}": types.AddTutorDocument,
"query tutorFormEvents {\n events(needsTutors: true, onlyFuture: true) {\n ID\n title\n from\n to\n topic {\n name\n color\n }\n type {\n name\n color\n }\n }\n}": types.TutorFormEventsDocument,
"query registrationForm($eventID: Int!) {\n forms(id: [$eventID]) {\n title\n description\n questions {\n title\n type\n required\n answers {\n ID\n title\n points\n }\n }\n }\n}": types.RegistrationFormDocument,
"query registrationForm($eventID: Int!) {\n forms(id: [$eventID]) {\n title\n description\n questions {\n ID\n title\n type\n required\n answers {\n ID\n title\n points\n }\n }\n }\n}": types.RegistrationFormDocument,
};

/**
Expand All @@ -32,6 +33,10 @@ const documents = {
*/
export function graphql(source: string): unknown;

/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "mutation addStudentApplicationForEvent($application: NewUserToEventApplication!) {\n addStudentApplicationForEvent(application: $application) {\n fn\n }\n}"): (typeof documents)["mutation addStudentApplicationForEvent($application: NewUserToEventApplication!) {\n addStudentApplicationForEvent(application: $application) {\n fn\n }\n}"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
Expand All @@ -43,7 +48,7 @@ export function graphql(source: "query tutorFormEvents {\n events(needsTutors:
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "query registrationForm($eventID: Int!) {\n forms(id: [$eventID]) {\n title\n description\n questions {\n title\n type\n required\n answers {\n ID\n title\n points\n }\n }\n }\n}"): (typeof documents)["query registrationForm($eventID: Int!) {\n forms(id: [$eventID]) {\n title\n description\n questions {\n title\n type\n required\n answers {\n ID\n title\n points\n }\n }\n }\n}"];
export function graphql(source: "query registrationForm($eventID: Int!) {\n forms(id: [$eventID]) {\n title\n description\n questions {\n ID\n title\n type\n required\n answers {\n ID\n title\n points\n }\n }\n }\n}"): (typeof documents)["query registrationForm($eventID: Int!) {\n forms(id: [$eventID]) {\n title\n description\n questions {\n ID\n title\n type\n required\n answers {\n ID\n title\n points\n }\n }\n }\n}"];

export function graphql(source: string) {
return (documents as any)[source] ?? {};
Expand Down
Loading

0 comments on commit d399e26

Please sign in to comment.