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
4 changes: 3 additions & 1 deletion internal/database/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ type Client struct {
Email string `db:"email" json:"email"`
GivenName string `db:"given_name" json:"given_name"`
FamilyName string `db:"family_name" json:"family_name"`
Company *string `db:"company" json:"company"`
Status string `db:"status" json:"status"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
}

Expand All @@ -40,7 +42,7 @@ func (s *Store) ListClients(ctx context.Context, p ListClientsParams) ([]Client,
}

rows, _ := s.pool.Query(ctx, `
SELECT u.id, u.email, u.given_name, u.family_name, u.created_at, count(*) OVER () AS total
SELECT u.id, u.email, u.given_name, u.family_name, u.company, u.status, u.created_at, count(*) OVER () AS total
FROM users u
WHERE strpos(lower(u.given_name || ' ' || u.family_name || ' ' || u.email), lower($1)) > 0
ORDER BY `+order+`, u.id
Expand Down
5 changes: 5 additions & 0 deletions migrations/00004_users_company.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-- +goose Up
ALTER TABLE users ADD COLUMN company text;

-- +goose Down
ALTER TABLE users DROP COLUMN company;
9 changes: 9 additions & 0 deletions migrations/00005_users_status.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-- +goose Up
CREATE TYPE user_status AS ENUM ('active', 'suspended', 'closed');

ALTER TABLE users ADD COLUMN status user_status NOT NULL DEFAULT 'active';

-- +goose Down
ALTER TABLE users DROP COLUMN status;

DROP TYPE user_status;
3 changes: 3 additions & 0 deletions web/src/api/clients/clients.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ export type Client = {
email: string;
given_name: string;
family_name: string;
company: string | null;
status: ClientStatus;
created_at: string;
};

export type ClientStatus = "active" | "suspended" | "closed";
export type ClientSort = "name" | "created_at";
export type SortOrder = "asc" | "desc";

Expand Down
20 changes: 19 additions & 1 deletion web/src/routes/admin/clients.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
} from "@tanstack/react-table";

import { Permission } from "@/api/auth/permissions";
import { CLIENTS_PER_PAGE, clientsQuery, type Client, type ClientSort, type SortOrder } from "@/api/clients/clients";
import { CLIENTS_PER_PAGE, clientsQuery, type Client, type ClientSort, type ClientStatus, type SortOrder } from "@/api/clients/clients";
import { Add01Icon, ArrowLeft01Icon, ArrowRight01Icon, HugeiconsIcon } from "@/components/icons";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
Expand Down Expand Up @@ -43,6 +43,12 @@ export const Route = createFileRoute("/admin/clients")({

const date = new Intl.DateTimeFormat("en-GB", { day: "numeric", month: "short", year: "numeric" });

const STATUS_CLASS: Record<ClientStatus, string> = {
active: "bg-emerald-300/10 text-emerald-200",
suspended: "bg-amber-300/10 text-amber-200",
closed: "bg-rose-300/10 text-rose-200",
};

const NO_CLIENTS: Client[] = [];

const features = tableFeatures({ rowPaginationFeature, rowSortingFeature });
Expand All @@ -58,6 +64,18 @@ const columns = helper.columns([
</>
),
}),
helper.accessor("company", {
header: "Company",
enableSorting: false,
cell: ({ getValue }) => getValue() ?? <span className="text-muted-foreground">—</span>,
}),
helper.accessor("status", {
header: "Status",
enableSorting: false,
cell: ({ getValue }) => (
<span className={cn("inline-flex px-1.5 py-0.5 text-[11px] capitalize", STATUS_CLASS[getValue()])}>{getValue()}</span>
),
}),
helper.accessor("created_at", {
header: "Created",
sortDescFirst: true,
Expand Down
Loading