diff --git a/app/(dashboard)/parental-control/page.tsx b/app/(dashboard)/parental-control/page.tsx index ab1474c..09dc0be 100644 --- a/app/(dashboard)/parental-control/page.tsx +++ b/app/(dashboard)/parental-control/page.tsx @@ -1,18 +1,22 @@ +import { Suspense } from "react"; import { DevicesTable } from "@/components/devices-table"; import Search from "@/components/search"; -import { Suspense } from "react"; export default async function ParentalControl({ searchParams, }: { searchParams: Promise<{ - query: string; page: number; sortBy: string; status: string; }>; }) { - const query = (await searchParams)?.query || ""; + + const parentalControlFilters = { + is_active: "true", + has_a_pending_payment: "false", + }; + return (
@@ -25,10 +29,11 @@ export default async function ParentalControl({ >
- +
diff --git a/app/(dashboard)/payments/page.tsx b/app/(dashboard)/payments/page.tsx index 1b8e60d..2b6f207 100644 --- a/app/(dashboard)/payments/page.tsx +++ b/app/(dashboard)/payments/page.tsx @@ -1,7 +1,4 @@ -import { redirect } from "next/navigation"; -import { getServerSession } from "next-auth"; import { Suspense } from "react"; -import { authOptions } from "@/app/auth"; import { PaymentsTable } from "@/components/payments-table"; import Search from "@/components/search"; @@ -16,10 +13,7 @@ export default async function Payments({ }>; }) { const query = (await searchParams)?.query || ""; - const session = await getServerSession(authOptions); - if (session?.user?.is_admin) { - return redirect("/user-payments"); - } + return (
diff --git a/components/block-device-dialog.tsx b/components/block-device-dialog.tsx index e1fb9b6..55d1f89 100644 --- a/components/block-device-dialog.tsx +++ b/components/block-device-dialog.tsx @@ -1,12 +1,9 @@ "use client"; - -import { zodResolver } from "@hookform/resolvers/zod"; -import { OctagonX } from "lucide-react"; -import { useState } from "react"; -import { type SubmitHandler, useForm } from "react-hook-form"; +import { DialogDescription } from "@radix-ui/react-dialog"; +import { OctagonX, ShieldBan } from "lucide-react"; +import { useActionState, useEffect, useState, useTransition } from "react"; import { toast } from "sonner"; -import { z } from "zod"; import { Button } from "@/components/ui/button"; import { Dialog, @@ -19,160 +16,146 @@ import { import { Label } from "@/components/ui/label"; import type { Device } from "@/lib/backend-types"; import { cn } from "@/lib/utils"; -import { blockDevice } from "@/queries/devices"; +import { blockDeviceAction } from "@/queries/devices"; import { TextShimmer } from "./ui/text-shimmer"; import { Textarea } from "./ui/textarea"; -const validationSchema = z.object({ - reasonForBlocking: z.string().min(5, { message: "Reason is required" }), -}); +export type BlockDeviceFormState = { + message: string; + success: boolean; + fieldErrors?: { + reason_for_blocking?: string[]; + }; + payload?: FormData; +}; + +const initialState: BlockDeviceFormState = { + message: "", + success: false, + fieldErrors: {}, +}; export default function BlockDeviceDialog({ device, - admin, -}: { device: Device; type: "block" | "unblock"; admin?: boolean }) { - const [disabled, setDisabled] = useState(false); + // admin, + parentalControl = false, +}: { + device: Device; + type: "block" | "unblock"; + admin?: boolean; + parentalControl?: boolean; +}) { const [open, setOpen] = useState(false); - const { - register, - handleSubmit, - formState: { errors }, - } = useForm>({ - resolver: zodResolver(validationSchema), - }); + const [state, formAction, isPending] = useActionState(blockDeviceAction, initialState); + const [isTransitioning, startTransition] = useTransition(); - const onSubmit: SubmitHandler> = (data) => { - setDisabled(true); - console.log(data); - toast.promise( - blockDevice({ - deviceId: String(device.id), - reason_for_blocking: data.reasonForBlocking, - blocked_by: "ADMIN", - }), - { - loading: "Blocking...", - success: () => { - setDisabled(false); - setOpen((prev) => !prev); - return "Blocked!"; - }, - error: (error) => { - setDisabled(false); - return error || "Something went wrong"; - }, - }, - ); - setDisabled(false); + const handleSimpleBlock = () => { + startTransition(() => { + const formData = new FormData(); + formData.append("deviceId", String(device.id)); + formData.append("reason_for_blocking", ""); + formData.append("action", "simple-block"); + formData.append("blocked_by", "PARENT"); + + formAction(formData); + }); }; + const handleUnblock = () => { + startTransition(() => { + const formData = new FormData(); + formData.append("deviceId", String(device.id)); + formData.append("reason_for_blocking", ""); + formData.append("action", "unblock"); + formData.append("blocked_by", "PARENT"); + + formAction(formData); + }); + }; + + // Show toast notifications based on state changes + useEffect(() => { + if (state.message) { + if (state.success) { + toast.success(state.message); + if (open) setOpen(false); + } else { + toast.error(state.message); + } + } + }, [state, open]); + + const isLoading = isPending || isTransitioning; + + // If device is blocked and user is not admin, show unblock button + if (device.blocked && parentalControl) { + return ( + + ); + } + + // If device is not blocked and user is not admin, show simple block button + if (!device.blocked && parentalControl) { + return ( + + ); + } + + // If user is admin, show block with reason dialog return (
- {device.blocked ? ( - - ) : ( -
- {!admin ? ( - - ) : ( - - - - - - - - Please provide a reason for blocking this device. - - -
-
-
- -