updates
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
"use client"
|
||||
|
||||
import { ResourcePage } from "@/shared/data-view/resource-page"
|
||||
import { ColumnHeader } from "@/shared/data-view/table-view"
|
||||
import { PartForm } from "@/modules/parts/part-form"
|
||||
import { Badge } from "@/shared/components/ui/badge"
|
||||
import { PARTS_ROUTES } from "@repo/api"
|
||||
import type { PartsClient } from "@repo/api"
|
||||
|
||||
export default function PartsPage() {
|
||||
return (
|
||||
<ResourcePage<PartsClient>
|
||||
pageTitle="Parts"
|
||||
title="Part"
|
||||
routeKey={PARTS_ROUTES.INDEX}
|
||||
getClient={(api) => api.parts}
|
||||
columns={({ actionsColumn }) => [
|
||||
{
|
||||
accessorKey: "title",
|
||||
header: ({ column }) => <ColumnHeader column={column} title="Title" />,
|
||||
cell: ({ row }) => {
|
||||
const r = row.original as any
|
||||
return (
|
||||
<div>
|
||||
<span className="font-medium">{r.title || "—"}</span>
|
||||
{r.sku && (
|
||||
<span className="ml-2 text-xs text-muted-foreground">{r.sku}</span>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "part_number",
|
||||
header: ({ column }) => <ColumnHeader column={column} title="Part #" />,
|
||||
cell: ({ row }) => (row.original as any).part_number || "—",
|
||||
},
|
||||
{
|
||||
accessorKey: "manufactured_by",
|
||||
header: ({ column }) => <ColumnHeader column={column} title="Manufacturer" />,
|
||||
cell: ({ row }) => (row.original as any).manufactured_by || "—",
|
||||
},
|
||||
{
|
||||
accessorKey: "selling_price",
|
||||
header: ({ column }) => <ColumnHeader column={column} title="Sell Price" />,
|
||||
cell: ({ row }) => {
|
||||
const val = (row.original as any).selling_price
|
||||
return val != null ? `$${Number(val).toFixed(2)}` : "—"
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "purchase_price",
|
||||
header: ({ column }) => <ColumnHeader column={column} title="Cost" />,
|
||||
cell: ({ row }) => {
|
||||
const val = (row.original as any).purchase_price
|
||||
return val != null ? `$${Number(val).toFixed(2)}` : "—"
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "is_active",
|
||||
header: ({ column }) => <ColumnHeader column={column} title="Status" />,
|
||||
cell: ({ row }) => {
|
||||
const active = (row.original as any).is_active
|
||||
return (
|
||||
<Badge variant={active ? "default" : "secondary"}>
|
||||
{active ? "Active" : "Inactive"}
|
||||
</Badge>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "created_at",
|
||||
header: ({ column }) => <ColumnHeader column={column} title="Created" />,
|
||||
cell: ({ row }) => {
|
||||
const val = (row.original as any).created_at
|
||||
return val ? new Date(val).toLocaleDateString() : "—"
|
||||
},
|
||||
},
|
||||
actionsColumn(),
|
||||
]}
|
||||
renderForm={({ resourceId, initialData, onSuccess }) => (
|
||||
<PartForm
|
||||
resourceId={resourceId}
|
||||
initialData={initialData}
|
||||
onSuccess={onSuccess}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
"use client"
|
||||
|
||||
import { ResourcePage } from "@/shared/data-view/resource-page"
|
||||
import { ColumnHeader } from "@/shared/data-view/table-view"
|
||||
import { ServiceGroupForm } from "@/modules/service-groups/service-group-form"
|
||||
import { Badge } from "@/shared/components/ui/badge"
|
||||
import { SERVICE_GROUP_ROUTES } from "@repo/api"
|
||||
import type { ServiceGroupsClient } from "@repo/api"
|
||||
|
||||
export default function ServiceGroupPage() {
|
||||
return (
|
||||
<ResourcePage<ServiceGroupsClient>
|
||||
pageTitle="Service Groups"
|
||||
title="Service Group"
|
||||
routeKey={SERVICE_GROUP_ROUTES.INDEX}
|
||||
getClient={(api) => api.serviceGroups}
|
||||
columns={({ actionsColumn }) => [
|
||||
{
|
||||
accessorKey: "name",
|
||||
header: ({ column }) => <ColumnHeader column={column} title="Name" />,
|
||||
cell: ({ row }) => {
|
||||
const r = row.original as any
|
||||
return (
|
||||
<div>
|
||||
<span className="font-medium">{r.service_name || r.name || "—"}</span>
|
||||
{r.code && (
|
||||
<span className="ml-2 text-xs text-muted-foreground">{r.code}</span>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "selling_price",
|
||||
header: ({ column }) => <ColumnHeader column={column} title="Price" />,
|
||||
cell: ({ row }) => {
|
||||
const val = (row.original as any).selling_price
|
||||
return val != null ? `$${Number(val).toFixed(2)}` : "—"
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "is_active",
|
||||
header: ({ column }) => <ColumnHeader column={column} title="Status" />,
|
||||
cell: ({ row }) => {
|
||||
const active = (row.original as any).is_active
|
||||
return (
|
||||
<Badge variant={active ? "default" : "secondary"}>
|
||||
{active ? "Active" : "Inactive"}
|
||||
</Badge>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "created_at",
|
||||
header: ({ column }) => <ColumnHeader column={column} title="Created" />,
|
||||
cell: ({ row }) => {
|
||||
const val = (row.original as any).created_at
|
||||
return val ? new Date(val).toLocaleDateString() : "—"
|
||||
},
|
||||
},
|
||||
actionsColumn(),
|
||||
]}
|
||||
renderForm={({ resourceId, initialData, onSuccess }) => (
|
||||
<ServiceGroupForm
|
||||
resourceId={resourceId}
|
||||
initialData={initialData}
|
||||
onSuccess={onSuccess}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
"use client"
|
||||
|
||||
import { ResourcePage } from "@/shared/data-view/resource-page"
|
||||
import { ColumnHeader } from "@/shared/data-view/table-view"
|
||||
import { ServiceForm } from "@/modules/services/service-form"
|
||||
import { SERVICE_ROUTES } from "@repo/api"
|
||||
import type { ServicesClient } from "@repo/api"
|
||||
|
||||
export default function ServicesPage() {
|
||||
return (
|
||||
<ResourcePage<ServicesClient>
|
||||
pageTitle="Services"
|
||||
title="Service"
|
||||
routeKey={SERVICE_ROUTES.INDEX}
|
||||
getClient={(api) => api.services}
|
||||
columns={({ actionsColumn }) => [
|
||||
{
|
||||
accessorKey: "labor_name",
|
||||
header: ({ column }) => <ColumnHeader column={column} title="Name" />,
|
||||
cell: ({ row }) => {
|
||||
const r = row.original as any
|
||||
return (
|
||||
<div>
|
||||
<span className="font-medium">{r.labor_name || r.name || "—"}</span>
|
||||
{r.service_code && (
|
||||
<span className="ml-2 text-xs text-muted-foreground">{r.service_code}</span>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "description",
|
||||
header: ({ column }) => <ColumnHeader column={column} title="Description" />,
|
||||
cell: ({ row }) => {
|
||||
const val = (row.original as any).description
|
||||
return val
|
||||
? <span className="max-w-[200px] truncate block">{val}</span>
|
||||
: "—"
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "selling_price",
|
||||
header: ({ column }) => <ColumnHeader column={column} title="Price" />,
|
||||
cell: ({ row }) => {
|
||||
const val = (row.original as any).selling_price
|
||||
return val != null ? `$${Number(val).toFixed(2)}` : "—"
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "created_at",
|
||||
header: ({ column }) => <ColumnHeader column={column} title="Created" />,
|
||||
cell: ({ row }) => {
|
||||
const val = (row.original as any).created_at
|
||||
return val ? new Date(val).toLocaleDateString() : "—"
|
||||
},
|
||||
},
|
||||
actionsColumn(),
|
||||
]}
|
||||
renderForm={({ resourceId, initialData, onSuccess }) => (
|
||||
<ServiceForm
|
||||
resourceId={resourceId}
|
||||
initialData={initialData}
|
||||
onSuccess={onSuccess}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -61,7 +61,7 @@ const navGroups: NavGroup[] = [
|
||||
},
|
||||
{
|
||||
title: "Customer & Vehicles",
|
||||
href: "/customer_vehicles",
|
||||
href: "/customer-vehicles",
|
||||
icon: <UsersIcon />,
|
||||
},
|
||||
{
|
||||
@@ -79,7 +79,7 @@ const navGroups: NavGroup[] = [
|
||||
href: "/calendars",
|
||||
icon: <CalendarIcon />,
|
||||
items: [
|
||||
{ title: "Work Schedule", href: "/calendar/work_schedule/list", icon: <Clock3Icon /> },
|
||||
{ title: "Work Schedule", href: "/calendar/work-schedule/list", icon: <Clock3Icon /> },
|
||||
{ title: "Appointments", href: "/calendar/appointment/list", icon: <CalendarCheck2Icon /> },
|
||||
],
|
||||
},
|
||||
@@ -94,8 +94,8 @@ const navGroups: NavGroup[] = [
|
||||
{ title: "Estimates", href: "/sales/estimate", icon: <ReceiptTextIcon /> },
|
||||
{ title: "Job Cards", href: "/sales/workorder/list", icon: <ClipboardListIcon /> },
|
||||
{ title: "Invoices", href: "/sales/invoice", icon: <ReceiptIcon /> },
|
||||
{ title: "Payments Received", href: "/sales/payment_received", icon: <HandCoinsIcon /> },
|
||||
{ title: "Credit Notes", href: "/sales/credit_notes", icon: <ReceiptTextIcon /> },
|
||||
{ title: "Payments Received", href: "/sales/payment-received", icon: <HandCoinsIcon /> },
|
||||
{ title: "Credit Notes", href: "/sales/credit-notes", icon: <ReceiptTextIcon /> },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -105,10 +105,10 @@ const navGroups: NavGroup[] = [
|
||||
items: [
|
||||
{ title: "Vendors", href: "/purchase/vendor", icon: <StoreIcon /> },
|
||||
{ title: "Expenses", href: "/purchase/expense", icon: <WalletIcon /> },
|
||||
{ title: "Purchase Orders", href: "/purchase/purchase_order", icon: <ShoppingBasketIcon /> },
|
||||
{ title: "Purchase Orders", href: "/purchase/purchase-order", icon: <ShoppingBasketIcon /> },
|
||||
{ title: "Bills", href: "/purchase/bill", icon: <ReceiptIcon /> },
|
||||
{ title: "Payments Made", href: "/purchase/payments_made", icon: <BanknoteArrowDownIcon /> },
|
||||
{ title: "Vendor Credits", href: "/purchase/vendor_credit", icon: <ReceiptTextIcon /> },
|
||||
{ title: "Payments Made", href: "/purchase/payments-made", icon: <BanknoteArrowDownIcon /> },
|
||||
{ title: "Vendor Credits", href: "/purchase/vendor-credit", icon: <ReceiptTextIcon /> },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -117,7 +117,7 @@ const navGroups: NavGroup[] = [
|
||||
icon: <BriefcaseBusinessIcon />,
|
||||
items: [
|
||||
{ title: "Leads", href: "/crm/leads/list", icon: <GemIcon /> },
|
||||
{ title: "Calls", href: "/crm/calls_follow_up/list", icon: <PhoneCallIcon /> },
|
||||
{ title: "Calls", href: "/crm/calls-follow-up/list", icon: <PhoneCallIcon /> },
|
||||
{ title: "Tasks", href: "/crm/tasks/list", icon: <ListTodoIcon /> },
|
||||
],
|
||||
},
|
||||
@@ -126,9 +126,9 @@ const navGroups: NavGroup[] = [
|
||||
href: "/marketing",
|
||||
icon: <MegaphoneIcon />,
|
||||
items: [
|
||||
{ title: "Service Reminders", href: "/marketing/service_reminder/list", icon: <AlarmClockIcon /> },
|
||||
{ title: "Rating & Reviews", href: "/marketing/rating_review", icon: <StarIcon /> },
|
||||
{ title: "Google Business Reviews", href: "/marketing/google_rating_review", icon: <AwardIcon /> },
|
||||
{ title: "Service Reminders", href: "/marketing/service-reminder/list", icon: <AlarmClockIcon /> },
|
||||
{ title: "Rating & Reviews", href: "/marketing/rating-review", icon: <StarIcon /> },
|
||||
{ title: "Google Business Reviews", href: "/marketing/google-rating-review", icon: <AwardIcon /> },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -136,8 +136,8 @@ const navGroups: NavGroup[] = [
|
||||
href: "/accountants",
|
||||
icon: <BookIcon />,
|
||||
items: [
|
||||
{ title: "Manual Journals", href: "/accountants/manual_journal", icon: <BookIcon /> },
|
||||
{ title: "Chart of Accounts", href: "/accountants/chart_of_account", icon: <GitBranchIcon /> },
|
||||
{ title: "Manual Journals", href: "/accountants/manual-journal", icon: <BookIcon /> },
|
||||
{ title: "Chart of Accounts", href: "/accountants/chart-of-account", icon: <GitBranchIcon /> },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -146,12 +146,12 @@ const navGroups: NavGroup[] = [
|
||||
icon: <UserCogIcon />,
|
||||
items: [
|
||||
{ title: "Employees", href: "/productivity/employees", icon: <UsersIcon /> },
|
||||
{ title: "Time Clocks", href: "/productivity/time_clocks", icon: <TimerIcon /> },
|
||||
{ title: "Time Clocks", href: "/productivity/time-clocks", icon: <TimerIcon /> },
|
||||
{ title: "Time Sheets", href: "/productivity/timesheet", icon: <ClockIcon /> },
|
||||
{ title: "Payroll", href: "/productivity/payroll", icon: <WalletIcon /> },
|
||||
{ title: "Payments Made", href: "/productivity/employee_payments_made", icon: <HandCoinsIcon /> },
|
||||
{ title: "Shop Calendars", href: "/productivity/shop_calendars", icon: <CalendarDaysIcon /> },
|
||||
{ title: "Shop Timing", href: "/productivity/shop_timings", icon: <Clock3Icon /> },
|
||||
{ title: "Payments Made", href: "/productivity/employee-payments-made", icon: <HandCoinsIcon /> },
|
||||
{ title: "Shop Calendars", href: "/productivity/shop-calendars", icon: <CalendarDaysIcon /> },
|
||||
{ title: "Shop Timing", href: "/productivity/shop-timings", icon: <Clock3Icon /> },
|
||||
{ title: "Holidays", href: "/productivity/holidays", icon: <CalendarIcon /> },
|
||||
],
|
||||
},
|
||||
@@ -162,8 +162,8 @@ const navGroups: NavGroup[] = [
|
||||
items: [
|
||||
{ title: "Services", href: "/items/services", icon: <WrenchIcon /> },
|
||||
{ title: "Parts", href: "/items/parts", icon: <WrenchIcon /> },
|
||||
{ title: "Expense Item", href: "/items/expense_item", icon: <WalletIcon /> },
|
||||
{ title: "Service Group", href: "/items/service_group", icon: <PackageIcon /> },
|
||||
{ title: "Expense Item", href: "/items/expense-item", icon: <WalletIcon /> },
|
||||
{ title: "Service Group", href: "/items/service-group", icon: <PackageIcon /> },
|
||||
{ title: "Inspections", href: "/items/inspection", icon: <ClipboardCheckIcon /> },
|
||||
{ title: "Inventory Adjustments", href: "/items/adjustment", icon: <ListIcon /> },
|
||||
],
|
||||
@@ -174,12 +174,12 @@ const navGroups: NavGroup[] = [
|
||||
icon: <SettingsIcon />,
|
||||
items: [
|
||||
{ title: "Company", href: "/setting/company", icon: <Building2Icon /> },
|
||||
{ title: "Shop Types", href: "/setting/shop_type", icon: <CarIcon /> },
|
||||
{ title: "Tax & Rates", href: "/setting/tax_rates", icon: <ReceiptTextIcon /> },
|
||||
{ title: "Shop Types", href: "/setting/shop-type", icon: <CarIcon /> },
|
||||
{ title: "Tax & Rates", href: "/setting/tax-rates", icon: <ReceiptTextIcon /> },
|
||||
{ title: "Configurations", href: "/setting/configurations/preferences/sales", icon: <SettingsIcon /> },
|
||||
{ title: "Templates", href: "/setting/templates", icon: <ClipboardListIcon /> },
|
||||
{ title: "Integrations", href: "/setting/integrations/providers", icon: <PlugZapIcon /> },
|
||||
{ title: "Master", href: "/setting/master/body_type", icon: <ListIcon /> },
|
||||
{ title: "Master", href: "/setting/master/body-type", icon: <ListIcon /> },
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
@@ -20,11 +20,18 @@ export default function VehiclesPage() {
|
||||
header: ({ column }) => <ColumnHeader column={column} title="Vehicle" />,
|
||||
cell: ({ row }) => {
|
||||
const r = row.original as any
|
||||
const display = r.name || `${r.make ?? ""} ${r.model ?? ""}`.trim() || "—"
|
||||
const make = r.make ?? ""
|
||||
const model = r.model ?? ""
|
||||
const display = r.name || `${make} ${model}`.trim() || "—"
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<CarIcon className="h-4 w-4 text-muted-foreground" />
|
||||
<span>{display}</span>
|
||||
<div>
|
||||
<span className="font-medium">{display}</span>
|
||||
{r.sub_model && (
|
||||
<span className="ml-1 text-xs text-muted-foreground">{r.sub_model}</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
@@ -37,12 +44,43 @@ export default function VehiclesPage() {
|
||||
{
|
||||
accessorKey: "license_plate",
|
||||
header: ({ column }) => <ColumnHeader column={column} title="License Plate" />,
|
||||
cell: ({ row }) => (row.original as any).license_plate ?? "—",
|
||||
cell: ({ row }) => {
|
||||
const val = (row.original as any).license_plate
|
||||
return val
|
||||
? <span className="font-mono text-xs">{val}</span>
|
||||
: "—"
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "vin_number",
|
||||
header: ({ column }) => <ColumnHeader column={column} title="VIN" />,
|
||||
cell: ({ row }) => {
|
||||
const val = (row.original as any).vin_number
|
||||
return val
|
||||
? <span className="max-w-30 truncate block font-mono text-xs">{val}</span>
|
||||
: "—"
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "engine_size",
|
||||
header: ({ column }) => <ColumnHeader column={column} title="Engine" />,
|
||||
cell: ({ row }) => (row.original as any).engine_size ?? "—",
|
||||
},
|
||||
{
|
||||
accessorKey: "mileage",
|
||||
header: ({ column }) => <ColumnHeader column={column} title="Mileage" />,
|
||||
cell: ({ row }) => (row.original as any).mileage ?? "—",
|
||||
cell: ({ row }) => {
|
||||
const val = (row.original as any).mileage
|
||||
return val != null ? `${Number(val).toLocaleString()} mi` : "—"
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "created_at",
|
||||
header: ({ column }) => <ColumnHeader column={column} title="Created" />,
|
||||
cell: ({ row }) => {
|
||||
const val = (row.original as any).created_at
|
||||
return val ? new Date(val).toLocaleDateString() : "—"
|
||||
},
|
||||
},
|
||||
actionsColumn(),
|
||||
]}
|
||||
|
||||
Reference in New Issue
Block a user