refactor: redesign table module

This commit is contained in:
2026-03-18 01:03:58 +05:30
parent caf527f584
commit 344f37719e
24 changed files with 991 additions and 815 deletions

View File

@@ -23,6 +23,8 @@ import {
} from "@/lib/api"
import { ColumnDef } from "@tanstack/react-table"
import { toast } from "sonner"
import { Badge } from "@/components/ui/badge"
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
import { PoweredBy } from "@/components/powered-by"
export default function PackagePage() {
@@ -108,7 +110,9 @@ export default function PackagePage() {
region: region.trim() || null,
}
await updatePackage(currentPackage.id, data)
toast.success("Package updated successfully!")
toast.success("Package Updated", {
description: `${name} has been updated successfully at ${new Date().toLocaleTimeString()}`,
})
} else {
const data: PackageCreate = {
project_id: selectedProjectId,
@@ -116,7 +120,9 @@ export default function PackagePage() {
region: region.trim() || null,
}
await createPackage(data)
toast.success("Package created successfully!")
toast.success("Package Created", {
description: `${name} has been established successfully at ${new Date().toLocaleTimeString()}`,
})
}
// Refresh packages list
@@ -126,7 +132,11 @@ export default function PackagePage() {
setIsModalOpen(false)
resetForm()
} catch (err) {
setError(err instanceof Error ? err.message : `Failed to ${isEditing ? 'update' : 'create'} package`)
const message = err instanceof Error ? err.message : `Failed to ${isEditing ? 'update' : 'create'} package`
setError(message)
toast.error("Operation Failed", {
description: message,
})
} finally {
setIsSubmitting(false)
}
@@ -147,10 +157,15 @@ export default function PackagePage() {
try {
setIsLoading(true)
await deletePackage(pkg.id)
toast.success("Package deleted successfully!")
toast.success("Package Deleted", {
description: `${pkg.name} has been removed from the system.`,
})
await loadPackages()
} catch (err) {
setError("Failed to delete package")
toast.error("Deletion Failed", {
description: "The package could not be removed. Please try again.",
})
} finally {
setIsLoading(false)
}
@@ -180,16 +195,38 @@ export default function PackagePage() {
const pkg = row.original
const project = projects.find(p => p.id === pkg.project_id)
if (!project?.state) return <span className="text-gray-400"></span>
const states = project.state.split(',').map(s => s.trim()).filter(Boolean)
if (states.length === 0) return <span className="text-gray-400"></span>
const firstState = states[0]
const remainingStates = states.slice(1)
return (
<div className="flex flex-wrap gap-1">
{project.state.split(',').map((item, idx) => (
<span
key={idx}
className="px-2 py-0.5 rounded-full bg-blue-50 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 font-semibold border border-blue-100 dark:border-blue-800"
>
{item.trim()}
</span>
))}
<div className="flex items-center gap-1.5">
<Badge variant="secondary">
{firstState}
</Badge>
{remainingStates.length > 0 && (
<Popover>
<PopoverTrigger asChild>
<button className="flex items-center justify-center rounded-full bg-muted/50 hover:bg-muted px-1.5 py-0.5 text-[10px] font-bold text-muted-foreground transition-colors border border-border/40">
+{remainingStates.length}
</button>
</PopoverTrigger>
<PopoverContent className="w-auto p-2" align="start">
<div className="flex flex-col gap-1.5">
<p className="text-[10px] font-bold text-muted-foreground uppercase tracking-wider mb-0.5 px-1">Other States</p>
{remainingStates.map((item, idx) => (
<Badge key={idx} variant="secondary">
{item}
</Badge>
))}
</div>
</PopoverContent>
</Popover>
)}
</div>
)
}
@@ -201,27 +238,26 @@ export default function PackagePage() {
]
return (
<div className="min-h-screen text-gray-900 dark:text-gray-100">
<main className="min-h-screen relative overflow-hidden">
<div className="mx-auto px-6 py-8 max-w-340 relative z-10">
<>
<main className="relative z-10">
{/* Refined Header */}
<div className="mb-8">
<PageHeader
title="Package Management"
description="Manage project packages"
icon={Package}
actions={
<Button
onClick={() => { setIsEditing(false); setIsModalOpen(true); }}
>
<Package className="mr-2 h-4 w-4" />
Add New Package
</Button>
}
/>
</div>
{/* Error Message */}
{error && !isModalOpen && (
<div className="mb-6 flex items-center gap-3 p-4 rounded-xl bg-red-50 dark:bg-red-950/30 border border-red-200 dark:border-red-800">
<div className="w-5 h-5 rounded-full bg-red-100 dark:bg-red-900 flex items-center justify-center shrink-0">
<span className="text-xs font-bold text-red-500">!</span>
</div>
<p className="text-sm text-red-600 dark:text-red-400 break-all">{error}</p>
</div>
)}
{/* Data Table */}
<div>
@@ -229,10 +265,8 @@ export default function PackagePage() {
title="Packages"
data={packages}
columns={columns}
onAddNew={() => { setIsEditing(false); setIsModalOpen(true); }}
onEdit={handleEdit}
onDelete={handleDelete}
addButtonText="Add New Package"
isLoading={isLoading}
pagination={{
skip,
@@ -247,8 +281,7 @@ export default function PackagePage() {
</div>
<PoweredBy />
</div>
</main>
</main>
{/* Modal Dialog */}
<Dialog open={isModalOpen} onOpenChange={(open) => { if (!open) { setIsModalOpen(false); resetForm(); } else { setIsModalOpen(true); } }}>
@@ -269,15 +302,6 @@ export default function PackagePage() {
</DialogHeader>
{/* Error Message in Modal */}
{error && (
<div className="flex items-center gap-3 p-4 rounded-xl bg-red-50 dark:bg-red-950/30 border border-red-200 dark:border-red-800">
<div className="w-5 h-5 rounded-full bg-red-100 dark:bg-red-900 flex items-center justify-center shrink-0">
<span className="text-xs font-bold text-red-500">!</span>
</div>
<p className="text-sm text-red-600 dark:text-red-400 break-all">{error}</p>
</div>
)}
<form onSubmit={handleSubmit} className="space-y-8">
{/* Step 1: Select Project */}
@@ -371,7 +395,7 @@ export default function PackagePage() {
<Button
type="submit"
disabled={isSubmitting || !name.trim() || !selectedProjectId}
className="flex-1 h-12 font-bold uppercase tracking-wider text-xs shadow-lg shadow-primary/20"
className="flex-1 h-12 font-bold uppercase tracking-wider text-xs"
>
{isSubmitting ? (
<div className="flex items-center gap-2">
@@ -389,6 +413,6 @@ export default function PackagePage() {
</form>
</DialogContent>
</Dialog>
</div>
</>
)
}