mirror of
https://github.com/i701/sarlink-portal.git
synced 2025-07-01 15:23:58 +00:00
Implement new features and enhance existing components for improved user experience
- Added a new `bun.lockb` file for dependency management. - Updated `next.config.ts` to set output to "standalone" for better deployment options. - Removed `package-lock.json` to streamline package management. - Modified `package.json` to update dependencies, including `@prisma/client` and `sonner`, and adjusted build scripts for improved functionality. - Enhanced Tailwind CSS configuration to include new animations and color schemes. - Refactored various dashboard components to improve UI consistency, including adding a new `My Wallet` page and updating existing pages to use a unified styling approach. - Introduced a new `BlockDeviceDialog` component for managing device blocking with user-defined reasons. - Improved logging and error handling in payment verification and device management functions. These changes enhance the overall functionality, maintainability, and user experience of the application.
This commit is contained in:
@ -1,35 +1,135 @@
|
||||
'use client'
|
||||
"use client"
|
||||
|
||||
import { blockDevice } from "@/actions/omada-actions";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import type { Device } from "@prisma/client";
|
||||
import { useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { TextShimmer } from "./ui/text-shimmer";
|
||||
import { blockDevice } from "@/actions/omada-actions"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog"
|
||||
import { Label } from "@/components/ui/label"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import type { Device, } from "@prisma/client"
|
||||
import { OctagonX } from "lucide-react"
|
||||
import { useState } from "react"
|
||||
import { type SubmitHandler, useForm } from "react-hook-form"
|
||||
import { toast } from "sonner"
|
||||
import { z } from "zod"
|
||||
import { Textarea } from "./ui/textarea"
|
||||
import { TextShimmer } from "./ui/text-shimmer"
|
||||
|
||||
|
||||
|
||||
const validationSchema = z.object({
|
||||
reasonForBlocking: z.string().min(5, { message: "Reason is required" }),
|
||||
})
|
||||
|
||||
export default function BlockDeviceDialog({ device, type }: { device: Device, type: "block" | "unblock" }) {
|
||||
const [disabled, setDisabled] = useState(false)
|
||||
const [open, setOpen] = useState(false)
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
} = useForm<z.infer<typeof validationSchema>>({
|
||||
resolver: zodResolver(validationSchema),
|
||||
})
|
||||
|
||||
const onSubmit: SubmitHandler<z.infer<typeof validationSchema>> = (data) => {
|
||||
setDisabled(true)
|
||||
console.log(data)
|
||||
toast.promise(blockDevice({
|
||||
macAddress: device.mac,
|
||||
type: type,
|
||||
reason: data.reasonForBlocking,
|
||||
// reason: data.reasonForBlocking,
|
||||
}), {
|
||||
loading: "Blocking...",
|
||||
success: () => {
|
||||
setDisabled(false)
|
||||
setOpen((prev) => !prev)
|
||||
return "Blocked!"
|
||||
},
|
||||
error: (error) => {
|
||||
setDisabled(false)
|
||||
return error || "Something went wrong"
|
||||
},
|
||||
})
|
||||
setDisabled(false)
|
||||
|
||||
}
|
||||
|
||||
export default function BlockDeviceDialog({ device }: { device: Device }) {
|
||||
const [disabled, setDisabled] = useState(false);
|
||||
return (
|
||||
<Button
|
||||
className="w-full mt-2"
|
||||
disabled={disabled}
|
||||
onClick={() => {
|
||||
setDisabled(true);
|
||||
toast.promise(blockDevice({ macAddress: device.mac, type: device.blocked ? "unblock" : "block" }), {
|
||||
loading: device.blocked ? "Unblocking..." : "Blocking...",
|
||||
success: () => {
|
||||
setDisabled(false);
|
||||
return `Device ${device.name} successfully ${device.blocked ? "unblocked" : "blocked"
|
||||
}!`;
|
||||
},
|
||||
error: () => {
|
||||
setDisabled(false);
|
||||
return "Something went wrong";
|
||||
},
|
||||
});
|
||||
}}
|
||||
>
|
||||
{disabled ? <TextShimmer>{device.blocked ? "Unblocking..." : "Blocking..."}</TextShimmer> : (device?.blocked ? "Unblock" : "Block")}
|
||||
</Button>
|
||||
<div>
|
||||
{device.blocked ? (
|
||||
<Button onClick={
|
||||
() => {
|
||||
setDisabled(true);
|
||||
toast.promise(blockDevice({
|
||||
macAddress: device.mac,
|
||||
type: "unblock",
|
||||
reason: '',
|
||||
}), {
|
||||
loading: "unblockinig...",
|
||||
success: () => {
|
||||
setDisabled(false);
|
||||
return "Unblocked!";
|
||||
},
|
||||
error: () => {
|
||||
setDisabled(false);
|
||||
return "Something went wrong";
|
||||
},
|
||||
})
|
||||
}
|
||||
}>
|
||||
{disabled ? (
|
||||
<TextShimmer>
|
||||
Unblocking
|
||||
</TextShimmer>
|
||||
) : "Unblock"}
|
||||
</Button>
|
||||
|
||||
) : (
|
||||
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button disabled={disabled} variant="destructive">
|
||||
<OctagonX />
|
||||
Block
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-[425px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Please provide a reason for blocking this device.</DialogTitle>
|
||||
|
||||
</DialogHeader>
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<div className="grid gap-4 py-4">
|
||||
<div className="flex flex-col items-start gap-1">
|
||||
<Label htmlFor="reason" className="text-right">
|
||||
Reason for blocking
|
||||
</Label>
|
||||
<Textarea rows={10} {...register("reasonForBlocking")} id="reasonForBlocking" className={cn("col-span-5", errors.reasonForBlocking && "ring-2 ring-red-500")} />
|
||||
<span className="text-sm text-red-500">
|
||||
{errors.reasonForBlocking?.message}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button variant={"destructive"} disabled={disabled} type="submit">
|
||||
Block
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)}
|
||||
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
Reference in New Issue
Block a user