feat: Next.js 14 web admin scaffold — auth, sidebar, dashboard, placeholders
This commit is contained in:
71
app/(app)/clients/page.tsx
Normal file
71
app/(app)/clients/page.tsx
Normal file
@@ -0,0 +1,71 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Card, CardContent, CardHeader } from '@/components/ui/card';
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from '@/components/ui/table';
|
||||
import { Search, UserPlus } from 'lucide-react';
|
||||
|
||||
export default function ClientsPage() {
|
||||
const [search, setSearch] = useState('');
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="mb-6 flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold text-slate-800">Clients</h1>
|
||||
<p className="text-slate-500 text-sm mt-1">Manage your ISP subscribers</p>
|
||||
</div>
|
||||
<Button style={{ backgroundColor: '#0891B2' }}>
|
||||
<UserPlus size={16} className="mr-2" />
|
||||
Add Client
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Card className="border shadow-sm">
|
||||
<CardHeader className="pb-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="relative flex-1 max-w-sm">
|
||||
<Search size={16} className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-400" />
|
||||
<Input
|
||||
placeholder="Search clients..."
|
||||
className="pl-9"
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="p-0">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Name</TableHead>
|
||||
<TableHead>Email</TableHead>
|
||||
<TableHead>Phone</TableHead>
|
||||
<TableHead>Plan</TableHead>
|
||||
<TableHead>Status</TableHead>
|
||||
<TableHead>Actions</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell colSpan={6} className="text-center py-12 text-slate-400">
|
||||
No clients yet. Add your first client to get started.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
100
app/(app)/dashboard/page.tsx
Normal file
100
app/(app)/dashboard/page.tsx
Normal file
@@ -0,0 +1,100 @@
|
||||
'use client';
|
||||
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { api } from '@/lib/api';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
import { Users, Wifi, DollarSign, AlertTriangle } from 'lucide-react';
|
||||
|
||||
interface DashboardSummary {
|
||||
totalClients: number;
|
||||
activeSubscribers: number;
|
||||
todayCollections: number;
|
||||
overdueInvoices: number;
|
||||
}
|
||||
|
||||
const kpiCards = [
|
||||
{
|
||||
key: 'totalClients' as const,
|
||||
label: 'Total Clients',
|
||||
icon: Users,
|
||||
color: '#0891B2',
|
||||
format: (v: number) => v.toLocaleString(),
|
||||
},
|
||||
{
|
||||
key: 'activeSubscribers' as const,
|
||||
label: 'Active Subscribers',
|
||||
icon: Wifi,
|
||||
color: '#059669',
|
||||
format: (v: number) => v.toLocaleString(),
|
||||
},
|
||||
{
|
||||
key: 'todayCollections' as const,
|
||||
label: "Today's Collections",
|
||||
icon: DollarSign,
|
||||
color: '#7C3AED',
|
||||
format: (v: number) => '₱' + v.toLocaleString('en-PH', { minimumFractionDigits: 2 }),
|
||||
},
|
||||
{
|
||||
key: 'overdueInvoices' as const,
|
||||
label: 'Overdue Invoices',
|
||||
icon: AlertTriangle,
|
||||
color: '#DC2626',
|
||||
format: (v: number) => v.toLocaleString(),
|
||||
},
|
||||
];
|
||||
|
||||
export default function DashboardPage() {
|
||||
const { data, isLoading, error } = useQuery<DashboardSummary>({
|
||||
queryKey: ['dashboard', 'summary'],
|
||||
queryFn: async () => {
|
||||
const res = await api.get('/api/v1/dashboard/summary');
|
||||
return res.data;
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="mb-6">
|
||||
<h1 className="text-2xl font-bold text-slate-800">Dashboard</h1>
|
||||
<p className="text-slate-500 text-sm mt-1">Overview of your ISP operations</p>
|
||||
</div>
|
||||
|
||||
{error && (
|
||||
<div className="mb-4 p-3 bg-red-50 border border-red-200 rounded-lg text-red-600 text-sm">
|
||||
Failed to load dashboard data. The API endpoint may not be available yet.
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-4">
|
||||
{kpiCards.map((card) => {
|
||||
const Icon = card.icon;
|
||||
return (
|
||||
<Card key={card.key} className="border shadow-sm">
|
||||
<CardHeader className="flex flex-row items-center justify-between pb-2">
|
||||
<CardTitle className="text-sm font-medium text-slate-500">
|
||||
{card.label}
|
||||
</CardTitle>
|
||||
<div
|
||||
className="w-9 h-9 rounded-lg flex items-center justify-center"
|
||||
style={{ backgroundColor: card.color + '1A' }}
|
||||
>
|
||||
<Icon size={18} style={{ color: card.color }} />
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{isLoading ? (
|
||||
<Skeleton className="h-8 w-24" />
|
||||
) : (
|
||||
<p className="text-2xl font-bold text-slate-800">
|
||||
{data ? card.format(data[card.key]) : '—'}
|
||||
</p>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
54
app/(app)/invoices/page.tsx
Normal file
54
app/(app)/invoices/page.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
'use client';
|
||||
|
||||
import { Card, CardContent, CardHeader } from '@/components/ui/card';
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from '@/components/ui/table';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Search } from 'lucide-react';
|
||||
|
||||
export default function InvoicesPage() {
|
||||
return (
|
||||
<div>
|
||||
<div className="mb-6">
|
||||
<h1 className="text-2xl font-bold text-slate-800">Invoices</h1>
|
||||
<p className="text-slate-500 text-sm mt-1">Track and manage billing invoices</p>
|
||||
</div>
|
||||
|
||||
<Card className="border shadow-sm">
|
||||
<CardHeader className="pb-4">
|
||||
<div className="relative max-w-sm">
|
||||
<Search size={16} className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-400" />
|
||||
<Input placeholder="Search invoices..." className="pl-9" />
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="p-0">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Invoice #</TableHead>
|
||||
<TableHead>Client</TableHead>
|
||||
<TableHead>Amount</TableHead>
|
||||
<TableHead>Due Date</TableHead>
|
||||
<TableHead>Status</TableHead>
|
||||
<TableHead>Actions</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell colSpan={6} className="text-center py-12 text-slate-400">
|
||||
No invoices found.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
32
app/(app)/layout.tsx
Normal file
32
app/(app)/layout.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useAuthStore } from '@/lib/auth-store';
|
||||
import Sidebar from '@/components/layout/sidebar';
|
||||
import Topbar from '@/components/layout/topbar';
|
||||
|
||||
export default function AppLayout({ children }: { children: React.ReactNode }) {
|
||||
const router = useRouter();
|
||||
const accessToken = useAuthStore((s) => s.accessToken);
|
||||
|
||||
useEffect(() => {
|
||||
if (!accessToken) {
|
||||
router.replace('/login');
|
||||
}
|
||||
}, [accessToken, router]);
|
||||
|
||||
if (!accessToken) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex min-h-screen" style={{ backgroundColor: '#F8FAFC' }}>
|
||||
<Sidebar />
|
||||
<div className="flex-1 flex flex-col overflow-hidden">
|
||||
<Topbar />
|
||||
<main className="flex-1 overflow-y-auto p-6">{children}</main>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
54
app/(app)/payments/page.tsx
Normal file
54
app/(app)/payments/page.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
'use client';
|
||||
|
||||
import { Card, CardContent, CardHeader } from '@/components/ui/card';
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from '@/components/ui/table';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Search } from 'lucide-react';
|
||||
|
||||
export default function PaymentsPage() {
|
||||
return (
|
||||
<div>
|
||||
<div className="mb-6">
|
||||
<h1 className="text-2xl font-bold text-slate-800">Payments</h1>
|
||||
<p className="text-slate-500 text-sm mt-1">Record and review payment transactions</p>
|
||||
</div>
|
||||
|
||||
<Card className="border shadow-sm">
|
||||
<CardHeader className="pb-4">
|
||||
<div className="relative max-w-sm">
|
||||
<Search size={16} className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-400" />
|
||||
<Input placeholder="Search payments..." className="pl-9" />
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="p-0">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Ref #</TableHead>
|
||||
<TableHead>Client</TableHead>
|
||||
<TableHead>Amount</TableHead>
|
||||
<TableHead>Channel</TableHead>
|
||||
<TableHead>Date</TableHead>
|
||||
<TableHead>Actions</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell colSpan={6} className="text-center py-12 text-slate-400">
|
||||
No payments recorded yet.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
47
app/(app)/remittances/page.tsx
Normal file
47
app/(app)/remittances/page.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
'use client';
|
||||
|
||||
import { Card, CardContent, CardHeader } from '@/components/ui/card';
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from '@/components/ui/table';
|
||||
|
||||
export default function RemittancesPage() {
|
||||
return (
|
||||
<div>
|
||||
<div className="mb-6">
|
||||
<h1 className="text-2xl font-bold text-slate-800">Remittances</h1>
|
||||
<p className="text-slate-500 text-sm mt-1">Collector cash remittance management</p>
|
||||
</div>
|
||||
|
||||
<Card className="border shadow-sm">
|
||||
<CardHeader className="pb-4" />
|
||||
<CardContent className="p-0">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Reference</TableHead>
|
||||
<TableHead>Collector</TableHead>
|
||||
<TableHead>Amount</TableHead>
|
||||
<TableHead>Date</TableHead>
|
||||
<TableHead>Status</TableHead>
|
||||
<TableHead>Actions</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell colSpan={6} className="text-center py-12 text-slate-400">
|
||||
No remittances found.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
33
app/(app)/reports/page.tsx
Normal file
33
app/(app)/reports/page.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
'use client';
|
||||
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { BarChart3 } from 'lucide-react';
|
||||
|
||||
export default function ReportsPage() {
|
||||
return (
|
||||
<div>
|
||||
<div className="mb-6">
|
||||
<h1 className="text-2xl font-bold text-slate-800">Reports</h1>
|
||||
<p className="text-slate-500 text-sm mt-1">Financial and operational reports</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
{['Collections Report', 'Subscriber Growth', 'Invoice Aging', 'Technician Performance'].map(
|
||||
(report) => (
|
||||
<Card key={report} className="border shadow-sm hover:shadow-md transition-shadow cursor-pointer">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-base flex items-center gap-2 text-slate-700">
|
||||
<BarChart3 size={18} style={{ color: '#0891B2' }} />
|
||||
{report}
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p className="text-slate-400 text-sm">Coming soon — report generation will be available here.</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
30
app/(app)/settings/areas/page.tsx
Normal file
30
app/(app)/settings/areas/page.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
'use client';
|
||||
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Plus, MapPin } from 'lucide-react';
|
||||
|
||||
export default function AreasPage() {
|
||||
return (
|
||||
<div>
|
||||
<div className="mb-6 flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold text-slate-800">Areas & Zones</h1>
|
||||
<p className="text-slate-500 text-sm mt-1">Define service coverage areas</p>
|
||||
</div>
|
||||
<Button style={{ backgroundColor: '#0891B2' }}>
|
||||
<Plus size={16} className="mr-2" />
|
||||
Add Area
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Card className="border shadow-sm">
|
||||
<CardContent className="flex flex-col items-center justify-center py-16 text-slate-400">
|
||||
<MapPin size={32} className="mb-3 text-slate-300" />
|
||||
<p className="text-sm font-medium">No areas defined yet</p>
|
||||
<p className="text-xs mt-1">Create areas to group clients by coverage zone</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
31
app/(app)/settings/plans/page.tsx
Normal file
31
app/(app)/settings/plans/page.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
'use client';
|
||||
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Plus } from 'lucide-react';
|
||||
|
||||
export default function PlansPage() {
|
||||
return (
|
||||
<div>
|
||||
<div className="mb-6 flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold text-slate-800">Service Plans</h1>
|
||||
<p className="text-slate-500 text-sm mt-1">Manage internet subscription plans</p>
|
||||
</div>
|
||||
<Button style={{ backgroundColor: '#0891B2' }}>
|
||||
<Plus size={16} className="mr-2" />
|
||||
Add Plan
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<Card className="border shadow-sm border-dashed border-slate-300">
|
||||
<CardContent className="flex flex-col items-center justify-center py-12 text-slate-400">
|
||||
<Plus size={24} className="mb-2" />
|
||||
<p className="text-sm">Create your first plan</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
43
app/(app)/settings/tenant/page.tsx
Normal file
43
app/(app)/settings/tenant/page.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
'use client';
|
||||
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { Button } from '@/components/ui/button';
|
||||
|
||||
export default function TenantSettingsPage() {
|
||||
return (
|
||||
<div>
|
||||
<div className="mb-6">
|
||||
<h1 className="text-2xl font-bold text-slate-800">Tenant Settings</h1>
|
||||
<p className="text-slate-500 text-sm mt-1">Configure your ISP business details</p>
|
||||
</div>
|
||||
|
||||
<Card className="border shadow-sm max-w-2xl">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-base">Business Information</CardTitle>
|
||||
<CardDescription>Update your ISP company details</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="space-y-1.5">
|
||||
<Label>Business Name</Label>
|
||||
<Input placeholder="e.g. My Internet Services" />
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<Label>Address</Label>
|
||||
<Input placeholder="Business address" />
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<Label>Phone</Label>
|
||||
<Input placeholder="+63 9XX XXX XXXX" />
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<Label>Email</Label>
|
||||
<Input type="email" placeholder="info@yourisp.com" />
|
||||
</div>
|
||||
<Button style={{ backgroundColor: '#0891B2' }}>Save Changes</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
53
app/(app)/settings/users/page.tsx
Normal file
53
app/(app)/settings/users/page.tsx
Normal file
@@ -0,0 +1,53 @@
|
||||
'use client';
|
||||
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from '@/components/ui/table';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { UserPlus } from 'lucide-react';
|
||||
|
||||
export default function UsersPage() {
|
||||
return (
|
||||
<div>
|
||||
<div className="mb-6 flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold text-slate-800">Users</h1>
|
||||
<p className="text-slate-500 text-sm mt-1">Manage staff accounts and permissions</p>
|
||||
</div>
|
||||
<Button style={{ backgroundColor: '#0891B2' }}>
|
||||
<UserPlus size={16} className="mr-2" />
|
||||
Invite User
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Card className="border shadow-sm">
|
||||
<CardContent className="p-0">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Name</TableHead>
|
||||
<TableHead>Email</TableHead>
|
||||
<TableHead>Role</TableHead>
|
||||
<TableHead>Status</TableHead>
|
||||
<TableHead>Actions</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell colSpan={5} className="text-center py-12 text-slate-400">
|
||||
No users found. Invite your team members.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
62
app/(app)/tickets/page.tsx
Normal file
62
app/(app)/tickets/page.tsx
Normal file
@@ -0,0 +1,62 @@
|
||||
'use client';
|
||||
|
||||
import { Card, CardContent, CardHeader } from '@/components/ui/card';
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from '@/components/ui/table';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Search, Plus } from 'lucide-react';
|
||||
|
||||
export default function TicketsPage() {
|
||||
return (
|
||||
<div>
|
||||
<div className="mb-6 flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold text-slate-800">Tickets</h1>
|
||||
<p className="text-slate-500 text-sm mt-1">Support and installation tickets</p>
|
||||
</div>
|
||||
<Button style={{ backgroundColor: '#0891B2' }}>
|
||||
<Plus size={16} className="mr-2" />
|
||||
New Ticket
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Card className="border shadow-sm">
|
||||
<CardHeader className="pb-4">
|
||||
<div className="relative max-w-sm">
|
||||
<Search size={16} className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-400" />
|
||||
<Input placeholder="Search tickets..." className="pl-9" />
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="p-0">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Ticket #</TableHead>
|
||||
<TableHead>Client</TableHead>
|
||||
<TableHead>Type</TableHead>
|
||||
<TableHead>Priority</TableHead>
|
||||
<TableHead>Status</TableHead>
|
||||
<TableHead>Assigned To</TableHead>
|
||||
<TableHead>Actions</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell colSpan={7} className="text-center py-12 text-slate-400">
|
||||
No tickets found.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user