diff --git a/app/app/(dashboard)/dashboard/cadet/[login]/_components/json-data/index.tsx b/app/app/(dashboard)/dashboard/cadet/[login]/_components/json-data/index.tsx index 0a0ec94..54477ad 100644 --- a/app/app/(dashboard)/dashboard/cadet/[login]/_components/json-data/index.tsx +++ b/app/app/(dashboard)/dashboard/cadet/[login]/_components/json-data/index.tsx @@ -1,18 +1,22 @@ -import { Button } from "@/components/ui/button"; +import { buttonVariants } from "@/components/ui/button"; import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@/components/ui/collapsible"; +import { cn } from "@/lib/utils"; import { BracesIcon } from "lucide-react"; export const JsonData = ({ data }: { data: object }) => { return ( - - + + JSON
{JSON.stringify(data, null, 2)}
diff --git a/app/app/(dashboard)/dashboard/cadet/[login]/_components/wallet-form/actions.ts b/app/app/(dashboard)/dashboard/cadet/[login]/_components/wallet-form/actions.ts new file mode 100644 index 0000000..8783eb5 --- /dev/null +++ b/app/app/(dashboard)/dashboard/cadet/[login]/_components/wallet-form/actions.ts @@ -0,0 +1,25 @@ +"use server"; + +import { transactions } from "@/lib/intra/users"; +import { SAResponse } from "@/types/sa-response"; +import { IAddAlt } from "./types"; +import { revalidateTag } from "next/cache"; + +/** + * Adds an alternative money + * @param payload - The payload + * @returns A promise that resolves to a SAResponse object with a boolean indicating the success of the operation. + */ +export async function addAlt(payload: IAddAlt): Promise> { + try { + const r = await transactions({ + ...payload, + transactable_type: "Tuteur api", + reason: "cadeau", + }); + revalidateTag(payload.login); + return { data: true, error: null }; + } catch (e) { + return { data: null, error: "Failed to add Alt" }; + } +} diff --git a/app/app/(dashboard)/dashboard/cadet/[login]/_components/wallet-form/index.tsx b/app/app/(dashboard)/dashboard/cadet/[login]/_components/wallet-form/index.tsx new file mode 100644 index 0000000..d55d918 --- /dev/null +++ b/app/app/(dashboard)/dashboard/cadet/[login]/_components/wallet-form/index.tsx @@ -0,0 +1,98 @@ +"use client"; + +import { zodResolver } from "@hookform/resolvers/zod"; +import { useForm } from "react-hook-form"; +import { z } from "zod"; + +import { Button } from "@/components/ui/button"; +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form"; +import { Input } from "@/components/ui/input"; +import { addAlt } from "./actions"; +import { IWalletForm } from "./types"; +import { toast } from "sonner"; +import { useState } from "react"; +const FormSchema = z.object({ + value: z.coerce.number().int(), +}); + +export function WalletForm(props: IWalletForm) { + const [currentValue, setCurrentValue] = useState(props.currentValue); + const [prevValue, setPrevValue] = useState(props.currentValue); + const [isPending, setIsPending] = useState(false); + const form = useForm>({ + resolver: zodResolver(FormSchema), + defaultValues: { + value: 0, + }, + }); + + async function onSubmit(data: z.infer) { + if (data.value === 0) { + toast.error("Why are you tring to add 0?"); + return; + } + setIsPending(true); + setPrevValue(currentValue); + setCurrentValue(currentValue + data.value); + const { data: respData, error } = await addAlt({ + value: data.value, + user_id: props.user_id, + login: props.login, + }); + if (error) { + setCurrentValue(prevValue); + setIsPending(false); + toast.error(error); + } else if (respData) { + setIsPending(false); + toast.success("Alt added"); + form.reset(); + } + } + + return ( +
+ + ( + + Add, or remove $Alt +
+ + + + + +
+ +
+ )} + /> + + + ); +} diff --git a/app/app/(dashboard)/dashboard/cadet/[login]/_components/wallet-form/types.ts b/app/app/(dashboard)/dashboard/cadet/[login]/_components/wallet-form/types.ts new file mode 100644 index 0000000..d13ea99 --- /dev/null +++ b/app/app/(dashboard)/dashboard/cadet/[login]/_components/wallet-form/types.ts @@ -0,0 +1,11 @@ +export interface IAddAlt { + value: number; + user_id: number; + login: string; +} + +export interface IWalletForm { + currentValue: number; + user_id: number; + login: string; +} diff --git a/app/app/(dashboard)/dashboard/cadet/[login]/page.tsx b/app/app/(dashboard)/dashboard/cadet/[login]/page.tsx index cd39ae6..2dee5d9 100644 --- a/app/app/(dashboard)/dashboard/cadet/[login]/page.tsx +++ b/app/app/(dashboard)/dashboard/cadet/[login]/page.tsx @@ -1,6 +1,9 @@ import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { fetchUser } from "@/lib/intra/users"; import { JsonData } from "./_components/json-data"; +import { WalletForm } from "./_components/wallet-form"; +import { Separator } from "@/components/ui/separator"; +import { CircleUserIcon, MailIcon, UserIcon } from "lucide-react"; export default async function Page({ params }: { params: { login: string } }) { const { login } = params; @@ -10,26 +13,44 @@ export default async function Page({ params }: { params: { login: string } }) { } catch (e) { return
Not Found
; } + const walletFormProps = { + currentValue: user.wallet, + user_id: user.id, + login: user.login, + }; return (
-
-
-
- - - - {user.login} - - + +
+
+ + + + {user.login} + + +
+
+
+ +

{user.login}

-
-

{user.login}

+
+

{user.displayname}

+
+
+

{user.email}

-
+ +
+ +
+ +
); } diff --git a/app/app/layout.tsx b/app/app/layout.tsx index bf5e91d..dd363dd 100644 --- a/app/app/layout.tsx +++ b/app/app/layout.tsx @@ -1,7 +1,8 @@ -import type { Metadata } from "next"; -import { Inter as FontSans } from "next/font/google"; +import { Toaster } from "@/components/ui/sonner"; import { cn } from "@/lib/utils"; import "@/styles/globals.css"; +import type { Metadata } from "next"; +import { Inter as FontSans } from "next/font/google"; const fontSans = FontSans({ subsets: ["latin"], @@ -26,6 +27,7 @@ export default function RootLayout({ )} > {children} + ); diff --git a/app/types/sa-response.ts b/app/types/sa-response.ts new file mode 100644 index 0000000..fd22c19 --- /dev/null +++ b/app/types/sa-response.ts @@ -0,0 +1,7 @@ +/** + * Represents a response object for Server Actions. + * @template T - The type of the data. + */ +export type SAResponse = + | { data: T; error: null } + | { data: null; error: string };