Skip to content

Commit

Permalink
Customers v0.5
Browse files Browse the repository at this point in the history
  • Loading branch information
pontusab committed Dec 5, 2024
1 parent 5856ce1 commit 5141ec4
Show file tree
Hide file tree
Showing 16 changed files with 208 additions and 61 deletions.
1 change: 1 addition & 0 deletions apps/dashboard/src/actions/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,7 @@ export const createCustomerSchema = z.object({
note: z.string().nullable().optional(),
website: z.string().nullable().optional(),
phone: z.string().nullable().optional(),
contact: z.string().nullable().optional(),
});

export const inboxUploadSchema = z.array(
Expand Down
9 changes: 4 additions & 5 deletions apps/dashboard/src/components/customers-header.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { InvoiceSearchFilter } from "@/components/invoice-search-filter";
import { getCustomers } from "@midday/supabase/cached-queries";
import { OpenInvoiceSheet } from "./open-invoice-sheet";
import { OpenCustomerSheet } from "./open-customer-sheet";
import { SearchField } from "./search-field";

export async function CustomersHeader() {
return (
<div className="flex items-center justify-between">
<InvoiceSearchFilter />
<SearchField placeholder="Search customers" />

<div className="hidden sm:block">
<OpenInvoiceSheet />
<OpenCustomerSheet />
</div>
</div>
);
Expand Down
21 changes: 21 additions & 0 deletions apps/dashboard/src/components/forms/customer-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ const formSchema = z.object({
.nullable()
.optional()
.transform((url) => url?.replace(/^https?:\/\//, "")),
contact: z.string().nullable().optional(),
address_line_1: z.string().nullable().optional(),
address_line_2: z.string().nullable().optional(),
city: z.string().nullable().optional(),
Expand Down Expand Up @@ -110,6 +111,7 @@ export function CustomerForm({ data }: Props) {
vat_number: undefined,
note: undefined,
phone: undefined,
contact: undefined,
},
});

Expand Down Expand Up @@ -237,6 +239,25 @@ export function CustomerForm({ data }: Props) {
</FormItem>
)}
/>

<FormField
control={form.control}
name="contact"
render={({ field }) => (
<FormItem>
<FormLabel className="text-xs text-[#878787] font-normal">
Contact person
</FormLabel>
<FormControl>
<Input
{...field}
placeholder="John Doe"
autoComplete="off"
/>
</FormControl>
</FormItem>
)}
/>
</div>
</AccordionContent>
</AccordionItem>
Expand Down
2 changes: 2 additions & 0 deletions apps/dashboard/src/components/invoice/customer-details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export interface Customer {
zip?: string;
country?: string;
vat?: string;
contact?: string;
website?: string;
}

interface CustomerDetailsProps {
Expand Down
22 changes: 22 additions & 0 deletions apps/dashboard/src/components/open-customer-sheet.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"use client";

import { useCustomerParams } from "@/hooks/use-customer-params";
import { useInvoiceParams } from "@/hooks/use-invoice-params";
import { Button } from "@midday/ui/button";
import { Icons } from "@midday/ui/icons";

export function OpenCustomerSheet() {
const { setParams } = useCustomerParams();

return (
<div>
<Button
variant="outline"
size="icon"
onClick={() => setParams({ createCustomer: true })}
>
<Icons.Add />
</Button>
</div>
);
}
6 changes: 5 additions & 1 deletion apps/dashboard/src/components/sheets/customer-edit-sheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,11 @@ export function CustomerEditSheet() {
}
}

fetchCustomer();
if (customerId) {
fetchCustomer();
} else {
setCustomer(null);
}
}, [customerId, supabase]);

return (
Expand Down
45 changes: 33 additions & 12 deletions apps/dashboard/src/components/tables/customers/columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,18 @@ import {
} from "@midday/ui/dropdown-menu";
import { DotsHorizontalIcon } from "@radix-ui/react-icons";
import type { ColumnDef } from "@tanstack/react-table";
import Link from "next/link";
import * as React from "react";

export type Customer = {
id: string;
name: string;
customer_name?: string;
website: string;
contact_person?: string;
contact?: string;
email: string;
invoices: number;
projects: number;
invoices: { id: string }[];
projects: { id: string }[];
tags: { id: string; name: string }[];
};

Expand Down Expand Up @@ -57,8 +58,8 @@ export const columns: ColumnDef<Customer>[] = [
},
{
header: "Contact person",
accessorKey: "contact_person",
cell: ({ row }) => row.getValue("contact_person") ?? "-",
accessorKey: "contact",
cell: ({ row }) => row.getValue("contact") ?? "-",
},
{
header: "Email",
Expand All @@ -68,18 +69,38 @@ export const columns: ColumnDef<Customer>[] = [
{
header: "Invoices",
accessorKey: "invoices",
cell: ({ row }) => row.getValue("invoices") ?? "-",
cell: ({ row }) => {
if (row.original.invoices.length > 0) {
return (
<Link href={`/invoices?customers=${row.original.id}`}>
{row.original.invoices.length}
</Link>
);
}

return "-";
},
},
{
header: "Projects",
accessorKey: "projects",
cell: ({ row }) => row.getValue("projects") ?? "-",
},
{
header: "Tags",
accessorKey: "tags",
cell: ({ row }) => row.getValue("tags") ?? "-",
cell: ({ row }) => {
if (row.original.projects.length > 0) {
return (
<Link href={`/tracker?customers=${row.original.id}`}>
{row.original.projects.length}
</Link>
);
}

return "-";
},
},
// {
// header: "Tags",
// accessorKey: "tags",
// cell: ({ row }) => row.getValue("tags") ?? "-",
// },
{
id: "actions",
header: "Actions",
Expand Down
12 changes: 5 additions & 7 deletions apps/dashboard/src/components/tables/customers/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,16 @@ export async function CustomersTable({ query, sort, start, end, page }: Props) {
"use server";

return getCustomers({
// to,
// from: from + 1,
// searchQuery: query,
// sort,
// filter,
to,
from: from + 1,
searchQuery: query,
sort,
});
}

const { data, meta } = await getCustomers({
searchQuery: query,
sort,
filter,
to: pageSize,
});

Expand All @@ -55,7 +53,7 @@ export async function CustomersTable({ query, sort, start, end, page }: Props) {
return (
<DataTable
data={data}
// loadMore={loadMore}
loadMore={loadMore}
pageSize={pageSize}
hasNextPage={hasNextPage}
page={page}
Expand Down
4 changes: 1 addition & 3 deletions apps/dashboard/src/components/tables/customers/row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@ export function CustomerRow({ row, setOpen }: Props) {
{row.getVisibleCells().map((cell, index) => (
<TableCell
key={cell.id}
onClick={() =>
index !== row.getVisibleCells().length - 1 && setOpen(row.id)
}
onClick={() => ![3, 4, 5].includes(index) && setOpen(row.id)}
>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell>
Expand Down
34 changes: 33 additions & 1 deletion apps/dashboard/src/components/tables/customers/skeleton.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,35 @@
import { Skeleton } from "@midday/ui/skeleton";
import { Table, TableBody, TableCell, TableRow } from "@midday/ui/table";
import { TableHeader } from "./table-header";

export function CustomersSkeleton() {
return <div>CustomersSkeleton</div>;
return (
<Table>
<TableHeader />
<TableBody>
{Array.from({ length: 25 }).map((_, index) => (
<TableRow key={index.toString()} className="h-[45px]">
<TableCell>
<Skeleton className="h-4 w-24" />
</TableCell>
<TableCell>
<Skeleton className="h-4 w-32" />
</TableCell>
<TableCell>
<Skeleton className="h-4 w-20" />
</TableCell>
<TableCell>
<Skeleton className="h-4 w-24" />
</TableCell>
<TableCell>
<Skeleton className="h-4 w-16" />
</TableCell>
<TableCell>
<Skeleton className="h-4 w-8" />
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
);
}
18 changes: 7 additions & 11 deletions apps/dashboard/src/components/tables/customers/table-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,11 @@ export function TableHeader() {
<Button
className="p-0 hover:bg-transparent space-x-2"
variant="ghost"
onClick={() => createSortQuery("status")}
onClick={() => createSortQuery("contact")}
>
<span>Contact person</span>
{"contact_person" === column && value === "asc" && (
<ArrowDown size={16} />
)}
{"contact_person" === column && value === "desc" && (
<ArrowUp size={16} />
)}
{"contact" === column && value === "asc" && <ArrowDown size={16} />}
{"contact" === column && value === "desc" && <ArrowUp size={16} />}
</Button>
</TableHead>
<TableHead>
Expand All @@ -73,7 +69,7 @@ export function TableHeader() {
<Button
className="p-0 hover:bg-transparent space-x-2"
variant="ghost"
onClick={() => createSortQuery("customer")}
// onClick={() => createSortQuery("customer")}
>
<span>Invoices</span>
{"invoices" === column && value === "asc" && (
Expand All @@ -86,7 +82,7 @@ export function TableHeader() {
<Button
className="p-0 hover:bg-transparent space-x-2"
variant="ghost"
onClick={() => createSortQuery("projects")}
// onClick={() => createSortQuery("projects")}
>
<span>Projects</span>
{"projects" === column && value === "asc" && (
Expand All @@ -96,7 +92,7 @@ export function TableHeader() {
</Button>
</TableHead>

<TableHead className="hidden md:table-cell">
{/* <TableHead className="hidden md:table-cell">
<Button
className="p-0 hover:bg-transparent space-x-2"
variant="ghost"
Expand All @@ -106,7 +102,7 @@ export function TableHeader() {
{"tags" === column && value === "asc" && <ArrowDown size={16} />}
{"tags" === column && value === "desc" && <ArrowUp size={16} />}
</Button>
</TableHead>
</TableHead> */}

<TableHead className="hidden md:table-cell">Actions</TableHead>
</TableRow>
Expand Down
24 changes: 17 additions & 7 deletions apps/dashboard/src/hooks/use-customer-params.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
import { parseAsBoolean, parseAsString, useQueryStates } from "nuqs";
import {
parseAsArrayOf,
parseAsBoolean,
parseAsString,
useQueryStates,
} from "nuqs";

export function useCustomerParams() {
const [params, setParams] = useQueryStates({
customerId: parseAsString,
createCustomer: parseAsBoolean,
name: parseAsString,
});
export function useCustomerParams(options?: { shallow: boolean }) {
const [params, setParams] = useQueryStates(
{
customerId: parseAsString,
createCustomer: parseAsBoolean,
sort: parseAsArrayOf(parseAsString),
name: parseAsString,
q: parseAsString,
},
options,
);

return {
...params,
Expand Down
Binary file modified bun.lockb
Binary file not shown.
9 changes: 6 additions & 3 deletions packages/supabase/src/queries/cached-queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { createClient } from "../client/server";
import {
type GetBurnRateQueryParams,
type GetCategoriesParams,
type GetCustomersQueryParams,
type GetExpensesQueryParams,
type GetInvoiceSummaryParams,
type GetInvoicesQueryParams,
Expand Down Expand Up @@ -500,7 +501,9 @@ export const getPaymentStatus = async () => {
)();
};

export const getCustomers = async () => {
export const getCustomers = async (
params?: Omit<GetCustomersQueryParams, "teamId">,
) => {
const supabase = createClient();
const user = await getUser();
const teamId = user?.data?.team_id;
Expand All @@ -511,14 +514,14 @@ export const getCustomers = async () => {

return unstable_cache(
async () => {
return getCustomersQuery(supabase, teamId);
return getCustomersQuery(supabase, { ...params, teamId });
},
["customers", teamId],
{
tags: [`customers_${teamId}`],
revalidate: 3600,
},
)();
)(params);
};

export const getInvoices = async (
Expand Down
Loading

0 comments on commit 5141ec4

Please sign in to comment.