Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/web/app/(auth)/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default function LoginPage() {
<h1 className="text-2xl font-semibold tracking-tight">
Welcome back
</h1>
<p className="text-sm text-gray-500 mt-2">
<p className="text-sm text-muted-foreground mt-2">
Enter your credentials to access your account
</p>
</div>
Expand Down
16 changes: 7 additions & 9 deletions apps/web/app/(dashboard)/error.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use client';

import { useEffect } from 'react';
import { Button } from '@/components/ui/button';

export default function DashboardError({
error,
Expand All @@ -16,9 +17,9 @@ export default function DashboardError({

return (
<div className="flex flex-col items-center justify-center min-h-[50vh] p-8 text-center">
<div className="rounded-full bg-red-100 p-4 mb-4">
<div className="rounded-full bg-destructive/10 p-4 mb-4">
<svg
className="h-8 w-8 text-red-600"
className="h-8 w-8 text-destructive"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
Expand All @@ -31,18 +32,15 @@ export default function DashboardError({
/>
</svg>
</div>
<h2 className="text-xl font-semibold text-gray-900 mb-2">
<h2 className="text-xl font-semibold text-foreground mb-2">
Unable to load dashboard
</h2>
<p className="text-gray-500 mb-6 max-w-md">
<p className="text-muted-foreground mb-6 max-w-md">
We encountered a problem while attempting to load your dashboard data. Please try again later.
</p>
<button
onClick={() => reset()}
className="px-4 py-2 bg-blue-600 text-white font-medium rounded hover:bg-blue-700 transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
>
<Button onClick={() => reset()}>
Try again
</button>
</Button>
</div>
);
}
17 changes: 12 additions & 5 deletions apps/web/app/(dashboard)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { AuthGuard } from '@/features/auth';
import { Sidebar } from '@/components/layout/sidebar';
import { Navbar } from '@/components/layout/navbar';

export default function DashboardLayout({
children,
Expand All @@ -7,11 +9,16 @@ export default function DashboardLayout({
}) {
return (
<AuthGuard>
<div className="flex min-h-screen w-full flex-col">
{/* Skeleton for future Sidebar/Header */}
<main className="flex-1 overflow-auto">
{children}
</main>
<div className="flex min-h-screen w-full bg-background text-foreground">
<div className="hidden md:flex">
<Sidebar />
</div>
<div className="flex w-full flex-col">
<Navbar />
<main className="flex-1 overflow-auto p-4 md:p-6 lg:p-8">
{children}
</main>
</div>
</div>
</AuthGuard>
)
Expand Down
30 changes: 15 additions & 15 deletions apps/web/app/(dashboard)/loading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,37 @@ export default function DashboardLoading() {
return (
<div className="p-8 max-w-7xl mx-auto w-full">
<header className="mb-8 animate-pulse">
<div className="h-8 w-64 bg-gray-200 rounded mb-2"></div>
<div className="h-4 w-96 bg-gray-200 rounded"></div>
<div className="h-8 w-64 bg-muted rounded mb-2"></div>
<div className="h-4 w-96 bg-muted rounded"></div>
</header>

<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4 mb-8">
{[1, 2, 3, 4].map((i) => (
<div key={i} className="rounded-lg border bg-white p-6 shadow-sm animate-pulse">
<div className="h-4 w-24 bg-gray-200 rounded mb-4"></div>
<div className="h-8 w-16 bg-gray-200 rounded mb-2"></div>
<div className="h-3 w-32 bg-gray-200 rounded"></div>
<div key={i} className="rounded-lg border border-border bg-card p-6 shadow-sm animate-pulse">
<div className="h-4 w-24 bg-muted rounded mb-4"></div>
<div className="h-8 w-16 bg-muted rounded mb-2"></div>
<div className="h-3 w-32 bg-muted rounded"></div>
</div>
))}
</div>

<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
<div className="rounded-lg border bg-white p-6 shadow-sm h-64 animate-pulse"></div>
<div className="rounded-lg border p-6 shadow-sm h-64 animate-pulse bg-gray-50"></div>
<div className="rounded-lg border border-border bg-card p-6 shadow-sm h-64 animate-pulse"></div>
<div className="rounded-lg border border-border p-6 shadow-sm h-64 animate-pulse bg-muted/20"></div>
</div>

<div className="rounded-lg border bg-white shadow-sm overflow-hidden animate-pulse">
<div className="p-6 border-b border-gray-100">
<div className="h-5 w-32 bg-gray-200 rounded"></div>
<div className="rounded-lg border border-border bg-card shadow-sm overflow-hidden animate-pulse">
<div className="p-6 border-b border-border">
<div className="h-5 w-32 bg-muted rounded"></div>
</div>
<div className="divide-y divide-gray-100">
<div className="divide-y divide-border">
{[1, 2, 3].map((i) => (
<div key={i} className="p-6 flex items-center justify-between">
<div className="flex gap-4 items-center">
<div className="h-10 w-10 bg-gray-200 rounded-full"></div>
<div className="h-10 w-10 bg-muted rounded-full"></div>
<div className="space-y-2">
<div className="h-4 w-48 bg-gray-200 rounded"></div>
<div className="h-3 w-24 bg-gray-200 rounded"></div>
<div className="h-4 w-48 bg-muted rounded"></div>
<div className="h-3 w-24 bg-muted rounded"></div>
</div>
</div>
</div>
Expand Down
38 changes: 19 additions & 19 deletions apps/web/app/(dashboard)/tickets/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,17 @@ export default async function TicketDetailPage({
return (
<div className="p-8 max-w-5xl mx-auto w-full">
<div className="mb-6">
<Link href="/tickets" className="text-sm text-blue-600 hover:text-blue-900 flex items-center">
<Link href="/tickets" className="text-sm text-primary hover:text-primary/80 flex items-center">
&larr; Back to tickets
</Link>
</div>

<div className="bg-white shadow-sm ring-1 ring-black/5 rounded-lg overflow-hidden">
<div className="p-6 sm:p-8 border-b border-gray-200">
<div className="bg-card shadow-sm border border-border rounded-lg overflow-hidden">
<div className="p-6 sm:p-8 border-b border-border">
<div className="flex flex-col sm:flex-row sm:items-start sm:justify-between gap-4">
<div>
<h1 className="text-2xl font-bold text-gray-900">{ticket.title}</h1>
<p className="text-sm text-gray-500 mt-1">Ticket ID: {ticket.id}</p>
<h1 className="text-2xl font-bold text-foreground">{ticket.title}</h1>
<p className="text-sm text-muted-foreground mt-1">Ticket ID: {ticket.id}</p>
</div>
<div className="flex items-center gap-2">
<TicketStatusBadge status={ticket.status} />
Expand All @@ -44,19 +44,19 @@ export default async function TicketDetailPage({
</div>

<div className="p-6 sm:p-8">
<h3 className="text-lg font-medium text-gray-900 mb-2">Description</h3>
<div className="prose max-w-none text-gray-700">
<h3 className="text-lg font-medium text-foreground mb-2">Description</h3>
<div className="prose max-w-none text-muted-foreground">
{ticket.description || 'No description provided.'}
</div>

<div className="mt-8 grid grid-cols-1 sm:grid-cols-2 gap-6">
<div>
<h4 className="text-sm font-medium text-gray-500">Category</h4>
<p className="mt-1 text-sm text-gray-900">{ticket.category || 'None'}</p>
<h4 className="text-sm font-medium text-muted-foreground">Category</h4>
<p className="mt-1 text-sm text-foreground">{ticket.category || 'None'}</p>
</div>
<div>
<h4 className="text-sm font-medium text-gray-500">Created At</h4>
<p className="mt-1 text-sm text-gray-900">{new Date(ticket.created_at).toLocaleString()}</p>
<h4 className="text-sm font-medium text-muted-foreground">Created At</h4>
<p className="mt-1 text-sm text-foreground">{new Date(ticket.created_at).toLocaleString()}</p>
</div>
</div>
</div>
Expand All @@ -68,32 +68,32 @@ export default async function TicketDetailPage({
</div>

{history.length > 0 && (
<div className="bg-white p-6 sm:p-8 rounded-lg shadow-sm ring-1 ring-black/5 mt-6">
<h3 className="text-lg font-medium text-gray-900 mb-4">Assignment History</h3>
<div className="bg-card p-6 sm:p-8 rounded-lg shadow-sm border border-border mt-6">
<h3 className="text-lg font-medium text-foreground mb-4">Assignment History</h3>
<div className="flow-root">
<ul role="list" className="-mb-8">
{history.map((event, eventIdx) => (
<li key={event.id}>
<div className="relative pb-8">
{eventIdx !== history.length - 1 ? (
<span className="absolute left-4 top-4 -ml-px h-full w-0.5 bg-gray-200" aria-hidden="true" />
<span className="absolute left-4 top-4 -ml-px h-full w-0.5 bg-border" aria-hidden="true" />
) : null}
<div className="relative flex space-x-3">
<div>
<span className="h-8 w-8 rounded-full bg-gray-100 flex items-center justify-center ring-8 ring-white">
<svg className="h-5 w-5 text-gray-500" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<span className="h-8 w-8 rounded-full bg-muted flex items-center justify-center ring-8 ring-background">
<svg className="h-5 w-5 text-muted-foreground" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fillRule="evenodd" d="M10 2a8 8 0 100 16 8 8 0 000-16zM9 10a1 1 0 112 0v2a1 1 0 11-2 0v-2zm1-4a1 1 0 100 2 1 1 0 000-2z" clipRule="evenodd" />
</svg>
</span>
</div>
<div className="flex min-w-0 flex-1 justify-between space-x-4 pt-1.5">
<div>
<p className="text-sm text-gray-500">
<p className="text-sm text-muted-foreground">
{event.action_type.replace('_', ' ')}
{event.assigned_to && <span className="font-medium text-gray-900"> to {event.assigned_to}</span>}
{event.assigned_to && <span className="font-medium text-foreground"> to {event.assigned_to}</span>}
</p>
</div>
<div className="whitespace-nowrap text-right text-sm text-gray-500">
<div className="whitespace-nowrap text-right text-sm text-muted-foreground">
<time dateTime={event.created_at}>{new Date(event.created_at).toLocaleString()}</time>
</div>
</div>
Expand Down
12 changes: 5 additions & 7 deletions apps/web/app/(dashboard)/tickets/error.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use client';

import { useEffect } from 'react';
import { Button } from '@/components/ui/button';

export default function TicketsError({
error,
Expand All @@ -15,14 +16,11 @@ export default function TicketsError({

return (
<div className="p-8 max-w-7xl mx-auto w-full text-center py-20">
<h2 className="text-2xl font-bold text-gray-900 mb-4">Something went wrong!</h2>
<p className="text-gray-500 mb-8">{error.message || 'Failed to load tickets.'}</p>
<button
onClick={() => reset()}
className="rounded-md bg-blue-600 px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-blue-500 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600"
>
<h2 className="text-2xl font-bold text-foreground mb-4">Something went wrong!</h2>
<p className="text-muted-foreground mb-8">{error.message || 'Failed to load tickets.'}</p>
<Button onClick={() => reset()}>
Try again
</button>
</Button>
</div>
);
}
16 changes: 8 additions & 8 deletions apps/web/app/(dashboard)/tickets/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default async function TicketsPage({

const cookieStore = await cookies();
const allCookies = cookieStore.getAll().map((c: { name: string; value: string }) => `${c.name}=${c.value}`).join('; ');

const response = await ticketService.getTickets(
{ page, limit, status, priority, search },
{ Cookie: allCookies }
Expand All @@ -30,22 +30,22 @@ export default async function TicketsPage({
<div className="p-8 max-w-7xl mx-auto w-full">
<div className="sm:flex sm:items-center sm:justify-between mb-8">
<div>
<h1 className="text-2xl font-bold leading-7 text-gray-900 sm:truncate sm:text-3xl sm:tracking-tight">
<h1 className="text-2xl font-bold leading-7 text-foreground sm:truncate sm:text-3xl sm:tracking-tight">
Tickets
</h1>
<p className="mt-2 text-sm text-gray-500">
<p className="mt-2 text-sm text-muted-foreground">
A list of all tickets in your account including their status, priority, and category.
</p>
</div>
</div>

<TicketFilters />

<TicketTable tickets={response.data} />
<TicketPagination
page={response.page}
limit={response.limit}

<TicketPagination
page={response.page}
limit={response.limit}
total={response.total}
pages={response.pages}
hasMore={response.data.length === response.limit}
Expand Down
6 changes: 3 additions & 3 deletions apps/web/app/(dashboard)/users/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ export default async function EditUserPage({
return (
<div className="space-y-6 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div className="mb-8">
<h1 className="text-2xl font-bold leading-7 text-gray-900 sm:truncate sm:text-3xl sm:tracking-tight">
Manage User: {user.full_name}
<h1 className="text-2xl font-bold leading-7 text-foreground sm:truncate sm:text-3xl sm:tracking-tight">
Edit User
</h1>
<p className="mt-1 text-sm text-gray-500">
<p className="mt-1 text-sm text-muted-foreground">
Update user details, change roles, or modify account status.
</p>
</div>
Expand Down
33 changes: 19 additions & 14 deletions apps/web/app/(dashboard)/users/error.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use client';

import { useEffect } from 'react';
import { Button } from '@/components/ui/button';

export default function UsersError({
error,
Expand All @@ -15,22 +16,26 @@ export default function UsersError({

return (
<div className="flex flex-col items-center justify-center h-[50vh] px-4">
<div className="text-center space-y-4 max-w-md w-full bg-white p-8 rounded-lg border border-red-100 shadow-sm">
<div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-red-100">
<svg className="h-6 w-6 text-red-600" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
<div className="text-center space-y-4 max-w-md w-full bg-card p-8 rounded-lg border border-destructive/20 shadow-sm">
<div className="flex justify-center">
<div className="h-12 w-12 rounded-full bg-destructive/10 flex items-center justify-center">
<svg className="h-6 w-6 text-destructive" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
</div>
</div>
<h2 className="text-lg font-semibold text-gray-900">Failed to load users</h2>
<p className="text-sm text-gray-500">
{error.message || 'An unexpected error occurred while loading the user list.'}
<h2 className="text-lg font-semibold text-foreground">Failed to load users</h2>
<p className="text-sm text-muted-foreground">
{error.message || 'An unexpected error occurred while fetching user data.'}
</p>
<button
onClick={reset}
className="inline-flex justify-center w-full px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
>
Try again
</button>
<div className="pt-4">
<Button
onClick={() => reset()}
className="w-full"
>
Try again
</Button>
</div>
</div>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion apps/web/app/(dashboard)/users/loading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default function UsersLoading() {
<div className="h-10 w-48 bg-gray-200 rounded"></div>
</div>

<div className="bg-white rounded-lg border border-gray-200 p-8 h-96">
<div className="bg-card rounded-lg border border-border p-8 h-96">
<div className="h-full w-full bg-gray-100 rounded"></div>
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions apps/web/app/(dashboard)/users/new/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ export default function NewUserPage() {
return (
<div className="space-y-6 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div className="mb-8">
<h1 className="text-2xl font-bold leading-7 text-gray-900 sm:truncate sm:text-3xl sm:tracking-tight">
<h1 className="text-2xl font-bold leading-7 text-foreground sm:truncate sm:text-3xl sm:tracking-tight">
Create New User
</h1>
<p className="mt-1 text-sm text-gray-500">
<p className="mt-1 text-sm text-muted-foreground">
Add a new user to the system and assign their role.
</p>
</div>
Expand Down
Loading
Loading