add admin checks for admin pages and run biome formating 🔨
All checks were successful
Build and Push Docker Images / Build and Push Docker Images (push) Successful in 11m8s

This commit is contained in:
2025-07-25 13:31:12 +05:00
parent aedf7cdf7d
commit 9b2f2c1528
127 changed files with 6577 additions and 6334 deletions

View File

@ -10,14 +10,18 @@ import { Button } from "../ui/button";
export default function CancelPaymentButton({
paymentId,
}: { paymentId: string }) {
}: {
paymentId: string;
}) {
const router = useRouter();
const [loading, setLoading] = React.useState(false);
return (
<Button
onClick={async () => {
setLoading(true);
const [error, payment] = await tryCatch(cancelPayment({ id: paymentId }));
const [error, payment] = await tryCatch(
cancelPayment({ id: paymentId }),
);
console.log(payment);
if (error) {
toast.error(error.message);

View File

@ -8,32 +8,30 @@ import { cancelTopup } from "@/actions/payment";
import { tryCatch } from "@/utils/tryCatch";
import { Button } from "../ui/button";
export default function CancelTopupButton({
topupId,
}: { topupId: string }) {
const router = useRouter();
const [loading, setLoading] = React.useState(false);
return (
<Button
onClick={async () => {
setLoading(true);
const [error, topup] = await tryCatch(cancelTopup({ id: topupId }));
if (error) {
toast.error(error.message);
setLoading(false);
} else {
toast.success("Topup cancelled successfully!", {
description: `Your topup of ${topup?.amount} MVR has been cancelled.`,
closeButton: true,
})
router.replace("/top-ups");
}
}}
disabled={loading}
variant={"destructive"}
>
Cancel Topup
{loading ? <Loader2 className="animate-spin" /> : <Trash2 />}
</Button>
);
export default function CancelTopupButton({ topupId }: { topupId: string }) {
const router = useRouter();
const [loading, setLoading] = React.useState(false);
return (
<Button
onClick={async () => {
setLoading(true);
const [error, topup] = await tryCatch(cancelTopup({ id: topupId }));
if (error) {
toast.error(error.message);
setLoading(false);
} else {
toast.success("Topup cancelled successfully!", {
description: `Your topup of ${topup?.amount} MVR has been cancelled.`,
closeButton: true,
});
router.replace("/top-ups");
}
}}
disabled={loading}
variant={"destructive"}
>
Cancel Topup
{loading ? <Loader2 className="animate-spin" /> : <Trash2 />}
</Button>
);
}

View File

@ -1,57 +1,67 @@
'use client'
import { usePathname, useRouter } from 'next/navigation'
import { useEffect, useState } from 'react'
import { Progress } from '@/components/ui/progress'
"use client";
import { usePathname, useRouter } from "next/navigation";
import { useEffect, useState } from "react";
import { Progress } from "@/components/ui/progress";
const calculateTimeLeft = (expiresAt: string) => {
const now = Date.now()
const expirationTime = new Date(expiresAt).getTime()
return Math.max(0, Math.floor((expirationTime - now) / 1000))
}
const now = Date.now();
const expirationTime = new Date(expiresAt).getTime();
return Math.max(0, Math.floor((expirationTime - now) / 1000));
};
const HumanizeTimeLeft = (seconds: number) => {
const minutes = Math.floor(seconds / 60)
const remainingSeconds = seconds % 60
return `${minutes}m ${remainingSeconds}s`
}
export default function ExpiryCountDown({ expiresAt, expiryLabel }: { expiresAt: string, expiryLabel: string }) {
const [timeLeft, setTimeLeft] = useState(calculateTimeLeft(expiresAt))
const [mounted, setMounted] = useState(false)
const router = useRouter()
const pathname = usePathname()
useEffect(() => {
setMounted(true)
}, [])
useEffect(() => {
const timer = setInterval(() => {
setTimeLeft(calculateTimeLeft(expiresAt))
}, 1000)
return () => clearInterval(timer)
}, [expiresAt])
useEffect(() => {
if (timeLeft <= 0) {
router.replace(pathname)
}
}, [timeLeft, router, pathname])
if (!mounted) {
return null
}
return (
<div className='overflow-clip relative mx-2 p-4 rounded-md border border-dashed flex items-center justify-between text-muted-foreground'>
<div className='absolute inset-0 title-bg mask-b-from-0' />
{timeLeft ? (
<span>Time left: {HumanizeTimeLeft(timeLeft)}</span>
) : (
<span>{expiryLabel} has expired.</span>
)}
{timeLeft > 0 && (
<Progress className='absolute bottom-0 left-0 right-0' color='#f49b5b' value={timeLeft / 600 * 100} />
)}
</div>
)
const minutes = Math.floor(seconds / 60);
const remainingSeconds = seconds % 60;
return `${minutes}m ${remainingSeconds}s`;
};
export default function ExpiryCountDown({
expiresAt,
expiryLabel,
}: {
expiresAt: string;
expiryLabel: string;
}) {
const [timeLeft, setTimeLeft] = useState(calculateTimeLeft(expiresAt));
const [mounted, setMounted] = useState(false);
const router = useRouter();
const pathname = usePathname();
useEffect(() => {
setMounted(true);
}, []);
useEffect(() => {
const timer = setInterval(() => {
setTimeLeft(calculateTimeLeft(expiresAt));
}, 1000);
return () => clearInterval(timer);
}, [expiresAt]);
useEffect(() => {
if (timeLeft <= 0) {
router.replace(pathname);
}
}, [timeLeft, router, pathname]);
if (!mounted) {
return null;
}
return (
<div className="overflow-clip relative mx-2 p-4 rounded-md border border-dashed flex items-center justify-between text-muted-foreground">
<div className="absolute inset-0 title-bg mask-b-from-0" />
{timeLeft ? (
<span>Time left: {HumanizeTimeLeft(timeLeft)}</span>
) : (
<span>{expiryLabel} has expired.</span>
)}
{timeLeft > 0 && (
<Progress
className="absolute bottom-0 left-0 right-0"
color="#f49b5b"
value={(timeLeft / 600) * 100}
/>
)}
</div>
);
}