Refactor authentication middleware to use native fetch, update dependencies, and enhance error handling. Add new error boundary component for dashboard and improve user verification UI. Update payment handling and device management components for better user experience. Adjust CSS for error backgrounds and refine input read-only components with validation indicators.
Some checks failed
Build and Push Docker Images / Build and Push Docker Images (push) Failing after 3m9s

This commit is contained in:
2025-01-15 10:35:03 +05:00
parent d14b0b35a3
commit 8ffabb1fcb
23 changed files with 535 additions and 303 deletions

View File

@ -0,0 +1,107 @@
"use client";
import { createPayment } from "@/actions/payment";
import DeviceCard from "@/components/device-card";
import NumberInput from "@/components/number-input";
import { Button } from "@/components/ui/button";
import {
deviceCartAtom,
numberOfMonths
} from "@/lib/atoms";
import { authClient } from "@/lib/auth-client";
import type { PaymentType } from "@/lib/types";
import type { BillFormula } from "@prisma/client";
import { useAtom, useAtomValue, useSetAtom } from "jotai";
import {
CircleDollarSign,
Loader2
} from "lucide-react";
import { usePathname } from "next/navigation";
import { useEffect, useState } from "react";
export default function DevicesForPayment({
billFormula,
}: {
billFormula?: BillFormula;
}) {
const baseAmount = billFormula?.baseAmount || 100;
const discountPercentage = billFormula?.discountPercentage || 75;
const session = authClient.useSession();
const pathname = usePathname();
const devices = useAtomValue(deviceCartAtom);
const setDeviceCart = useSetAtom(deviceCartAtom);
const [months, setMonths] = useAtom(numberOfMonths);
const [message, setMessage] = useState("");
const [disabled, setDisabled] = useState(false);
const [total, setTotal] = useState(0);
useEffect(() => {
if (months === 7) {
setMessage("You will get 1 month free.");
} else if (months === 12) {
setMessage("You will get 2 months free.");
} else {
setMessage("");
}
setTotal(baseAmount + ((devices.length + 1) - 1) * discountPercentage);
}, [months, devices.length, baseAmount, discountPercentage]);
if (pathname === "/payment") {
return null;
}
const data: PaymentType = {
numberOfMonths: months,
userId: session?.data?.user.id ?? "",
deviceIds: devices.map((device) => device.id),
amount: Number.parseFloat(total.toFixed(2)),
paid: false,
};
return (
<div className="max-w-lg mx-auto space-y-4 px-4">
<div className="flex max-h-[calc(100svh-400px)] flex-col overflow-auto pb-4 gap-4">
{devices.map((device) => (
<DeviceCard key={device.id} device={device} />
))}
</div>
<div className="flex flex-col gap-4">
<NumberInput
label="Set No of Months"
value={months}
onChange={(value: number) => setMonths(value)}
maxAllowed={12}
isDisabled={devices.length === 0}
/>
{message && (
<span className="title-bg text-lime-800 bg-lime-100/50 dark:text-lime-100 rounded text-center p-2 w-full">
{message}
</span>
)}
</div>
<Button
onClick={async () => {
setDisabled(true);
await createPayment(data);
setDeviceCart([]);
setMonths(1);
setDisabled(false);
}}
className="w-full"
disabled={devices.length === 0 || disabled}
>
{disabled ? (
<>
<Loader2 className="ml-2 animate-spin" />
</>
) : (
<>
Go to payment
<CircleDollarSign />
</>
)}
</Button>
</div>
)
}