@voyantjs/suppliers-ui 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -0
- package/dist/components/supplier-service-row.d.ts +13 -0
- package/dist/components/supplier-service-row.d.ts.map +1 -0
- package/dist/components/supplier-service-row.js +11 -0
- package/dist/components/suppliers-page.d.ts +11 -0
- package/dist/components/suppliers-page.d.ts.map +1 -0
- package/dist/components/suppliers-page.js +40 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/package.json +64 -0
package/README.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# @voyantjs/suppliers-ui
|
|
2
|
+
|
|
3
|
+
Importable React UI components for Voyant suppliers. Bundler-consumed (Vite, Next.js, webpack, etc.).
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @voyantjs/suppliers-ui @voyantjs/suppliers-react @voyantjs/voyant-ui @tanstack/react-query react react-dom
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`@voyantjs/voyant-ui` provides the design-system primitives. `@voyantjs/suppliers-react` provides the data-layer hooks. Both are required peers.
|
|
12
|
+
|
|
13
|
+
All components accept a `className` prop and merge it with `cn()`. Wrap or compose to extend; use the registry copy-paste path (`npx shadcn add @voyant/...`) for components you want to fork outright.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type SupplierRate, type SupplierService } from "@voyantjs/suppliers-react";
|
|
2
|
+
export declare function SupplierServiceRow({ service, rates, expanded, onToggle, onEdit, onDelete, onAddRate, onEditRate, onDeleteRate, }: {
|
|
3
|
+
service: SupplierService;
|
|
4
|
+
rates: SupplierRate[];
|
|
5
|
+
expanded: boolean;
|
|
6
|
+
onToggle: () => void;
|
|
7
|
+
onEdit: () => void;
|
|
8
|
+
onDelete: () => void;
|
|
9
|
+
onAddRate: () => void;
|
|
10
|
+
onEditRate: (rate: SupplierRate) => void;
|
|
11
|
+
onDeleteRate: (rateId: string) => void;
|
|
12
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
//# sourceMappingURL=supplier-service-row.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supplier-service-row.d.ts","sourceRoot":"","sources":["../../src/components/supplier-service-row.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,eAAe,EACrB,MAAM,2BAA2B,CAAA;AAIlC,wBAAgB,kBAAkB,CAAC,EACjC,OAAO,EACP,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,SAAS,EACT,UAAU,EACV,YAAY,GACb,EAAE;IACD,OAAO,EAAE,eAAe,CAAA;IACxB,KAAK,EAAE,YAAY,EAAE,CAAA;IACrB,QAAQ,EAAE,OAAO,CAAA;IACjB,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,SAAS,EAAE,MAAM,IAAI,CAAA;IACrB,UAAU,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAA;IACxC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;CACvC,2CAiHA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { formatAmount, formatUnit, } from "@voyantjs/suppliers-react";
|
|
3
|
+
import { Badge, Button } from "@voyantjs/voyant-ui/components";
|
|
4
|
+
import { ChevronDown, ChevronRight, Pencil, Plus, Trash2 } from "lucide-react";
|
|
5
|
+
export function SupplierServiceRow({ service, rates, expanded, onToggle, onEdit, onDelete, onAddRate, onEditRate, onDeleteRate, }) {
|
|
6
|
+
return (_jsxs("div", { className: "rounded-md border", children: [_jsxs("div", { className: "flex items-center gap-3 p-3", children: [_jsx("button", { type: "button", onClick: onToggle, className: "text-muted-foreground hover:text-foreground", children: expanded ? _jsx(ChevronDown, { className: "h-4 w-4" }) : _jsx(ChevronRight, { className: "h-4 w-4" }) }), _jsxs("div", { className: "flex-1", children: [_jsx("span", { className: "text-sm font-medium", children: service.name }), _jsxs("div", { className: "mt-0.5 flex items-center gap-2", children: [_jsx(Badge, { variant: "outline", className: "text-xs capitalize", children: service.serviceType }), service.duration ? (_jsx("span", { className: "text-xs text-muted-foreground", children: service.duration })) : null, service.capacity ? (_jsxs("span", { className: "text-xs text-muted-foreground", children: ["max ", service.capacity, " pax"] })) : null, !service.active ? (_jsx(Badge, { variant: "secondary", className: "text-xs", children: "Inactive" })) : null] })] }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx(Button, { variant: "ghost", size: "sm", onClick: onEdit, children: _jsx(Pencil, { className: "h-3.5 w-3.5" }) }), _jsx(Button, { variant: "ghost", size: "sm", onClick: onDelete, children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) })] })] }), expanded ? (_jsxs("div", { className: "border-t bg-muted/30 p-3", children: [_jsxs("div", { className: "mb-2 flex items-center justify-between", children: [_jsx("p", { className: "text-xs font-medium uppercase tracking-wide text-muted-foreground", children: "Rates" }), _jsxs(Button, { variant: "outline", size: "sm", onClick: onAddRate, children: [_jsx(Plus, { className: "mr-1 h-3 w-3" }), "Add Rate"] })] }), rates.length === 0 ? (_jsx("p", { className: "py-2 text-center text-xs text-muted-foreground", children: "No rates yet." })) : (_jsx("div", { className: "rounded border bg-background", children: _jsxs("table", { className: "w-full text-xs", children: [_jsx("thead", { children: _jsxs("tr", { className: "border-b text-muted-foreground", children: [_jsx("th", { className: "p-2 text-left font-medium", children: "Name" }), _jsx("th", { className: "p-2 text-left font-medium", children: "Amount" }), _jsx("th", { className: "p-2 text-left font-medium", children: "Unit" }), _jsx("th", { className: "p-2 text-left font-medium", children: "Valid" }), _jsx("th", { className: "p-2 text-left font-medium", children: "Pax" }), _jsx("th", { className: "w-16 p-2" })] }) }), _jsx("tbody", { children: rates.map((rate) => (_jsxs("tr", { className: "border-b last:border-b-0", children: [_jsx("td", { className: "p-2", children: rate.name }), _jsx("td", { className: "p-2 font-mono", children: formatAmount(rate.amountCents, rate.currency) }), _jsx("td", { className: "p-2 capitalize", children: formatUnit(rate.unit) }), _jsx("td", { className: "p-2", children: rate.validFrom || rate.validTo
|
|
7
|
+
? `${rate.validFrom ?? "..."} — ${rate.validTo ?? "..."}`
|
|
8
|
+
: "-" }), _jsx("td", { className: "p-2", children: rate.minPax || rate.maxPax
|
|
9
|
+
? `${rate.minPax ?? "?"}-${rate.maxPax ?? "?"}`
|
|
10
|
+
: "-" }), _jsx("td", { className: "p-2", children: _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("button", { type: "button", onClick: () => onEditRate(rate), className: "text-muted-foreground hover:text-foreground", children: _jsx(Pencil, { className: "h-3 w-3" }) }), _jsx("button", { type: "button", onClick: () => onDeleteRate(rate.id), className: "text-muted-foreground hover:text-destructive", children: _jsx(Trash2, { className: "h-3 w-3" }) })] }) })] }, rate.id))) })] }) }))] })) : null] }));
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Supplier } from "@voyantjs/suppliers-react";
|
|
2
|
+
export declare function SuppliersPage({ search, onSearchChange, onCreate, onRowClick, rows, total, isPending, }: {
|
|
3
|
+
search: string;
|
|
4
|
+
onSearchChange: (value: string) => void;
|
|
5
|
+
onCreate: () => void;
|
|
6
|
+
onRowClick: (supplier: Supplier) => void;
|
|
7
|
+
rows: Supplier[];
|
|
8
|
+
total: number;
|
|
9
|
+
isPending?: boolean;
|
|
10
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
//# sourceMappingURL=suppliers-page.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suppliers-page.d.ts","sourceRoot":"","sources":["../../src/components/suppliers-page.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAA;AA+CzD,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,cAAc,EACd,QAAQ,EACR,UAAU,EACV,IAAI,EACJ,KAAK,EACL,SAAS,GACV,EAAE;IACD,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,UAAU,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAA;IACxC,IAAI,EAAE,QAAQ,EAAE,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,2CAuCA"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { statusVariant } from "@voyantjs/suppliers-react";
|
|
3
|
+
import { Badge, Button, Input } from "@voyantjs/voyant-ui/components";
|
|
4
|
+
import { DataTable } from "@voyantjs/voyant-ui/components/data-table";
|
|
5
|
+
import { DataTableColumnHeader } from "@voyantjs/voyant-ui/components/data-table-column-header";
|
|
6
|
+
import { Loader2, Plus, Search } from "lucide-react";
|
|
7
|
+
const columns = [
|
|
8
|
+
{
|
|
9
|
+
accessorKey: "name",
|
|
10
|
+
header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Name" }),
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
accessorKey: "type",
|
|
14
|
+
header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Type" }),
|
|
15
|
+
cell: ({ row }) => (_jsx(Badge, { variant: "outline", className: "capitalize", children: row.original.type })),
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
accessorKey: "status",
|
|
19
|
+
header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Status" }),
|
|
20
|
+
cell: ({ row }) => (_jsx(Badge, { variant: statusVariant[row.original.status] ?? "secondary", className: "capitalize", children: row.original.status })),
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
accessorKey: "city",
|
|
24
|
+
header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "City" }),
|
|
25
|
+
cell: ({ row }) => row.original.city ?? "-",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
accessorKey: "country",
|
|
29
|
+
header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Country" }),
|
|
30
|
+
cell: ({ row }) => row.original.country ?? "-",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
accessorKey: "defaultCurrency",
|
|
34
|
+
header: ({ column }) => _jsx(DataTableColumnHeader, { column: column, title: "Currency" }),
|
|
35
|
+
cell: ({ row }) => row.original.defaultCurrency ?? "-",
|
|
36
|
+
},
|
|
37
|
+
];
|
|
38
|
+
export function SuppliersPage({ search, onSearchChange, onCreate, onRowClick, rows, total, isPending, }) {
|
|
39
|
+
return (_jsxs("div", { className: "flex flex-col gap-6 p-6", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-2xl font-bold tracking-tight", children: "Suppliers" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Manage your hotels, transfers, guides, and service providers." })] }), _jsxs(Button, { onClick: onCreate, children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), "New Supplier"] })] }), _jsxs("div", { className: "relative max-w-sm", children: [_jsx(Search, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { placeholder: "Search suppliers...", value: search, onChange: (event) => onSearchChange(event.target.value), className: "pl-9" })] }), isPending ? (_jsx("div", { className: "flex items-center justify-center py-12", children: _jsx(Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }) })) : (_jsx(DataTable, { columns: columns, data: rows, onRowClick: (row) => onRowClick(row.original) })), _jsxs("p", { className: "text-sm text-muted-foreground", children: ["Showing ", rows.length, " of ", total, " suppliers"] })] }));
|
|
40
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA"}
|
package/dist/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@voyantjs/suppliers-ui",
|
|
3
|
+
"version": "0.13.0",
|
|
4
|
+
"license": "FSL-1.1-Apache-2.0",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/voyantjs/voyant.git",
|
|
8
|
+
"directory": "packages/suppliers-ui"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"sideEffects": false,
|
|
12
|
+
"exports": {
|
|
13
|
+
".": "./src/index.ts",
|
|
14
|
+
"./components/*": "./src/components/*.tsx"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc -p tsconfig.build.json",
|
|
18
|
+
"clean": "rm -rf dist",
|
|
19
|
+
"prepack": "pnpm run build",
|
|
20
|
+
"typecheck": "tsc --noEmit",
|
|
21
|
+
"lint": "biome check src/",
|
|
22
|
+
"test": "vitest run --passWithNoTests"
|
|
23
|
+
},
|
|
24
|
+
"peerDependencies": {
|
|
25
|
+
"@tanstack/react-query": "^5.0.0",
|
|
26
|
+
"@tanstack/react-table": "^8.0.0",
|
|
27
|
+
"@voyantjs/suppliers-react": "workspace:*",
|
|
28
|
+
"@voyantjs/voyant-ui": "workspace:*",
|
|
29
|
+
"react": "^19.0.0",
|
|
30
|
+
"react-dom": "^19.0.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@tanstack/react-query": "^5.96.2",
|
|
34
|
+
"@tanstack/react-table": "^8.21.3",
|
|
35
|
+
"@types/react": "^19.2.14",
|
|
36
|
+
"@types/react-dom": "^19.2.3",
|
|
37
|
+
"@voyantjs/suppliers-react": "workspace:*",
|
|
38
|
+
"@voyantjs/voyant-typescript-config": "workspace:*",
|
|
39
|
+
"@voyantjs/voyant-ui": "workspace:*",
|
|
40
|
+
"lucide-react": "^0.475.0",
|
|
41
|
+
"react": "^19.2.4",
|
|
42
|
+
"react-dom": "^19.2.4",
|
|
43
|
+
"typescript": "^6.0.2",
|
|
44
|
+
"vitest": "^4.1.2"
|
|
45
|
+
},
|
|
46
|
+
"files": [
|
|
47
|
+
"dist"
|
|
48
|
+
],
|
|
49
|
+
"publishConfig": {
|
|
50
|
+
"access": "public",
|
|
51
|
+
"exports": {
|
|
52
|
+
".": {
|
|
53
|
+
"types": "./dist/index.d.ts",
|
|
54
|
+
"import": "./dist/index.js"
|
|
55
|
+
},
|
|
56
|
+
"./components/*": {
|
|
57
|
+
"types": "./dist/components/*.d.ts",
|
|
58
|
+
"import": "./dist/components/*.js"
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"main": "./dist/index.js",
|
|
62
|
+
"types": "./dist/index.d.ts"
|
|
63
|
+
}
|
|
64
|
+
}
|