mirror of
https://github.com/i701/sarlink-portal.git
synced 2025-07-01 03:05:55 +00:00
Refactor payment verification and add MAC address guide
Some checks failed
Build and Push Docker Images / Build and Push Docker Images (push) Failing after 1m23s
Some checks failed
Build and Push Docker Images / Build and Push Docker Images (push) Failing after 1m23s
- Updated payment verification logic in `actions/payment.ts` to remove unused code and improve clarity. - Enhanced `DevicesToPay` component to handle separate states for wallet and transfer payment verification. - Introduced a new `GetMacAccordion` component to guide users on finding their MAC addresses. - Created a reusable accordion component in `ui/accordion.tsx` for better UI consistency. - Integrated the MAC address guide into the device addition dialog. - Updated Tailwind CSS configuration to include animations for the accordion component. - Added Radix UI Accordion dependency to package.json and package-lock.json. - Improved error handling in API response utility to log unauthorized responses.
This commit is contained in:
@ -25,8 +25,9 @@ export default function DevicesToPay({
|
||||
payment,
|
||||
user,
|
||||
}: { payment?: Payment; user?: User }) {
|
||||
console.log(user);
|
||||
const [verifying, setVerifying] = useState(false);
|
||||
const [verifyingWalletPayment, setVerifyingWalletPayment] = useState(false);
|
||||
const [verifyingTransferPayment, setVerifyingTransferPayment] = useState(false);
|
||||
|
||||
|
||||
const devices = payment?.devices;
|
||||
if (devices?.length === 0) {
|
||||
@ -81,37 +82,47 @@ export default function DevicesToPay({
|
||||
<div className="flex flex-col gap-2">
|
||||
{isWalletPayVisible && (
|
||||
<Button
|
||||
disabled={verifying}
|
||||
disabled={verifyingWalletPayment || verifyingTransferPayment}
|
||||
onClick={async () => {
|
||||
setVerifying(true);
|
||||
setVerifyingWalletPayment(true);
|
||||
await verifyPayment({
|
||||
method: "WALLET",
|
||||
id: payment?.id ?? "",
|
||||
});
|
||||
setVerifying(false);
|
||||
setVerifyingWalletPayment(false);
|
||||
}}
|
||||
variant={"secondary"}
|
||||
size={"lg"}
|
||||
>
|
||||
{verifying ? "Paying..." : "Pay with wallet"}
|
||||
{verifyingWalletPayment ? "Processing payment..." : "Pay with wallet"}
|
||||
<Wallet />
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
disabled={verifying}
|
||||
disabled={verifyingTransferPayment || verifyingWalletPayment}
|
||||
onClick={async () => {
|
||||
setVerifying(true);
|
||||
const res = await verifyPayment({
|
||||
id: payment?.id ?? "",
|
||||
method: "TRANSFER",
|
||||
});
|
||||
setVerifying(false);
|
||||
setVerifyingTransferPayment(true);
|
||||
try {
|
||||
const res = await verifyPayment({
|
||||
id: payment?.id ?? "",
|
||||
method: "TRANSFER"
|
||||
});
|
||||
toast.success("Payment verification successful!");
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof Error) {
|
||||
toast.error(error.message);
|
||||
} else {
|
||||
toast.error("Payment verification failed.");
|
||||
}
|
||||
} finally {
|
||||
setVerifyingTransferPayment(false);
|
||||
}
|
||||
}}
|
||||
size={"lg"}
|
||||
className="mb-4"
|
||||
>
|
||||
{verifying ? "Verifying..." : "Verify Payment"}
|
||||
{verifying ? (
|
||||
{verifyingTransferPayment ? "Processing payment..." : "I have paid"}
|
||||
{verifyingTransferPayment ? (
|
||||
<Loader2 className="animate-spin" />
|
||||
) : (
|
||||
<BadgeDollarSign />
|
||||
|
60
components/how-to-get-mac.tsx
Normal file
60
components/how-to-get-mac.tsx
Normal file
@ -0,0 +1,60 @@
|
||||
import {
|
||||
Accordion,
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "@/components/ui/accordion"
|
||||
|
||||
export function GetMacAccordion() {
|
||||
return (
|
||||
<Accordion
|
||||
type="single"
|
||||
collapsible
|
||||
className="w-full"
|
||||
>
|
||||
<AccordionItem value="item-1">
|
||||
<AccordionTrigger>How do I find my MAC Address?</AccordionTrigger>
|
||||
<AccordionContent className="flex flex-col gap-4 text-balance">
|
||||
<p>
|
||||
A MAC (Media Access Control) address is a unique identifier assigned
|
||||
to a device's network. It is used to identify the device on a
|
||||
network, helping to differentiate devices on a network.
|
||||
</p>
|
||||
<Accordion type="single" collapsible className="w-full">
|
||||
<AccordionItem value="iphone">
|
||||
<AccordionTrigger>iPhone</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
Settings ➜ General ➜ About ➜ Wi-Fi Address
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
<AccordionItem value="redmi">
|
||||
<AccordionTrigger>Redmi</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
Settings ➜ About ➜ Wi-Fi MAC Address
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
<AccordionItem value="samsung">
|
||||
<AccordionTrigger>Samsung</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
Settings ➜ About phone ➜ Status Information ➜ Wi-Fi MAC Address
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
<AccordionItem value="windows">
|
||||
<AccordionTrigger>Windows Laptop</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
Settings ➜ Network and Internet ➜ Wi-Fi ➜ Hardware
|
||||
Properties ➜ Physical address (MAC):
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
<AccordionItem value="other">
|
||||
<AccordionTrigger>Other Device</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
Please contact SAR Link for assistance.
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
)
|
||||
}
|
66
components/ui/accordion.tsx
Normal file
66
components/ui/accordion.tsx
Normal file
@ -0,0 +1,66 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import * as AccordionPrimitive from "@radix-ui/react-accordion"
|
||||
import { ChevronDownIcon } from "lucide-react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function Accordion({
|
||||
...props
|
||||
}: React.ComponentProps<typeof AccordionPrimitive.Root>) {
|
||||
return <AccordionPrimitive.Root data-slot="accordion" {...props} />
|
||||
}
|
||||
|
||||
function AccordionItem({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof AccordionPrimitive.Item>) {
|
||||
return (
|
||||
<AccordionPrimitive.Item
|
||||
data-slot="accordion-item"
|
||||
className={cn("border-b last:border-b-0", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function AccordionTrigger({
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
}: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {
|
||||
return (
|
||||
<AccordionPrimitive.Header className="flex">
|
||||
<AccordionPrimitive.Trigger
|
||||
data-slot="accordion-trigger"
|
||||
className={cn(
|
||||
"focus-visible:border-ring focus-visible:ring-ring/50 flex flex-1 items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<ChevronDownIcon className="text-muted-foreground pointer-events-none size-4 shrink-0 translate-y-0.5 transition-transform duration-200" />
|
||||
</AccordionPrimitive.Trigger>
|
||||
</AccordionPrimitive.Header>
|
||||
)
|
||||
}
|
||||
|
||||
function AccordionContent({
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
}: React.ComponentProps<typeof AccordionPrimitive.Content>) {
|
||||
return (
|
||||
<AccordionPrimitive.Content
|
||||
data-slot="accordion-content"
|
||||
className="data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm"
|
||||
{...props}
|
||||
>
|
||||
<div className={cn("pt-0 pb-4", className)}>{children}</div>
|
||||
</AccordionPrimitive.Content>
|
||||
)
|
||||
}
|
||||
|
||||
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
|
@ -22,6 +22,7 @@ import { useState } from "react";
|
||||
import { type SubmitHandler, useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
import { z } from "zod";
|
||||
import { GetMacAccordion } from "../how-to-get-mac";
|
||||
|
||||
export default function AddDeviceDialogForm({ user_id }: { user_id?: string }) {
|
||||
const formSchema = z.object({
|
||||
@ -90,6 +91,7 @@ export default function AddDeviceDialogForm({ user_id }: { user_id?: string }) {
|
||||
To add a new device, enter the device name and mac address below.
|
||||
Click save when you are done.
|
||||
</DialogDescription>
|
||||
<GetMacAccordion />
|
||||
</DialogHeader>
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<div className="grid gap-4 py-4">
|
||||
|
Reference in New Issue
Block a user