mirror of
https://github.com/i701/sarlink-portal.git
synced 2025-08-03 02:50:22 +00:00
feat(agreements): implement agreement fetching and display with error handling
All checks were successful
Build and Push Docker Images / Build and Push Docker Images (push) Successful in 13m34s
All checks were successful
Build and Push Docker Images / Build and Push Docker Images (push) Successful in 13m34s
feat(agreement-card): create AgreementCard component for displaying user agreements fix(devices-table): update no devices message for clarity based on parental control fix(payments-table): update no payments message for consistency fix(topups-table): update no topups message for consistency feat(user): add agreement field to User interface
This commit is contained in:
@ -1,11 +1,25 @@
|
|||||||
import React from "react";
|
import { getProfile } from "@/actions/user-actions";
|
||||||
|
import { AgreementCard } from "@/components/agreement-card";
|
||||||
|
import { tryCatch } from "@/utils/tryCatch";
|
||||||
|
|
||||||
export default function Agreements() {
|
export default async function Agreements() {
|
||||||
|
const [error, profile] = await tryCatch(getProfile())
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="flex justify-between items-center border rounded-md border-dashed font-bold title-bg py-4 px-2 mb-4">
|
<div className="flex justify-between items-center border rounded-md border-dashed font-bold title-bg py-4 px-2 mb-4">
|
||||||
<h3 className="text-sarLinkOrange text-2xl">Agreements</h3>
|
<h3 className="text-sarLinkOrange text-2xl">Agreements</h3>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="grid grid-cols-1">
|
||||||
|
{error ? (
|
||||||
|
<div className="text-red-500">
|
||||||
|
An error occurred while fetching agreements: {error.message}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div>
|
||||||
|
<AgreementCard agreement={profile.agreement ?? ""} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
30
components/agreement-card.tsx
Normal file
30
components/agreement-card.tsx
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import { EyeIcon } from "lucide-react"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle
|
||||||
|
} from "@/components/ui/card"
|
||||||
|
|
||||||
|
export function AgreementCard({ agreement }: { agreement: string }) {
|
||||||
|
return (
|
||||||
|
<Card className="w-full max-w-sm">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Sarlink User Agreement</CardTitle>
|
||||||
|
<CardDescription>
|
||||||
|
User agreement for Sarlink services.
|
||||||
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardFooter className="flex-col gap-2">
|
||||||
|
<a target="_blank" rel="noopener noreferrer" className="w-full hover:cursor-pointer" href={agreement}>
|
||||||
|
<Button type="button" className="w-full hover:cursor-pointer">
|
||||||
|
<EyeIcon />
|
||||||
|
View Agreement
|
||||||
|
</Button>
|
||||||
|
</a>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
@ -65,7 +65,7 @@ export async function DevicesTable({
|
|||||||
<div>
|
<div>
|
||||||
{data?.length === 0 ? (
|
{data?.length === 0 ? (
|
||||||
<div className="h-[calc(100svh-400px)] text-muted-foreground flex flex-col items-center justify-center my-4">
|
<div className="h-[calc(100svh-400px)] text-muted-foreground flex flex-col items-center justify-center my-4">
|
||||||
<h3>No devices.</h3>
|
<h3>{parentalControl ? "No active devices" : "No devices."}</h3>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
|
@ -52,8 +52,8 @@ export async function PaymentsTable({
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{data?.length === 0 ? (
|
{data?.length === 0 ? (
|
||||||
<div className="h-[calc(100svh-400px)] flex flex-col items-center justify-center my-4">
|
<div className="h-[calc(100svh-400px)] text-muted-foreground flex flex-col items-center justify-center my-4">
|
||||||
<h3>No Payments yet.</h3>
|
<h3>No Payments.</h3>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
|
@ -52,8 +52,8 @@ export async function TopupsTable({
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{data?.length === 0 ? (
|
{data?.length === 0 ? (
|
||||||
<div className="h-[calc(100svh-400px)] flex flex-col items-center justify-center my-4">
|
<div className="h-[calc(100svh-400px)] flex text-muted-foreground flex-col items-center justify-center my-4">
|
||||||
<h3>No topups yet.</h3>
|
<h3>No topups.</h3>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { useAtom } from "jotai";
|
import { useAtom } from "jotai";
|
||||||
import { CircleDollarSign, Loader2, Wallet2 } from "lucide-react";
|
import { CircleDollarSign, Loader2, Wallet2 } from "lucide-react";
|
||||||
import millify from "millify";
|
|
||||||
import { usePathname, useRouter } from "next/navigation";
|
import { usePathname, useRouter } from "next/navigation";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
@ -40,10 +39,7 @@ export function Wallet({ walletBalance }: { walletBalance: number }) {
|
|||||||
<Drawer open={isOpen} onOpenChange={setIsOpen}>
|
<Drawer open={isOpen} onOpenChange={setIsOpen}>
|
||||||
<DrawerTrigger asChild>
|
<DrawerTrigger asChild>
|
||||||
<Button onClick={() => setIsOpen(!isOpen)} variant="outline">
|
<Button onClick={() => setIsOpen(!isOpen)} variant="outline">
|
||||||
{millify(walletBalance, {
|
{walletBalance}{" "}
|
||||||
precision: 2,
|
|
||||||
lowercase: true,
|
|
||||||
})}{" "}
|
|
||||||
MVR
|
MVR
|
||||||
<Wallet2 />
|
<Wallet2 />
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -29,6 +29,7 @@ export interface User {
|
|||||||
is_superuser: boolean;
|
is_superuser: boolean;
|
||||||
date_joined: string;
|
date_joined: string;
|
||||||
last_login: string;
|
last_login: string;
|
||||||
|
agreement?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UserProfile {
|
export interface UserProfile {
|
||||||
|
19420
package-lock.json
generated
19420
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -25,7 +25,6 @@
|
|||||||
"input-otp": "^1.4.2",
|
"input-otp": "^1.4.2",
|
||||||
"jotai": "2.8.0",
|
"jotai": "2.8.0",
|
||||||
"lucide-react": "^0.523.0",
|
"lucide-react": "^0.523.0",
|
||||||
"millify": "^6.1.0",
|
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"motion": "^12.15.0",
|
"motion": "^12.15.0",
|
||||||
"next": "15.3.3",
|
"next": "15.3.3",
|
||||||
|
Reference in New Issue
Block a user