Refactor dashboard components and update global styles

- Updated the title and description in layout.tsx to reflect the new application name.
- Replaced the background color in globals.css with a background image for the title section.
- Enhanced the Devices and UserDevices pages by adding search and filter components for improved user interaction.
- Introduced a new DevicesTable component for displaying device data with pagination.
- Updated the Users page to improve layout and added a filter for user status.
- Made various UI adjustments across components for better consistency and usability.
This commit is contained in:
2024-11-30 23:38:32 +05:00
parent 490150f9b7
commit b91f34b6b1
14 changed files with 330 additions and 68 deletions

View File

@ -5,10 +5,10 @@ import Link from "next/link";
import { signup } from "@/actions/auth-actions";
import { cn } from "@/lib/utils";
import { Loader } from "lucide-react";
import { useActionState } from "react";
import { useSearchParams } from "next/navigation";
import type { Island, Prisma } from "@prisma/client";
import { Loader } from "lucide-react";
import { useSearchParams } from "next/navigation";
import { useActionState } from "react";
import * as React from "react";
import {
@ -20,6 +20,7 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Checkbox } from "../ui/checkbox";
type AtollWithIslands = Prisma.AtollGetPayload<{
include: {
@ -31,13 +32,16 @@ export default function SignUpForm({ atolls }: { atolls: AtollWithIslands[] }) {
const [atoll, setAtoll] = React.useState<AtollWithIslands>();
const [islands, setIslands] = React.useState<Island[]>();
const [actionState, action, isPending] = useActionState(signup, {
message: "",
});
React.useEffect(() => {
setIslands(atoll?.islands);
}, [atoll]);
const [actionState, action, isPending] = useActionState(signup, {
message: "",
});
const params = useSearchParams();
const phoneNumberFromUrl = params.get("phone_number");
const NUMBER_WITHOUT_DASH = phoneNumberFromUrl?.split("-").join("");
@ -83,7 +87,7 @@ export default function SignUpForm({ atolls }: { atolls: AtollWithIslands[] }) {
className={cn(
"text-base",
actionState.errors?.fieldErrors?.id_card &&
"border-2 border-red-500",
"border-2 border-red-500",
)}
placeholder="ID Card"
/>
@ -160,26 +164,26 @@ export default function SignUpForm({ atolls }: { atolls: AtollWithIslands[] }) {
</div>
<div>
<label htmlFor="house_name" className="text-sm">
House Name
<label htmlFor="address" className="text-sm">
Address
</label>
<Input
className={cn(
"text-base",
actionState.errors?.fieldErrors?.house_name &&
"border-2 border-red-500",
actionState.errors?.fieldErrors?.address &&
"border-2 border-red-500",
)}
disabled={isPending}
name="house_name"
name="address"
defaultValue={
(actionState.payload?.get("house_name") || "") as string
(actionState.payload?.get("address") || "") as string
}
type="text"
placeholder="House Name"
placeholder="Address"
/>
{actionState.errors?.fieldErrors?.house_name && (
{actionState.errors?.fieldErrors?.address && (
<span className="text-sm inline-block text-red-500">
{actionState.errors?.fieldErrors?.house_name}
{actionState.errors?.fieldErrors?.address}
</span>
)}
</div>
@ -217,8 +221,8 @@ export default function SignUpForm({ atolls }: { atolls: AtollWithIslands[] }) {
disabled={isPending}
className={cn(
!phoneNumberFromUrl &&
actionState.errors?.fieldErrors?.phone_number &&
"border-2 border-red-500 rounded-md",
actionState.errors?.fieldErrors?.phone_number &&
"border-2 border-red-500 rounded-md",
)}
defaultValue={NUMBER_WITHOUT_DASH ?? ""}
readOnly={Boolean(phoneNumberFromUrl)}
@ -235,6 +239,51 @@ export default function SignUpForm({ atolls }: { atolls: AtollWithIslands[] }) {
{actionState.message}
</span>
)}
<div className="flex flex-col gap-2 items-start justify-start py-2">
<div className="flex gap-2 items-center">
<Checkbox
defaultChecked={(actionState.payload?.get("terms") || "") as string === 'on'}
name="terms" id="terms" />
<label
htmlFor="terms"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
<span>
i accept
</span>
<Link className="ml-1 underline" href="">
terms and conditions
</Link>
</label>
</div>
{actionState.errors?.fieldErrors?.terms && (
<span className="text-sm inline-block text-red-500">
{actionState.errors?.fieldErrors?.terms}
</span>
)}
<div className="flex gap-2 items-center">
<Checkbox
name="policy" id="terms" />
<label
htmlFor="terms"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
<span>
i undertand
</span>
<Link className="ml-1 underline" href="">
the privacy policy
</Link>
</label>
</div>
{actionState.errors?.fieldErrors?.policy && (
<span className="text-sm inline-block text-red-500">
{actionState.errors?.fieldErrors?.policy}
</span>
)}
</div>
<Button disabled={isPending} className="mt-4 w-full" type="submit">
{isPending ? <Loader className="animate-spin" /> : "Submit"}
</Button>