TEMPORARY FIX TO TEST BUILD
Some checks failed
Build and Push Docker Images / Build and Push Docker Images (push) Failing after 1m15s

This commit is contained in:
i701 2025-04-10 23:18:19 +05:00
parent e8296ae3f6
commit b932fcf03c
Signed by: i701
GPG Key ID: 54A0DA1E26D8E587
49 changed files with 8314 additions and 8858 deletions

View File

@ -1,6 +1,4 @@
import SignUpForm from "@/components/auth/signup-form"; import SignUpForm from "@/components/auth/signup-form";
import type { ApiResponse, Atoll, Island } from "@/lib/backend-types";
import { getAtolls } from "@/queries/islands";
import Image from "next/image"; import Image from "next/image";
import { redirect } from "next/navigation"; import { redirect } from "next/navigation";
@ -9,18 +7,23 @@ export default async function SignupPage({
}: { }: {
searchParams: Promise<{ phone_number: string }>; searchParams: Promise<{ phone_number: string }>;
}) { }) {
const phone_number = (await searchParams).phone_number; const phone_number = (await searchParams).phone_number;
console.log({ phone_number }) console.log({ phone_number });
if (!phone_number) { if (!phone_number) {
return redirect("/auth/login"); return redirect("/auth/login");
} }
return ( return (
<div className="dark:bg-black w-full h-screen flex items-center justify-center font-sans"> <div className="dark:bg-black w-full h-screen flex items-center justify-center font-sans">
<div className="flex flex-col items-center justify-center w-full h-full "> <div className="flex flex-col items-center justify-center w-full h-full ">
<Image priority alt="Sar Link Logo" src="/logo.png" width={100} height={100} style={{ width: "auto", height: "auto" }} /> <Image
priority
alt="Sar Link Logo"
src="/logo.png"
width={100}
height={100}
style={{ width: "auto", height: "auto" }}
/>
<div className="mt-4 flex flex-col items-center justify-center"> <div className="mt-4 flex flex-col items-center justify-center">
<h4 className="font-bold text-xl text-gray-600">SAR Link Portal</h4> <h4 className="font-bold text-xl text-gray-600">SAR Link Portal</h4>
<p className="text-gray-500"> <p className="text-gray-500">

View File

@ -2,10 +2,8 @@ import { getPayment } from "@/actions/payment";
import { authOptions } from "@/app/auth"; import { authOptions } from "@/app/auth";
import CancelPaymentButton from "@/components/billing/cancel-payment-button"; import CancelPaymentButton from "@/components/billing/cancel-payment-button";
import DevicesToPay from "@/components/devices-to-pay"; import DevicesToPay from "@/components/devices-to-pay";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { tryCatch } from "@/utils/tryCatch"; import { tryCatch } from "@/utils/tryCatch";
import { Trash2 } from "lucide-react";
import { getServerSession } from "next-auth"; import { getServerSession } from "next-auth";
export default async function PaymentPage({ export default async function PaymentPage({
params, params,

View File

@ -1,11 +1,3 @@
import InputReadOnly from "@/components/input-read-only";
import { Badge } from "@/components/ui/badge";
import UserRejectDialog from "@/components/user/user-reject-dialog";
import { UserVerifyDialog } from "@/components/user/user-verify-dialog";
import { getNationalPerson } from "@/lib/person";
import Image from "next/image";
export default async function VerifyUserPage({ export default async function VerifyUserPage({
params, params,
}: { }: {
@ -14,6 +6,7 @@ export default async function VerifyUserPage({
}>; }>;
}) { }) {
const userId = (await params).userId; const userId = (await params).userId;
console.log("userId", userId);
// const dbUser = await prisma.user.findUnique({ // const dbUser = await prisma.user.findUnique({
// where: { // where: {
// id: userId, // id: userId,

View File

@ -1,4 +1,3 @@
import { Rejectuser } from "@/actions/user-actions";
import Filter from "@/components/filter"; import Filter from "@/components/filter";
import Search from "@/components/search"; import Search from "@/components/search";
import { UsersTable } from "@/components/user-table"; import { UsersTable } from "@/components/user-table";
@ -9,8 +8,7 @@ import {
Hourglass, Hourglass,
Minus, Minus,
} from "lucide-react"; } from "lucide-react";
import { redirect } from "next/navigation"; import { Suspense } from "react";
import React, { Suspense } from "react";
const sortfilterOptions = [ const sortfilterOptions = [
{ {

View File

@ -1,10 +1,5 @@
import { blockDevice } from "@/actions/omada-actions";
import { validateApiKey } from "@/lib/utils";
import { addDays, addMonths, isAfter, isWithinInterval } from "date-fns";
const lastRunTime = new Date();
export async function GET(request: Request) { export async function GET(request: Request) {
console.log(request.url);
return Response.json({ message: "Request received" }); return Response.json({ message: "Request received" });
// try { // try {
// // Validate API key before proceeding // // Validate API key before proceeding

6
app/next-auth.d.ts vendored
View File

@ -1,5 +1,7 @@
import NextAuth, { DefaultSession, type User } from "next-auth"; /* eslint-disable @typescript-eslint/no-unused-vars */
import { Session } from "next-auth"; // @ts-expect-error importing unused types are required here
import NextAuth, { DefaultSession, type User, Session } from "next-auth";
/* eslint-enable @typescript-eslint/no-unused-vars */
declare module "next-auth" { declare module "next-auth" {
/** /**
* Returned by `useSession`, `getSession` and received as a prop on the `SessionProvider` React Context * Returned by `useSession`, `getSession` and received as a prop on the `SessionProvider` React Context

View File

@ -1,18 +1,18 @@
import { // import {
Table, // Table,
TableBody, // TableBody,
TableCaption, // TableCaption,
TableCell, // TableCell,
TableFooter, // TableFooter,
TableHead, // TableHead,
TableHeader, // TableHeader,
TableRow, // TableRow,
} from "@/components/ui/table"; // } from "@/components/ui/table";
import { headers } from "next/headers"; // import { headers } from "next/headers";
import Link from "next/link"; // import Link from "next/link";
import BlockDeviceDialog from "../block-device-dialog"; // import BlockDeviceDialog from "../block-device-dialog";
import DeviceCard from "../device-card"; // import DeviceCard from "../device-card";
import Pagination from "../pagination"; // import Pagination from "../pagination";
export async function AdminDevicesTable({ export async function AdminDevicesTable({
searchParams, searchParams,
@ -25,12 +25,14 @@ export async function AdminDevicesTable({
}>; }>;
parentalControl?: boolean; parentalControl?: boolean;
}) { }) {
console.log(parentalControl);
// const session = await auth.api.getSession({ // const session = await auth.api.getSession({
// headers: await headers(), // headers: await headers(),
// }); // });
// const isAdmin = session?.user.role === "ADMIN"; // const isAdmin = session?.user.role === "ADMIN";
// const query = (await searchParams)?.query || ""; const query = (await searchParams)?.query || "";
// const page = (await searchParams)?.page; const page = (await searchParams)?.page;
console.log(query, page);
// const sortBy = (await searchParams)?.sortBy || "asc"; // const sortBy = (await searchParams)?.sortBy || "asc";
// const totalDevices = await prisma.device.count({ // const totalDevices = await prisma.device.count({
// where: { // where: {

View File

@ -1,17 +1,17 @@
import Pagination from "@/components/pagination"; // import Pagination from "@/components/pagination";
import { Badge } from "@/components/ui/badge"; // import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button"; // import { Button } from "@/components/ui/button";
import { // import {
Table, // Table,
TableBody, // TableBody,
TableCaption, // TableCaption,
TableCell, // TableCell,
TableFooter, // TableFooter,
TableHead, // TableHead,
TableHeader, // TableHeader,
TableRow, // TableRow,
} from "@/components/ui/table"; // } from "@/components/ui/table";
import Link from "next/link"; // import Link from "next/link";
export async function UsersPaymentsTable({ export async function UsersPaymentsTable({
searchParams, searchParams,
@ -24,8 +24,9 @@ export async function UsersPaymentsTable({
}>; }>;
}) { }) {
const query = (await searchParams)?.query || ""; const query = (await searchParams)?.query || "";
const page = (await searchParams)?.page; console.log(query);
const sortBy = (await searchParams)?.sortBy || "asc"; // const page = (await searchParams)?.page;
// const sortBy = (await searchParams)?.sortBy || "asc";
// const totalPayments = await prisma.payment.count({ // const totalPayments = await prisma.payment.count({
// where: { // where: {
// OR: [ // OR: [

View File

@ -7,13 +7,11 @@ import {
} from "@/components/ui/popover"; } from "@/components/ui/popover";
import { Loader2, User as UserIcon } from "lucide-react"; import { Loader2, User as UserIcon } from "lucide-react";
import { signOut, useSession } from "next-auth/react"; import { signOut, useSession } from "next-auth/react";
import { useRouter } from "next/navigation";
import { useState } from "react"; import { useState } from "react";
export function AccountPopover() { export function AccountPopover() {
const session = useSession(); const session = useSession();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const router = useRouter();
if (session.status === "loading") { if (session.status === "loading") {
<Button variant={"outline"} disabled> <Button variant={"outline"} disabled>

View File

@ -23,7 +23,7 @@ import { getAtolls } from "@/queries/islands";
import { keepPreviousData, useQuery } from "@tanstack/react-query"; import { keepPreviousData, useQuery } from "@tanstack/react-query";
export default function SignUpForm() { export default function SignUpForm() {
const { data: atolls, isFetching } = useQuery<ApiResponse<Atoll>>({ const { data: atolls } = useQuery<ApiResponse<Atoll>>({
queryKey: ["ATOLLS"], queryKey: ["ATOLLS"],
queryFn: () => getAtolls(), queryFn: () => getAtolls(),
placeholderData: keepPreviousData, placeholderData: keepPreviousData,

View File

@ -17,7 +17,8 @@ export default function CancelPaymentButton({
<Button <Button
onClick={async () => { onClick={async () => {
setLoading(true); setLoading(true);
const [error, _] = await tryCatch(cancelPayment({ id: paymentId })); const [error, x] = await tryCatch(cancelPayment({ id: paymentId }));
console.log(x);
if (error) { if (error) {
toast.error(error.message); toast.error(error.message);
setLoading(false); setLoading(false);

View File

@ -3,7 +3,6 @@ import { TableCell, TableRow } from "@/components/ui/table";
import { deviceCartAtom } from "@/lib/atoms"; import { deviceCartAtom } from "@/lib/atoms";
import type { Device } from "@/lib/backend-types"; import type { Device } from "@/lib/backend-types";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { pl } from "date-fns/locale";
import { useAtom } from "jotai"; import { useAtom } from "jotai";
import { Hourglass } from "lucide-react"; import { Hourglass } from "lucide-react";
import Link from "next/link"; import Link from "next/link";

View File

@ -5,18 +5,16 @@ import DeviceCard from "@/components/device-card";
import NumberInput from "@/components/number-input"; import NumberInput from "@/components/number-input";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { deviceCartAtom, numberOfMonths } from "@/lib/atoms"; import { deviceCartAtom, numberOfMonths } from "@/lib/atoms";
import type { NewPayment, Payment } from "@/lib/backend-types"; import type { NewPayment } from "@/lib/backend-types";
import { tryCatch } from "@/utils/tryCatch"; import { tryCatch } from "@/utils/tryCatch";
import { useAtom, useAtomValue, useSetAtom } from "jotai"; import { useAtom, useAtomValue, useSetAtom } from "jotai";
import { CircleDollarSign, Loader2 } from "lucide-react"; import { CircleDollarSign, Loader2 } from "lucide-react";
import { useSession } from "next-auth/react";
import { redirect, usePathname } from "next/navigation"; import { redirect, usePathname } from "next/navigation";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { toast } from "sonner"; import { toast } from "sonner";
export default function DevicesForPayment() { export default function DevicesForPayment() {
const baseAmount = 100; const baseAmount = 100;
const discountPercentage = 75; const discountPercentage = 75;
const session = useSession();
const pathname = usePathname(); const pathname = usePathname();
const devices = useAtomValue(deviceCartAtom); const devices = useAtomValue(deviceCartAtom);
const setDeviceCart = useSetAtom(deviceCartAtom); const setDeviceCart = useSetAtom(deviceCartAtom);
@ -24,6 +22,7 @@ export default function DevicesForPayment() {
const [message, setMessage] = useState(""); const [message, setMessage] = useState("");
const [disabled, setDisabled] = useState(false); const [disabled, setDisabled] = useState(false);
const [total, setTotal] = useState(0); const [total, setTotal] = useState(0);
console.log(total);
useEffect(() => { useEffect(() => {
if (months === 7) { if (months === 7) {
setMessage("You will get 1 month free."); setMessage("You will get 1 month free.");

View File

@ -35,7 +35,7 @@ export async function DevicesTable({
if (error) { if (error) {
return <pre>{JSON.stringify(error, null, 2)}</pre>; return <pre>{JSON.stringify(error, null, 2)}</pre>;
} }
const { meta, links, data } = devices; const { meta, data } = devices;
return ( return (
<div> <div>
{data.length === 0 ? ( {data.length === 0 ? (

View File

@ -9,7 +9,6 @@ import {
TableRow, TableRow,
} from "@/components/ui/table"; } from "@/components/ui/table";
import type { Payment } from "@/lib/backend-types"; import type { Payment } from "@/lib/backend-types";
import { formatDate } from "@/lib/utils";
import { import {
BadgeDollarSign, BadgeDollarSign,
Clipboard, Clipboard,
@ -26,6 +25,7 @@ export default function DevicesToPay({
payment, payment,
user, user,
}: { payment?: Payment; user?: User }) { }: { payment?: Payment; user?: User }) {
console.log(user);
const [verifying, setVerifying] = useState(false); const [verifying, setVerifying] = useState(false);
const devices = payment?.devices; const devices = payment?.devices;

View File

@ -93,7 +93,7 @@ export async function PaymentsTable({
return <pre>{JSON.stringify(error, null, 2)}</pre>; return <pre>{JSON.stringify(error, null, 2)}</pre>;
} }
} }
const { data, meta, links } = payments; const { data, meta } = payments;
return ( return (
<div> <div>
{data?.length === 0 ? ( {data?.length === 0 ? (

View File

@ -55,7 +55,6 @@ type Categories = {
}[]; }[];
export async function AppSidebar({ export async function AppSidebar({
role,
...props ...props
}: React.ComponentProps<typeof Sidebar>) { }: React.ComponentProps<typeof Sidebar>) {
const categories = [ const categories = [

View File

@ -1,12 +1,12 @@
"use client" "use client";
import { ChevronLeft, ChevronRight } from "lucide-react" import { ChevronLeft, ChevronRight } from "lucide-react";
import { DayPicker } from "react-day-picker" import { DayPicker } from "react-day-picker";
import { buttonVariants } from "@/components/ui/button" import { buttonVariants } from "@/components/ui/button";
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils";
export type CalendarProps = React.ComponentProps<typeof DayPicker> export type CalendarProps = React.ComponentProps<typeof DayPicker>;
function Calendar({ function Calendar({
className, className,
@ -26,7 +26,7 @@ function Calendar({
nav: "space-x-1 flex items-center", nav: "space-x-1 flex items-center",
nav_button: cn( nav_button: cn(
buttonVariants({ variant: "outline" }), buttonVariants({ variant: "outline" }),
"h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100" "h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100",
), ),
nav_button_previous: "absolute left-1", nav_button_previous: "absolute left-1",
nav_button_next: "absolute right-1", nav_button_next: "absolute right-1",
@ -39,11 +39,11 @@ function Calendar({
"relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-accent [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected].day-range-end)]:rounded-r-md", "relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-accent [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected].day-range-end)]:rounded-r-md",
props.mode === "range" props.mode === "range"
? "[&:has(>.day-range-end)]:rounded-r-md [&:has(>.day-range-start)]:rounded-l-md first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md" ? "[&:has(>.day-range-end)]:rounded-r-md [&:has(>.day-range-start)]:rounded-l-md first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md"
: "[&:has([aria-selected])]:rounded-md" : "[&:has([aria-selected])]:rounded-md",
), ),
day: cn( day: cn(
buttonVariants({ variant: "ghost" }), buttonVariants({ variant: "ghost" }),
"h-8 w-8 p-0 font-normal aria-selected:opacity-100" "h-8 w-8 p-0 font-normal aria-selected:opacity-100",
), ),
day_range_start: "day-range-start", day_range_start: "day-range-start",
day_range_end: "day-range-end", day_range_end: "day-range-end",
@ -59,13 +59,14 @@ function Calendar({
...classNames, ...classNames,
}} }}
components={{ components={{
// @ts-expect-error this works but types are not correct
IconLeft: () => <ChevronLeft className="h-4 w-4" />, IconLeft: () => <ChevronLeft className="h-4 w-4" />,
IconRight: () => <ChevronRight className="h-4 w-4" />, IconRight: () => <ChevronRight className="h-4 w-4" />,
}} }}
{...props} {...props}
/> />
) );
} }
Calendar.displayName = "Calendar" Calendar.displayName = "Calendar";
export { Calendar } export { Calendar };

View File

@ -1,17 +1,17 @@
import { // import {
Table, // Table,
TableBody, // TableBody,
TableCaption, // TableCaption,
TableCell, // TableCell,
TableFooter, // TableFooter,
TableHead, // TableHead,
TableHeader, // TableHeader,
TableRow, // TableRow,
} from "@/components/ui/table"; // } from "@/components/ui/table";
import Link from "next/link"; // import Link from "next/link";
import Pagination from "./pagination"; // import Pagination from "./pagination";
import { Badge } from "./ui/badge"; // import { Badge } from "./ui/badge";
import { Button } from "./ui/button"; // import { Button } from "./ui/button";
export async function UsersTable({ export async function UsersTable({
searchParams, searchParams,
@ -24,9 +24,10 @@ export async function UsersTable({
}>; }>;
}) { }) {
const query = (await searchParams)?.query || ""; const query = (await searchParams)?.query || "";
const page = (await searchParams)?.page; console.log(query);
const sortBy = (await searchParams)?.sortBy || "asc"; // const page = (await searchParams)?.page;
const verified = (await searchParams)?.status || "all"; // const sortBy = (await searchParams)?.sortBy || "asc";
// const verified = (await searchParams)?.status || "all";
// const totalUsers = await prisma.user.count({ // const totalUsers = await prisma.user.count({
// where: { // where: {
// OR: [ // OR: [

View File

@ -62,6 +62,7 @@ export default function AddDeviceDialogForm({ user_id }: { user_id?: string }) {
toast.error(error.message || "Something went wrong."); toast.error(error.message || "Something went wrong.");
setDisabled(false); setDisabled(false);
} else { } else {
console.log(response);
setOpen(false); setOpen(false);
setDisabled(false); setDisabled(false);
toast.success("Device successfully added!"); toast.success("Device successfully added!");

View File

@ -1,7 +1,7 @@
"use client" "use client";
import { Rejectuser } from "@/actions/user-actions" import { Rejectuser } from "@/actions/user-actions";
import { Button } from "@/components/ui/button" import { Button } from "@/components/ui/button";
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@ -10,56 +10,56 @@ import {
DialogHeader, DialogHeader,
DialogTitle, DialogTitle,
DialogTrigger, DialogTrigger,
} from "@/components/ui/dialog" } from "@/components/ui/dialog";
import { Label } from "@/components/ui/label" import { Label } from "@/components/ui/label";
import { cn } from "@/lib/utils" import type { User } from "@/lib/types/user";
import { zodResolver } from "@hookform/resolvers/zod" import { cn } from "@/lib/utils";
import type { User } from "@prisma/client" import { zodResolver } from "@hookform/resolvers/zod";
import { UserX } from "lucide-react" import { UserX } from "lucide-react";
import { useState } from "react" import { useState } from "react";
import { type SubmitHandler, useForm } from "react-hook-form" import { type SubmitHandler, useForm } from "react-hook-form";
import { toast } from "sonner" import { toast } from "sonner";
import { z } from "zod" import { z } from "zod";
import { Textarea } from "../ui/textarea" import { Textarea } from "../ui/textarea";
const validationSchema = z.object({ const validationSchema = z.object({
reason: z.string().min(5, { message: "Reason is required" }), reason: z.string().min(5, { message: "Reason is required" }),
}) });
export default function UserRejectDialog({ user }: { user: User }) { export default function UserRejectDialog({ user }: { user: User }) {
const [disabled, setDisabled] = useState(false) const [disabled, setDisabled] = useState(false);
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false);
const { const {
register, register,
handleSubmit, handleSubmit,
formState: { errors }, formState: { errors },
} = useForm<z.infer<typeof validationSchema>>({ } = useForm<z.infer<typeof validationSchema>>({
resolver: zodResolver(validationSchema), resolver: zodResolver(validationSchema),
}) });
const onSubmit: SubmitHandler<z.infer<typeof validationSchema>> = (data) => { const onSubmit: SubmitHandler<z.infer<typeof validationSchema>> = (data) => {
setDisabled(true) setDisabled(true);
console.log(data) console.log(data);
toast.promise(Rejectuser({ toast.promise(
userId: user.id, Rejectuser({
userId: String(user.id),
reason: data.reason, reason: data.reason,
}), { }),
{
loading: "Rejecting...", loading: "Rejecting...",
success: () => { success: () => {
setDisabled(false) setDisabled(false);
setOpen((prev) => !prev) setOpen((prev) => !prev);
return "Rejected!" return "Rejected!";
}, },
error: (error) => { error: (error) => {
setDisabled(false) setDisabled(false);
return error.message || "Something went wrong" return error.message || "Something went wrong";
}, },
}) },
setDisabled(false) );
setDisabled(false);
} };
return ( return (
<Dialog open={open} onOpenChange={setOpen}> <Dialog open={open} onOpenChange={setOpen}>
@ -71,20 +71,25 @@ export default function UserRejectDialog({ user }: { user: User }) {
</DialogTrigger> </DialogTrigger>
<DialogContent className="sm:max-w-[425px]"> <DialogContent className="sm:max-w-[425px]">
<DialogHeader> <DialogHeader>
<DialogTitle>Are you sure you want to {" "} <DialogTitle>
<span className="text-red-500">reject</span>{" "} Are you sure you want to{" "}
this user?</DialogTitle> <span className="text-red-500">reject</span> this user?
</DialogTitle>
<DialogDescription className="py-2"> <DialogDescription className="py-2">
<li>Name: {user.name}</li> <li>
Name: {user.first_name} {user.last_name}
</li>
<li>ID Card: {user.id_card}</li> <li>ID Card: {user.id_card}</li>
<li>Address: {user.address}</li> <li>Address: {user.address}</li>
<li>DOB: {new Date(user.dob ?? "").toLocaleDateString("en-US", { <li>
DOB:{" "}
{new Date(user.dob ?? "").toLocaleDateString("en-US", {
month: "short", month: "short",
day: "2-digit", day: "2-digit",
year: "numeric", year: "numeric",
})} })}
</li> </li>
<li>Phone Number: {user.phoneNumber}</li> <li>Phone Number: {user.mobile}</li>
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
<form onSubmit={handleSubmit(onSubmit)}> <form onSubmit={handleSubmit(onSubmit)}>
@ -93,7 +98,15 @@ export default function UserRejectDialog({ user }: { user: User }) {
<Label htmlFor="reason" className="text-right"> <Label htmlFor="reason" className="text-right">
Rejection details Rejection details
</Label> </Label>
<Textarea rows={10} {...register("reason")} id="reason" className={cn("col-span-5", errors.reason && "ring-2 ring-red-500")} /> <Textarea
rows={10}
{...register("reason")}
id="reason"
className={cn(
"col-span-5",
errors.reason && "ring-2 ring-red-500",
)}
/>
<span className="text-sm text-red-500"> <span className="text-sm text-red-500">
{errors.reason?.message} {errors.reason?.message}
</span> </span>
@ -107,5 +120,5 @@ export default function UserRejectDialog({ user }: { user: User }) {
</form> </form>
</DialogContent> </DialogContent>
</Dialog> </Dialog>
) );
} }

View File

@ -12,7 +12,7 @@ import {
AlertDialogTrigger, AlertDialogTrigger,
} from "@/components/ui/alert-dialog"; } from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import type { User } from "@prisma/client"; import type { User } from "@/lib/types/user";
import { Check, CheckCheck } from "lucide-react"; import { Check, CheckCheck } from "lucide-react";
import { useState } from "react"; import { useState } from "react";
import { toast } from "sonner"; import { toast } from "sonner";
@ -37,15 +37,20 @@ export function UserVerifyDialog({ user }: { user: User }) {
<AlertDialogDescription> <AlertDialogDescription>
Are you sure you want to verify the following user? Are you sure you want to verify the following user?
<span className="inline-block my-4"> <span className="inline-block my-4">
<li>Name: {user.name}</li> <li>
Name: {user.first_name} {user.last_name}
</li>
<li>ID Card: {user.id_card}</li> <li>ID Card: {user.id_card}</li>
<li>Address: {user.address}</li> <li>Address: {user.address}</li>
<li>DOB: {new Date(user.dob ?? "").toLocaleDateString("en-US", { <li>
DOB:{" "}
{new Date(user.dob ?? "").toLocaleDateString("en-US", {
month: "short", month: "short",
day: "2-digit", day: "2-digit",
year: "numeric", year: "numeric",
})}</li> })}
<li>Phone Number: {user.phoneNumber}</li> </li>
<li>Phone Number: {user.mobile}</li>
</span> </span>
</AlertDialogDescription> </AlertDialogDescription>
</AlertDialogHeader> </AlertDialogHeader>
@ -55,7 +60,7 @@ export function UserVerifyDialog({ user }: { user: User }) {
disabled={disabled} disabled={disabled}
onClick={() => { onClick={() => {
setDisabled(true); setDisabled(true);
toast.promise(VerifyUser(userId), { toast.promise(VerifyUser(String(userId)), {
loading: "Verifying...", loading: "Verifying...",
success: () => { success: () => {
setDisabled(false); setDisabled(false);

View File

@ -1,5 +1,5 @@
import type { Device } from "@prisma/client";
import { atom, createStore } from "jotai"; import { atom, createStore } from "jotai";
import type { Device } from "./backend-types";
// Create a single store instance // Create a single store instance
export const store = createStore(); export const store = createStore();

View File

@ -1,6 +1,6 @@
"use server"; "use server";
import type { TNationalPerson } from "@/lib/types"; import type { TNationalPerson } from "@/lib/types";
import type { User } from "@prisma/client"; import { User } from "./types/user";
export async function getNationalPerson({ export async function getNationalPerson({
idCard, idCard,
@ -18,26 +18,27 @@ export async function getNationalPerson({
} }
export async function VerifyUserDetails({ user }: { user: User }) { export async function VerifyUserDetails({ user }: { user: User }) {
const phoneNumber = String(user.phoneNumber).slice(4); console.log(user)
console.log({ phoneNumber }); // const phoneNumber = String(user.phoneNumber).slice(4);
const nationalData = await getNationalPerson({ idCard: user.id_card ?? "" }); // console.log({ phoneNumber });
const dob = new Date(nationalData.dob); // const nationalData = await getNationalPerson({ idCard: user.id_card ?? "" });
const age = new Date().getFullYear() - dob.getFullYear(); // const dob = new Date(nationalData.dob);
// const age = new Date().getFullYear() - dob.getFullYear();
console.log("ID card", user.id_card === nationalData.nic); // console.log("ID card", user.id_card === nationalData.nic);
console.log("name", user.name === nationalData.name_en); // console.log("name", user.name === nationalData.name_en);
console.log("house", user.address === nationalData.house_name_en); // console.log("house", user.address === nationalData.house_name_en);
console.log("phone", phoneNumber === nationalData.primary_contact); // console.log("phone", phoneNumber === nationalData.primary_contact);
console.log("db phone", phoneNumber); // console.log("db phone", phoneNumber);
console.log("national phone", nationalData.primary_contact); // console.log("national phone", nationalData.primary_contact);
if ( // if (
user.id_card === nationalData.nic && // user.id_card === nationalData.nic &&
user.name === nationalData.name_en && // user.name === nationalData.name_en &&
user.address === nationalData.house_name_en && // user.address === nationalData.house_name_en &&
age >= 18 // age >= 18
) { // ) {
return true; // return true;
} // }
return false; return false;
} }

View File

@ -19,6 +19,10 @@ export interface User {
user_permissions: Permission[]; user_permissions: Permission[];
first_name: string; first_name: string;
last_name: string; last_name: string;
id_card?: string;
address?: string;
verified?: boolean;
dob?: string;
mobile?: string; mobile?: string;
wallet_balance?: number; wallet_balance?: number;
is_superuser: boolean; is_superuser: boolean;

551
package-lock.json generated
View File

@ -32,14 +32,14 @@
"lucide-react": "^0.460.0", "lucide-react": "^0.460.0",
"moment": "^2.30.1", "moment": "^2.30.1",
"motion": "^11.15.0", "motion": "^11.15.0",
"next": "15.1.2", "next": "15.3.0",
"next-auth": "^4.24.11", "next-auth": "^4.24.11",
"next-themes": "^0.4.3", "next-themes": "^0.4.3",
"nextjs-toploader": "^3.7.15", "nextjs-toploader": "^3.7.15",
"react": "19.0.0", "react": "19.1.0",
"react-aria-components": "^1.5.0", "react-aria-components": "^1.5.0",
"react-day-picker": "^9.6.3", "react-day-picker": "^9.6.3",
"react-dom": "19.0.0", "react-dom": "19.1.0",
"react-hook-form": "^7.53.2", "react-hook-form": "^7.53.2",
"react-phone-number-input": "^3.4.9", "react-phone-number-input": "^3.4.9",
"sonner": "^1.7.1", "sonner": "^1.7.1",
@ -50,14 +50,14 @@
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^22.10.2", "@types/node": "^22.10.2",
"@types/react": "^19.0.2", "@types/react": "^19.1.0",
"@types/react-dom": "^19.0.2", "@types/react-dom": "^19.1.2",
"eslint": "^9.17.0", "eslint": "^9.17.0",
"eslint-config-next": "15.1.2", "eslint-config-next": "15.1.2",
"postcss": "^8.4.49", "postcss": "^8.4.49",
"tailwindcss": "^3.4.17", "tailwindcss": "^3.4.17",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"typescript": "^5.7.2" "typescript": "^5.8.3"
} }
}, },
"node_modules/@alloc/quick-lru": { "node_modules/@alloc/quick-lru": {
@ -355,25 +355,12 @@
} }
}, },
"node_modules/@img/sharp-libvips-linux-x64": { "node_modules/@img/sharp-libvips-linux-x64": {
"version": "1.0.4", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.1.0.tgz",
"integrity": "sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
"license": "LGPL-3.0-or-later",
"optional": true,
"os": [
"linux"
],
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linuxmusl-x64": {
"version": "1.0.4",
"cpu": [
"x64"
],
"license": "LGPL-3.0-or-later",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@ -383,11 +370,12 @@
} }
}, },
"node_modules/@img/sharp-linux-x64": { "node_modules/@img/sharp-linux-x64": {
"version": "0.33.5", "version": "0.34.1",
"resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.1.tgz",
"integrity": "sha512-wExv7SH9nmoBW3Wr2gvQopX1k8q2g5V5Iag8Zk6AVENsjwd+3adjwxtp3Dcu2QhOXr8W9NusBU6XcQUohBZ5MA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
"license": "Apache-2.0",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@ -399,27 +387,7 @@
"url": "https://opencollective.com/libvips" "url": "https://opencollective.com/libvips"
}, },
"optionalDependencies": { "optionalDependencies": {
"@img/sharp-libvips-linux-x64": "1.0.4" "@img/sharp-libvips-linux-x64": "1.1.0"
}
},
"node_modules/@img/sharp-linuxmusl-x64": {
"version": "0.33.5",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linuxmusl-x64": "1.0.4"
} }
}, },
"node_modules/@internationalized/date": { "node_modules/@internationalized/date": {
@ -514,8 +482,9 @@
} }
}, },
"node_modules/@next/env": { "node_modules/@next/env": {
"version": "15.1.2", "version": "15.3.0",
"license": "MIT" "resolved": "https://registry.npmjs.org/@next/env/-/env-15.3.0.tgz",
"integrity": "sha512-6mDmHX24nWlHOlbwUiAOmMyY7KELimmi+ed8qWcJYjqXeC+G6JzPZ3QosOAfjNwgMIzwhXBiRiCgdh8axTTdTA=="
}, },
"node_modules/@next/eslint-plugin-next": { "node_modules/@next/eslint-plugin-next": {
"version": "15.1.2", "version": "15.1.2",
@ -551,72 +520,13 @@
"node": ">= 6" "node": ">= 6"
} }
}, },
"node_modules/@next/swc-darwin-arm64": {
"version": "15.1.2",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.1.2.tgz",
"integrity": "sha512-b9TN7q+j5/7+rGLhFAVZiKJGIASuo8tWvInGfAd8wsULjB1uNGRCj1z1WZwwPWzVQbIKWFYqc+9L7W09qwt52w==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-darwin-x64": {
"version": "15.1.2",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.1.2.tgz",
"integrity": "sha512-caR62jNDUCU+qobStO6YJ05p9E+LR0EoXh1EEmyU69cYydsAy7drMcOlUlRtQihM6K6QfvNwJuLhsHcCzNpqtA==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-linux-arm64-gnu": {
"version": "15.1.2",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.1.2.tgz",
"integrity": "sha512-fHHXBusURjBmN6VBUtu6/5s7cCeEkuGAb/ZZiGHBLVBXMBy4D5QpM8P33Or8JD1nlOjm/ZT9sEE5HouQ0F+hUA==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-linux-arm64-musl": {
"version": "15.1.2",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.1.2.tgz",
"integrity": "sha512-9CF1Pnivij7+M3G74lxr+e9h6o2YNIe7QtExWq1KUK4hsOLTBv6FJikEwCaC3NeYTflzrm69E5UfwEAbV2U9/g==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-linux-x64-gnu": { "node_modules/@next/swc-linux-x64-gnu": {
"version": "15.1.2", "version": "15.3.0",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.3.0.tgz",
"integrity": "sha512-ZMQ9yzDEts/vkpFLRAqfYO1wSpIJGlQNK9gZ09PgyjBJUmg8F/bb8fw2EXKgEaHbCc4gmqMpDfh+T07qUphp9A==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
"license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@ -625,50 +535,6 @@
"node": ">= 10" "node": ">= 10"
} }
}, },
"node_modules/@next/swc-linux-x64-musl": {
"version": "15.1.2",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
"version": "15.1.2",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.1.2.tgz",
"integrity": "sha512-wvg7MlfnaociP7k8lxLX4s2iBJm4BrNiNFhVUY+Yur5yhAJHfkS8qPPeDEUH8rQiY0PX3u/P7Q/wcg6Mv6GSAA==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-win32-x64-msvc": {
"version": "15.1.2",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.1.2.tgz",
"integrity": "sha512-D3cNA8NoT3aWISWmo7HF5Eyko/0OdOO+VagkoJuiTk7pyX3P/b+n8XA/MYvyR+xSVcbKn68B1rY9fgqjNISqzQ==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@nodelib/fs.scandir": { "node_modules/@nodelib/fs.scandir": {
"version": "2.1.5", "version": "2.1.5",
"license": "MIT", "license": "MIT",
@ -3073,35 +2939,38 @@
} }
}, },
"node_modules/@types/react": { "node_modules/@types/react": {
"version": "19.0.2", "version": "19.1.0",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.0.tgz",
"integrity": "sha512-UaicktuQI+9UKyA4njtDOGBD/67t8YEBt2xdfqu8+gP9hqPUPsiXlNPcpS2gVdjmis5GKPG3fCxbQLVgxsQZ8w==",
"devOptional": true, "devOptional": true,
"license": "MIT",
"dependencies": { "dependencies": {
"csstype": "^3.0.2" "csstype": "^3.0.2"
} }
}, },
"node_modules/@types/react-dom": { "node_modules/@types/react-dom": {
"version": "19.0.2", "version": "19.1.2",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.2.tgz",
"integrity": "sha512-XGJkWF41Qq305SKWEILa1O8vzhb3aOo3ogBlSmiqNko/WmRb6QIaweuZCXjKygVDXpzXb5wyxKTSOsmkuqj+Qw==",
"devOptional": true, "devOptional": true,
"license": "MIT",
"peerDependencies": { "peerDependencies": {
"@types/react": "^19.0.0" "@types/react": "^19.0.0"
} }
}, },
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.18.2", "version": "8.29.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.29.1.tgz",
"integrity": "sha512-ba0rr4Wfvg23vERs3eB+P3lfj2E+2g3lhWcCVukUuhtcdUx5lSIFZlGFEBHKr+3zizDa/TvZTptdNHVZWAkSBg==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/regexpp": "^4.10.0", "@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.18.2", "@typescript-eslint/scope-manager": "8.29.1",
"@typescript-eslint/type-utils": "8.18.2", "@typescript-eslint/type-utils": "8.29.1",
"@typescript-eslint/utils": "8.18.2", "@typescript-eslint/utils": "8.29.1",
"@typescript-eslint/visitor-keys": "8.18.2", "@typescript-eslint/visitor-keys": "8.29.1",
"graphemer": "^1.4.0", "graphemer": "^1.4.0",
"ignore": "^5.3.1", "ignore": "^5.3.1",
"natural-compare": "^1.4.0", "natural-compare": "^1.4.0",
"ts-api-utils": "^1.3.0" "ts-api-utils": "^2.0.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -3113,18 +2982,19 @@
"peerDependencies": { "peerDependencies": {
"@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0",
"eslint": "^8.57.0 || ^9.0.0", "eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <5.8.0" "typescript": ">=4.8.4 <5.9.0"
} }
}, },
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "8.18.2", "version": "8.29.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.29.1.tgz",
"integrity": "sha512-zczrHVEqEaTwh12gWBIJWj8nx+ayDcCJs06yoNMY0kwjMWDM6+kppljY+BxWI06d2Ja+h4+WdufDcwMnnMEWmg==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "8.18.2", "@typescript-eslint/scope-manager": "8.29.1",
"@typescript-eslint/types": "8.18.2", "@typescript-eslint/types": "8.29.1",
"@typescript-eslint/typescript-estree": "8.18.2", "@typescript-eslint/typescript-estree": "8.29.1",
"@typescript-eslint/visitor-keys": "8.18.2", "@typescript-eslint/visitor-keys": "8.29.1",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
@ -3136,16 +3006,17 @@
}, },
"peerDependencies": { "peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0", "eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <5.8.0" "typescript": ">=4.8.4 <5.9.0"
} }
}, },
"node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/scope-manager": {
"version": "8.18.2", "version": "8.29.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.29.1.tgz",
"integrity": "sha512-2nggXGX5F3YrsGN08pw4XpMLO1Rgtnn4AzTegC2MDesv6q3QaTU5yU7IbS1tf1IwCR0Hv/1EFygLn9ms6LIpDA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.18.2", "@typescript-eslint/types": "8.29.1",
"@typescript-eslint/visitor-keys": "8.18.2" "@typescript-eslint/visitor-keys": "8.29.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -3156,14 +3027,15 @@
} }
}, },
"node_modules/@typescript-eslint/type-utils": { "node_modules/@typescript-eslint/type-utils": {
"version": "8.18.2", "version": "8.29.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.29.1.tgz",
"integrity": "sha512-DkDUSDwZVCYN71xA4wzySqqcZsHKic53A4BLqmrWFFpOpNSoxX233lwGu/2135ymTCR04PoKiEEEvN1gFYg4Tw==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/typescript-estree": "8.18.2", "@typescript-eslint/typescript-estree": "8.29.1",
"@typescript-eslint/utils": "8.18.2", "@typescript-eslint/utils": "8.29.1",
"debug": "^4.3.4", "debug": "^4.3.4",
"ts-api-utils": "^1.3.0" "ts-api-utils": "^2.0.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -3174,13 +3046,14 @@
}, },
"peerDependencies": { "peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0", "eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <5.8.0" "typescript": ">=4.8.4 <5.9.0"
} }
}, },
"node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/types": {
"version": "8.18.2", "version": "8.29.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.29.1.tgz",
"integrity": "sha512-VT7T1PuJF1hpYC3AGm2rCgJBjHL3nc+A/bhOp9sGMKfi5v0WufsX/sHCFBfNTx2F+zA6qBc/PD0/kLRLjdt8mQ==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}, },
@ -3190,18 +3063,19 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/typescript-estree": {
"version": "8.18.2", "version": "8.29.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.29.1.tgz",
"integrity": "sha512-l1enRoSaUkQxOQnbi0KPUtqeZkSiFlqrx9/3ns2rEDhGKfTa+88RmXqedC1zmVTOWrLc2e6DEJrTA51C9iLH5g==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.18.2", "@typescript-eslint/types": "8.29.1",
"@typescript-eslint/visitor-keys": "8.18.2", "@typescript-eslint/visitor-keys": "8.29.1",
"debug": "^4.3.4", "debug": "^4.3.4",
"fast-glob": "^3.3.2", "fast-glob": "^3.3.2",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
"minimatch": "^9.0.4", "minimatch": "^9.0.4",
"semver": "^7.6.0", "semver": "^7.6.0",
"ts-api-utils": "^1.3.0" "ts-api-utils": "^2.0.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -3211,39 +3085,23 @@
"url": "https://opencollective.com/typescript-eslint" "url": "https://opencollective.com/typescript-eslint"
}, },
"peerDependencies": { "peerDependencies": {
"typescript": ">=4.8.4 <5.8.0" "typescript": ">=4.8.4 <5.9.0"
} }
}, },
"node_modules/@typescript-eslint/typescript-estree/node_modules/fast-glob": { "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
"version": "3.3.2", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@nodelib/fs.stat": "^2.0.2", "balanced-match": "^1.0.0"
"@nodelib/fs.walk": "^1.2.3",
"glob-parent": "^5.1.2",
"merge2": "^1.3.0",
"micromatch": "^4.0.4"
},
"engines": {
"node": ">=8.6.0"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/fast-glob/node_modules/glob-parent": {
"version": "5.1.2",
"dev": true,
"license": "ISC",
"dependencies": {
"is-glob": "^4.0.1"
},
"engines": {
"node": ">= 6"
} }
}, },
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
"version": "9.0.5", "version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"dev": true, "dev": true,
"license": "ISC",
"dependencies": { "dependencies": {
"brace-expansion": "^2.0.1" "brace-expansion": "^2.0.1"
}, },
@ -3254,18 +3112,11 @@
"url": "https://github.com/sponsors/isaacs" "url": "https://github.com/sponsors/isaacs"
} }
}, },
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch/node_modules/brace-expansion": {
"version": "2.0.1",
"dev": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
"version": "7.6.3", "version": "7.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
"dev": true, "dev": true,
"license": "ISC",
"bin": { "bin": {
"semver": "bin/semver.js" "semver": "bin/semver.js"
}, },
@ -3274,14 +3125,15 @@
} }
}, },
"node_modules/@typescript-eslint/utils": { "node_modules/@typescript-eslint/utils": {
"version": "8.18.2", "version": "8.29.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.29.1.tgz",
"integrity": "sha512-QAkFEbytSaB8wnmB+DflhUPz6CLbFWE2SnSCrRMEa+KnXIzDYbpsn++1HGvnfAsUY44doDXmvRkO5shlM/3UfA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.4.0", "@eslint-community/eslint-utils": "^4.4.0",
"@typescript-eslint/scope-manager": "8.18.2", "@typescript-eslint/scope-manager": "8.29.1",
"@typescript-eslint/types": "8.18.2", "@typescript-eslint/types": "8.29.1",
"@typescript-eslint/typescript-estree": "8.18.2" "@typescript-eslint/typescript-estree": "8.29.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -3292,15 +3144,16 @@
}, },
"peerDependencies": { "peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0", "eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <5.8.0" "typescript": ">=4.8.4 <5.9.0"
} }
}, },
"node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/visitor-keys": {
"version": "8.18.2", "version": "8.29.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.29.1.tgz",
"integrity": "sha512-RGLh5CRaUEf02viP5c1Vh1cMGffQscyHe7HPAzGpfmfflFg1wUz2rYxd+OZqwpeypYvZ8UxSxuIpF++fmOzEcg==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.18.2", "@typescript-eslint/types": "8.29.1",
"eslint-visitor-keys": "^4.2.0" "eslint-visitor-keys": "^4.2.0"
}, },
"engines": { "engines": {
@ -3818,7 +3671,8 @@
}, },
"node_modules/color": { "node_modules/color": {
"version": "4.2.3", "version": "4.2.3",
"license": "MIT", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
"integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
"optional": true, "optional": true,
"dependencies": { "dependencies": {
"color-convert": "^2.0.1", "color-convert": "^2.0.1",
@ -3844,7 +3698,8 @@
}, },
"node_modules/color-string": { "node_modules/color-string": {
"version": "1.9.1", "version": "1.9.1",
"license": "MIT", "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
"optional": true, "optional": true,
"dependencies": { "dependencies": {
"color-name": "^1.0.0", "color-name": "^1.0.0",
@ -4051,7 +3906,8 @@
}, },
"node_modules/detect-libc": { "node_modules/detect-libc": {
"version": "2.0.3", "version": "2.0.3",
"license": "Apache-2.0", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
"integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
"optional": true, "optional": true,
"engines": { "engines": {
"node": ">=8" "node": ">=8"
@ -5050,8 +4906,9 @@
}, },
"node_modules/graphemer": { "node_modules/graphemer": {
"version": "1.4.0", "version": "1.4.0",
"dev": true, "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
"license": "MIT" "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
"dev": true
}, },
"node_modules/has-bigints": { "node_modules/has-bigints": {
"version": "1.1.0", "version": "1.1.0",
@ -5221,7 +5078,8 @@
}, },
"node_modules/is-arrayish": { "node_modules/is-arrayish": {
"version": "0.3.2", "version": "0.3.2",
"license": "MIT", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
"optional": true "optional": true
}, },
"node_modules/is-async-function": { "node_modules/is-async-function": {
@ -5934,10 +5792,11 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/next": { "node_modules/next": {
"version": "15.1.2", "version": "15.3.0",
"license": "MIT", "resolved": "https://registry.npmjs.org/next/-/next-15.3.0.tgz",
"integrity": "sha512-k0MgP6BsK8cZ73wRjMazl2y2UcXj49ZXLDEgx6BikWuby/CN+nh81qFFI16edgd7xYpe/jj2OZEIwCoqnzz0bQ==",
"dependencies": { "dependencies": {
"@next/env": "15.1.2", "@next/env": "15.3.0",
"@swc/counter": "0.1.3", "@swc/counter": "0.1.3",
"@swc/helpers": "0.5.15", "@swc/helpers": "0.5.15",
"busboy": "1.6.0", "busboy": "1.6.0",
@ -5952,15 +5811,15 @@
"node": "^18.18.0 || ^19.8.0 || >= 20.0.0" "node": "^18.18.0 || ^19.8.0 || >= 20.0.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"@next/swc-darwin-arm64": "15.1.2", "@next/swc-darwin-arm64": "15.3.0",
"@next/swc-darwin-x64": "15.1.2", "@next/swc-darwin-x64": "15.3.0",
"@next/swc-linux-arm64-gnu": "15.1.2", "@next/swc-linux-arm64-gnu": "15.3.0",
"@next/swc-linux-arm64-musl": "15.1.2", "@next/swc-linux-arm64-musl": "15.3.0",
"@next/swc-linux-x64-gnu": "15.1.2", "@next/swc-linux-x64-gnu": "15.3.0",
"@next/swc-linux-x64-musl": "15.1.2", "@next/swc-linux-x64-musl": "15.3.0",
"@next/swc-win32-arm64-msvc": "15.1.2", "@next/swc-win32-arm64-msvc": "15.3.0",
"@next/swc-win32-x64-msvc": "15.1.2", "@next/swc-win32-x64-msvc": "15.3.0",
"sharp": "^0.33.5" "sharp": "^0.34.1"
}, },
"peerDependencies": { "peerDependencies": {
"@opentelemetry/api": "^1.1.0", "@opentelemetry/api": "^1.1.0",
@ -6566,8 +6425,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/react": { "node_modules/react": {
"version": "19.0.0", "version": "19.1.0",
"license": "MIT", "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
"integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@ -6684,13 +6544,14 @@
} }
}, },
"node_modules/react-dom": { "node_modules/react-dom": {
"version": "19.0.0", "version": "19.1.0",
"license": "MIT", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
"integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
"dependencies": { "dependencies": {
"scheduler": "^0.25.0" "scheduler": "^0.26.0"
}, },
"peerDependencies": { "peerDependencies": {
"react": "^19.0.0" "react": "^19.1.0"
} }
}, },
"node_modules/react-hook-form": { "node_modules/react-hook-form": {
@ -6981,8 +6842,9 @@
} }
}, },
"node_modules/scheduler": { "node_modules/scheduler": {
"version": "0.25.0", "version": "0.26.0",
"license": "MIT" "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
"integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="
}, },
"node_modules/semver": { "node_modules/semver": {
"version": "6.3.1", "version": "6.3.1",
@ -7023,14 +6885,15 @@
} }
}, },
"node_modules/sharp": { "node_modules/sharp": {
"version": "0.33.5", "version": "0.34.1",
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.1.tgz",
"integrity": "sha512-1j0w61+eVxu7DawFJtnfYcvSv6qPFvfTaqzTQ2BLknVhHTwGS8sc63ZBF4rzkWMBVKybo4S5OBtDdZahh2A1xg==",
"hasInstallScript": true, "hasInstallScript": true,
"license": "Apache-2.0",
"optional": true, "optional": true,
"dependencies": { "dependencies": {
"color": "^4.2.3", "color": "^4.2.3",
"detect-libc": "^2.0.3", "detect-libc": "^2.0.3",
"semver": "^7.6.3" "semver": "^7.7.1"
}, },
"engines": { "engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0" "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
@ -7039,30 +6902,32 @@
"url": "https://opencollective.com/libvips" "url": "https://opencollective.com/libvips"
}, },
"optionalDependencies": { "optionalDependencies": {
"@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-arm64": "0.34.1",
"@img/sharp-darwin-x64": "0.33.5", "@img/sharp-darwin-x64": "0.34.1",
"@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-arm64": "1.1.0",
"@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.1.0",
"@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm": "1.1.0",
"@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-arm64": "1.1.0",
"@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-ppc64": "1.1.0",
"@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.1.0",
"@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linux-x64": "1.1.0",
"@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.1.0",
"@img/sharp-linux-arm": "0.33.5", "@img/sharp-libvips-linuxmusl-x64": "1.1.0",
"@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-arm": "0.34.1",
"@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-arm64": "0.34.1",
"@img/sharp-linux-x64": "0.33.5", "@img/sharp-linux-s390x": "0.34.1",
"@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linux-x64": "0.34.1",
"@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.34.1",
"@img/sharp-wasm32": "0.33.5", "@img/sharp-linuxmusl-x64": "0.34.1",
"@img/sharp-win32-ia32": "0.33.5", "@img/sharp-wasm32": "0.34.1",
"@img/sharp-win32-x64": "0.33.5" "@img/sharp-win32-ia32": "0.34.1",
"@img/sharp-win32-x64": "0.34.1"
} }
}, },
"node_modules/sharp/node_modules/semver": { "node_modules/sharp/node_modules/semver": {
"version": "7.6.3", "version": "7.7.1",
"license": "ISC", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
"optional": true, "optional": true,
"bin": { "bin": {
"semver": "bin/semver.js" "semver": "bin/semver.js"
@ -7168,7 +7033,8 @@
}, },
"node_modules/simple-swizzle": { "node_modules/simple-swizzle": {
"version": "0.2.2", "version": "0.2.2",
"license": "MIT", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
"integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
"optional": true, "optional": true,
"dependencies": { "dependencies": {
"is-arrayish": "^0.3.1" "is-arrayish": "^0.3.1"
@ -7571,14 +7437,15 @@
} }
}, },
"node_modules/ts-api-utils": { "node_modules/ts-api-utils": {
"version": "1.4.3", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
"integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": ">=16" "node": ">=18.12"
}, },
"peerDependencies": { "peerDependencies": {
"typescript": ">=4.2.0" "typescript": ">=4.8.4"
} }
}, },
"node_modules/ts-interface-checker": { "node_modules/ts-interface-checker": {
@ -7729,9 +7596,10 @@
} }
}, },
"node_modules/typescript": { "node_modules/typescript": {
"version": "5.7.2", "version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"devOptional": true, "devOptional": true,
"license": "Apache-2.0",
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"
@ -8082,6 +7950,111 @@
"funding": { "funding": {
"url": "https://github.com/sponsors/colinhacks" "url": "https://github.com/sponsors/colinhacks"
} }
},
"node_modules/@next/swc-darwin-arm64": {
"version": "15.3.0",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.3.0.tgz",
"integrity": "sha512-PDQcByT0ZfF2q7QR9d+PNj3wlNN4K6Q8JoHMwFyk252gWo4gKt7BF8Y2+KBgDjTFBETXZ/TkBEUY7NIIY7A/Kw==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-darwin-x64": {
"version": "15.3.0",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.3.0.tgz",
"integrity": "sha512-m+eO21yg80En8HJ5c49AOQpFDq+nP51nu88ZOMCorvw3g//8g1JSUsEiPSiFpJo1KCTQ+jm9H0hwXK49H/RmXg==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-linux-arm64-gnu": {
"version": "15.3.0",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.3.0.tgz",
"integrity": "sha512-H0Kk04ZNzb6Aq/G6e0un4B3HekPnyy6D+eUBYPJv9Abx8KDYgNMWzKt4Qhj57HXV3sTTjsfc1Trc1SxuhQB+Tg==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-linux-arm64-musl": {
"version": "15.3.0",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.3.0.tgz",
"integrity": "sha512-k8GVkdMrh/+J9uIv/GpnHakzgDQhrprJ/FbGQvwWmstaeFG06nnAoZCJV+wO/bb603iKV1BXt4gHG+s2buJqZA==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-linux-x64-musl": {
"version": "15.3.0",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.3.0.tgz",
"integrity": "sha512-RFwq5VKYTw9TMr4T3e5HRP6T4RiAzfDJ6XsxH8j/ZeYq2aLsBqCkFzwMI0FmnSsLaUbOb46Uov0VvN3UciHX5A==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
"version": "15.3.0",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.3.0.tgz",
"integrity": "sha512-a7kUbqa/k09xPjfCl0RSVAvEjAkYBYxUzSVAzk2ptXiNEL+4bDBo9wNC43G/osLA/EOGzG4CuNRFnQyIHfkRgQ==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@next/swc-win32-x64-msvc": {
"version": "15.3.0",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.3.0.tgz",
"integrity": "sha512-vHUQS4YVGJPmpjn7r5lEZuMhK5UQBNBRSB+iGDvJjaNk649pTIcRluDWNb9siunyLLiu/LDPHfvxBtNamyuLTw==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
} }
} }
} }

View File

@ -6,14 +6,9 @@
"dev": "next dev --turbopack", "dev": "next dev --turbopack",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
"lint": "next lint", "lint": "next lint"
"studio": "npx prisma studio",
"push": "npx prisma db push",
"db-setup": "npx prisma migrate deploy && npx prisma generate && npx prisma db push"
},
"prisma": {
"seed": "ts-node --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts"
}, },
"dependencies": { "dependencies": {
"@faker-js/faker": "^9.3.0", "@faker-js/faker": "^9.3.0",
"@hookform/resolvers": "^3.9.1", "@hookform/resolvers": "^3.9.1",
@ -39,14 +34,14 @@
"lucide-react": "^0.460.0", "lucide-react": "^0.460.0",
"moment": "^2.30.1", "moment": "^2.30.1",
"motion": "^11.15.0", "motion": "^11.15.0",
"next": "15.1.2", "next": "15.3.0",
"next-auth": "^4.24.11", "next-auth": "^4.24.11",
"next-themes": "^0.4.3", "next-themes": "^0.4.3",
"nextjs-toploader": "^3.7.15", "nextjs-toploader": "^3.7.15",
"react": "19.0.0", "react": "19.1.0",
"react-aria-components": "^1.5.0", "react-aria-components": "^1.5.0",
"react-day-picker": "^9.6.3", "react-day-picker": "^9.6.3",
"react-dom": "19.0.0", "react-dom": "19.1.0",
"react-hook-form": "^7.53.2", "react-hook-form": "^7.53.2",
"react-phone-number-input": "^3.4.9", "react-phone-number-input": "^3.4.9",
"sonner": "^1.7.1", "sonner": "^1.7.1",
@ -57,14 +52,14 @@
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^22.10.2", "@types/node": "^22.10.2",
"@types/react": "^19.0.2", "@types/react": "^19.1.0",
"@types/react-dom": "^19.0.2", "@types/react-dom": "^19.1.2",
"eslint": "^9.17.0", "eslint": "^9.17.0",
"eslint-config-next": "15.1.2", "eslint-config-next": "15.1.2",
"postcss": "^8.4.49", "postcss": "^8.4.49",
"tailwindcss": "^3.4.17", "tailwindcss": "^3.4.17",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"typescript": "^5.7.2" "typescript": "^5.8.3"
}, },
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
} }

View File

@ -1,110 +0,0 @@
-- CreateTable
CREATE TABLE "user" (
"id" TEXT NOT NULL,
"name" TEXT,
"email" TEXT,
"emailVerified" BOOLEAN NOT NULL DEFAULT false,
"firstPaymentDone" BOOLEAN NOT NULL DEFAULT false,
"verified" BOOLEAN NOT NULL DEFAULT false,
"address" TEXT,
"id_card" TEXT,
"dob" TIMESTAMP(3),
"image" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"phoneNumber" TEXT NOT NULL,
"phoneNumberVerified" BOOLEAN NOT NULL DEFAULT false,
"role" TEXT,
"lang" TEXT,
"atollId" TEXT,
"islandId" TEXT,
CONSTRAINT "user_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "session" (
"id" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"token" TEXT NOT NULL,
"expiresAt" TIMESTAMP(3) NOT NULL,
"ipAddress" TEXT,
"userAgent" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "session_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "account" (
"id" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"accountId" TEXT NOT NULL,
"providerId" TEXT NOT NULL,
"accessToken" TEXT,
"refreshToken" TEXT,
"accessTokenExpiresAt" TIMESTAMP(3),
"refreshTokenExpiresAt" TIMESTAMP(3),
"scope" TEXT,
"password" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"idToken" TEXT,
CONSTRAINT "account_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "verification" (
"id" TEXT NOT NULL,
"identifier" TEXT NOT NULL,
"value" TEXT NOT NULL,
"expiresAt" TIMESTAMP(3) NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "verification_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Atoll" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "Atoll_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Island" (
"id" TEXT NOT NULL,
"atollId" TEXT NOT NULL,
"name" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "Island_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "user_email_key" ON "user"("email");
-- CreateIndex
CREATE UNIQUE INDEX "user_id_card_key" ON "user"("id_card");
-- CreateIndex
CREATE UNIQUE INDEX "user_phoneNumber_key" ON "user"("phoneNumber");
-- CreateIndex
CREATE UNIQUE INDEX "session_token_key" ON "session"("token");
-- AddForeignKey
ALTER TABLE "user" ADD CONSTRAINT "user_atollId_fkey" FOREIGN KEY ("atollId") REFERENCES "Atoll"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "user" ADD CONSTRAINT "user_islandId_fkey" FOREIGN KEY ("islandId") REFERENCES "Island"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Island" ADD CONSTRAINT "Island_atollId_fkey" FOREIGN KEY ("atollId") REFERENCES "Atoll"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -1,14 +0,0 @@
-- CreateTable
CREATE TABLE "Device" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"mac" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"userId" TEXT,
CONSTRAINT "Device_pkey" PRIMARY KEY ("id")
);
-- AddForeignKey
ALTER TABLE "Device" ADD CONSTRAINT "Device_userId_fkey" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE SET NULL ON UPDATE CASCADE;

View File

@ -1,29 +0,0 @@
-- AlterTable
ALTER TABLE "user" ADD COLUMN "policyAccepted" BOOLEAN NOT NULL DEFAULT false,
ADD COLUMN "termsAccepted" BOOLEAN NOT NULL DEFAULT false;
-- CreateTable
CREATE TABLE "Bill" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"amount" INTEGER NOT NULL,
"paid" BOOLEAN NOT NULL DEFAULT false,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"deviceId" TEXT,
CONSTRAINT "Bill_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "BillFormula" (
"id" TEXT NOT NULL,
"formula" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "BillFormula_pkey" PRIMARY KEY ("id")
);
-- AddForeignKey
ALTER TABLE "Bill" ADD CONSTRAINT "Bill_deviceId_fkey" FOREIGN KEY ("deviceId") REFERENCES "Device"("id") ON DELETE SET NULL ON UPDATE CASCADE;

View File

@ -1,10 +0,0 @@
/*
Warnings:
- Added the required column `baseAmount` to the `BillFormula` table without a default value. This is not possible if the table is not empty.
- Added the required column `discountPercentage` to the `BillFormula` table without a default value. This is not possible if the table is not empty.
*/
-- AlterTable
ALTER TABLE "BillFormula" ADD COLUMN "baseAmount" DOUBLE PRECISION NOT NULL,
ADD COLUMN "discountPercentage" DOUBLE PRECISION NOT NULL;

View File

@ -1,2 +0,0 @@
-- AlterTable
ALTER TABLE "Device" ADD COLUMN "isActive" BOOLEAN NOT NULL DEFAULT false;

View File

@ -1,33 +0,0 @@
/*
Warnings:
- You are about to drop the `Bill` table. If the table is not empty, all the data it contains will be lost.
*/
-- DropForeignKey
ALTER TABLE "Bill" DROP CONSTRAINT "Bill_deviceId_fkey";
-- AlterTable
ALTER TABLE "Device" ADD COLUMN "billId" TEXT;
-- DropTable
DROP TABLE "Bill";
-- CreateTable
CREATE TABLE "Payment" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"amount" INTEGER NOT NULL,
"paid" BOOLEAN NOT NULL DEFAULT false,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"userId" TEXT NOT NULL,
CONSTRAINT "Payment_pkey" PRIMARY KEY ("id")
);
-- AddForeignKey
ALTER TABLE "Device" ADD CONSTRAINT "Device_billId_fkey" FOREIGN KEY ("billId") REFERENCES "Payment"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Payment" ADD CONSTRAINT "Payment_userId_fkey" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -1,23 +0,0 @@
/*
Warnings:
- You are about to drop the column `billId` on the `Device` table. All the data in the column will be lost.
- You are about to drop the column `name` on the `Payment` table. All the data in the column will be lost.
- Added the required column `numberOfMonths` to the `Payment` table without a default value. This is not possible if the table is not empty.
*/
-- DropForeignKey
ALTER TABLE "Device" DROP CONSTRAINT "Device_billId_fkey";
-- AlterTable
ALTER TABLE "Device" DROP COLUMN "billId",
ADD COLUMN "expiryDate" TIMESTAMP(3),
ADD COLUMN "paymentId" TEXT;
-- AlterTable
ALTER TABLE "Payment" DROP COLUMN "name",
ADD COLUMN "numberOfMonths" INTEGER NOT NULL,
ALTER COLUMN "amount" SET DATA TYPE DOUBLE PRECISION;
-- AddForeignKey
ALTER TABLE "Device" ADD CONSTRAINT "Device_paymentId_fkey" FOREIGN KEY ("paymentId") REFERENCES "Payment"("id") ON DELETE SET NULL ON UPDATE CASCADE;

View File

@ -1,2 +0,0 @@
-- AlterTable
ALTER TABLE "Payment" ADD COLUMN "paidAt" TIMESTAMP(3);

View File

@ -1,2 +0,0 @@
-- AlterTable
ALTER TABLE "Payment" ADD COLUMN "expiresAt" TIMESTAMP(3);

View File

@ -1,2 +0,0 @@
-- AlterTable
ALTER TABLE "user" ADD COLUMN "accNo" TEXT;

View File

@ -1,11 +0,0 @@
/*
Warnings:
- You are about to drop the column `firstPaymentDone` on the `user` table. All the data in the column will be lost.
*/
-- AlterTable
ALTER TABLE "Device" ADD COLUMN "registered" BOOLEAN NOT NULL DEFAULT false;
-- AlterTable
ALTER TABLE "user" DROP COLUMN "firstPaymentDone";

View File

@ -1,2 +0,0 @@
-- AlterTable
ALTER TABLE "Device" ADD COLUMN "blocked" BOOLEAN NOT NULL DEFAULT false;

View File

@ -1,2 +0,0 @@
-- AlterTable
ALTER TABLE "user" ADD COLUMN "walletBalance" DOUBLE PRECISION NOT NULL DEFAULT 0;

View File

@ -1,2 +0,0 @@
-- AlterTable
ALTER TABLE "Device" ADD COLUMN "reasonForBlocking" TEXT;

View File

@ -1,11 +0,0 @@
-- CreateTable
CREATE TABLE "Topup" (
"id" TEXT NOT NULL,
"amount" DOUBLE PRECISION NOT NULL,
"userId" TEXT NOT NULL,
"paid" BOOLEAN NOT NULL DEFAULT false,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "Topup_pkey" PRIMARY KEY ("id")
);

View File

@ -1,5 +0,0 @@
-- CreateEnum
CREATE TYPE "Blocker" AS ENUM ('ADMIN', 'PARENT');
-- AlterTable
ALTER TABLE "Device" ADD COLUMN "blockedBy" "Blocker" NOT NULL DEFAULT 'PARENT';

View File

@ -1,2 +0,0 @@
-- AlterTable
ALTER TABLE "user" ADD COLUMN "ninja_user_id" TEXT;

View File

@ -1,5 +0,0 @@
-- CreateEnum
CREATE TYPE "PaymentType" AS ENUM ('WALLET', 'TRANSFER');
-- AlterTable
ALTER TABLE "Payment" ADD COLUMN "method" "PaymentType" NOT NULL DEFAULT 'TRANSFER';

View File

@ -1,28 +0,0 @@
/*
Warnings:
- You are about to drop the column `paymentId` on the `Device` table. All the data in the column will be lost.
*/
-- DropForeignKey
ALTER TABLE "Device" DROP CONSTRAINT "Device_paymentId_fkey";
-- AlterTable
ALTER TABLE "Device" DROP COLUMN "paymentId";
-- CreateTable
CREATE TABLE "_DeviceToPayment" (
"A" TEXT NOT NULL,
"B" TEXT NOT NULL,
CONSTRAINT "_DeviceToPayment_AB_pkey" PRIMARY KEY ("A","B")
);
-- CreateIndex
CREATE INDEX "_DeviceToPayment_B_index" ON "_DeviceToPayment"("B");
-- AddForeignKey
ALTER TABLE "_DeviceToPayment" ADD CONSTRAINT "_DeviceToPayment_A_fkey" FOREIGN KEY ("A") REFERENCES "Device"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_DeviceToPayment" ADD CONSTRAINT "_DeviceToPayment_B_fkey" FOREIGN KEY ("B") REFERENCES "Payment"("id") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@ -1,3 +0,0 @@
# Please do not edit this file manually
# It should be added in your version-control system (e.g., Git)
provider = "postgresql"

View File

@ -1,172 +0,0 @@
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
generator client {
provider = "prisma-client-js"
binaryTargets = ["native", "debian-openssl-3.0.x"]
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id String @id @default(cuid())
name String?
email String? @unique
emailVerified Boolean @default(false)
verified Boolean @default(false)
accNo String?
// island String?
address String?
id_card String? @unique
dob DateTime?
atoll Atoll? @relation(fields: [atollId], references: [id])
island Island? @relation(fields: [islandId], references: [id])
image String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
phoneNumber String @unique
phoneNumberVerified Boolean @default(false)
termsAccepted Boolean @default(false)
policyAccepted Boolean @default(false)
walletBalance Float @default(0)
ninja_user_id String?
devices Device[]
role String?
lang String?
atollId String?
islandId String?
Bill Payment[]
@@map("user")
}
model Session {
id String @id @default(cuid())
userId String
token String @unique
expiresAt DateTime
ipAddress String?
userAgent String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("session")
}
model Account {
id String @id @default(cuid())
userId String
accountId String
providerId String
accessToken String?
refreshToken String?
accessTokenExpiresAt DateTime?
refreshTokenExpiresAt DateTime?
scope String?
password String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
idToken String?
@@map("account")
}
model Verification {
id String @id @default(cuid())
identifier String
value String
expiresAt DateTime
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("verification")
}
model Atoll {
id String @id @default(cuid())
name String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
islands Island[]
User User[]
}
model Island {
id String @id @default(cuid())
atollId String
atoll Atoll @relation(fields: [atollId], references: [id])
name String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
User User[]
}
enum Blocker {
ADMIN
PARENT
}
enum PaymentType {
WALLET
TRANSFER
}
model Device {
id String @id @default(cuid())
name String
mac String
reasonForBlocking String?
isActive Boolean @default(false)
registered Boolean @default(false)
blocked Boolean @default(false)
blockedBy Blocker @default(PARENT)
expiryDate DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
User User? @relation(fields: [userId], references: [id])
userId String?
payments Payment[]
}
model Payment {
id String @id @default(cuid())
numberOfMonths Int
amount Float
paid Boolean @default(false)
user User @relation(fields: [userId], references: [id])
paidAt DateTime?
method PaymentType @default(TRANSFER)
expiresAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
devices Device[]
userId String
}
model BillFormula {
id String @id @default(cuid())
formula String
baseAmount Float
discountPercentage Float
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Topup {
id String @id @default(cuid())
amount Float
userId String
paid Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}

View File

@ -1,56 +0,0 @@
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
const DEFAULT_ISLANDS = ["Dharanboodhoo", "Feeali", "Nilandhoo", "Magoodhoo"];
async function main() {
await prisma.user.upsert({
where: {
phoneNumber: process.env.ADMIN_PHONENUMBER,
},
update: {},
create: {
name: process.env.ADMIN_FULLNAME,
email: process.env.ADMIN_EMAIL,
emailVerified: true,
verified: true,
address: process.env.ADMIN_ADDRESS,
id_card: process.env.ADMIN_IDCARD,
dob: new Date("1999-05-06"),
phoneNumber: process.env.ADMIN_PHONENUMBER ?? "",
phoneNumberVerified: true,
role: "ADMIN",
},
});
let FAAFU_ATOLL_ID = "";
const atollExists = await prisma.atoll.findFirst({
where: {
name: "F",
},
});
if (!atollExists) {
const NEW_ATOLL = await prisma.atoll.create({
data: {
name: "F",
},
});
FAAFU_ATOLL_ID = NEW_ATOLL.id;
const islands = DEFAULT_ISLANDS.map((name) => ({
name,
atollId: FAAFU_ATOLL_ID,
}));
await prisma.island.createMany({
data: islands,
});
}
}
main()
.then(() => prisma.$disconnect())
.catch(async (e) => {
console.error(e);
await prisma.$disconnect();
process.exit(1);
});