@cellarnode/ui 0.8.6 → 0.8.8
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/dist/components/attachment-row.d.ts +23 -0
- package/dist/components/attachment-row.d.ts.map +1 -0
- package/dist/components/attachment-row.js +61 -0
- package/dist/components/attachment-row.js.map +1 -0
- package/dist/components/attachment-row.stories.d.ts +9 -0
- package/dist/components/attachment-row.stories.d.ts.map +1 -0
- package/dist/components/attachment-row.stories.js +65 -0
- package/dist/components/attachment-row.stories.js.map +1 -0
- package/dist/components/certification-upload-card.d.ts +19 -0
- package/dist/components/certification-upload-card.d.ts.map +1 -0
- package/dist/components/certification-upload-card.js +74 -0
- package/dist/components/certification-upload-card.js.map +1 -0
- package/dist/components/certification-upload-card.stories.d.ts +9 -0
- package/dist/components/certification-upload-card.stories.d.ts.map +1 -0
- package/dist/components/certification-upload-card.stories.js +44 -0
- package/dist/components/certification-upload-card.stories.js.map +1 -0
- package/dist/components/confirmation-dialog.d.ts.map +1 -1
- package/dist/components/confirmation-dialog.js +1 -0
- package/dist/components/confirmation-dialog.js.map +1 -1
- package/dist/components/contact-person-select.d.ts +16 -0
- package/dist/components/contact-person-select.d.ts.map +1 -0
- package/dist/components/contact-person-select.js +19 -0
- package/dist/components/contact-person-select.js.map +1 -0
- package/dist/components/contact-person-select.stories.d.ts +16 -0
- package/dist/components/contact-person-select.stories.d.ts.map +1 -0
- package/dist/components/contact-person-select.stories.js +56 -0
- package/dist/components/contact-person-select.stories.js.map +1 -0
- package/dist/components/price-comparison.d.ts +13 -0
- package/dist/components/price-comparison.d.ts.map +1 -0
- package/dist/components/price-comparison.js +60 -0
- package/dist/components/price-comparison.js.map +1 -0
- package/dist/components/price-comparison.stories.d.ts +11 -0
- package/dist/components/price-comparison.stories.d.ts.map +1 -0
- package/dist/components/price-comparison.stories.js +56 -0
- package/dist/components/price-comparison.stories.js.map +1 -0
- package/dist/components/stat-card.js +1 -1
- package/dist/components/stat-card.js.map +1 -1
- package/dist/components/variant-picker-dialog.d.ts.map +1 -1
- package/dist/components/variant-picker-dialog.js +1 -0
- package/dist/components/variant-picker-dialog.js.map +1 -1
- package/dist/globe/globe-canvas.d.ts.map +1 -1
- package/dist/globe/globe-canvas.js +1 -0
- package/dist/globe/globe-canvas.js.map +1 -1
- package/dist/globe/globe-tooltip.d.ts.map +1 -1
- package/dist/globe/globe-tooltip.js +58 -18
- package/dist/globe/globe-tooltip.js.map +1 -1
- package/dist/globe/globe-types.d.ts +4 -0
- package/dist/globe/globe-types.d.ts.map +1 -1
- package/dist/globe/globe-view.d.ts.map +1 -1
- package/dist/globe/globe-view.js +29 -13
- package/dist/globe/globe-view.js.map +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/org/invite-member-dialog.d.ts.map +1 -1
- package/dist/org/invite-member-dialog.js +2 -0
- package/dist/org/invite-member-dialog.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface AttachmentRowFile {
|
|
2
|
+
id: string;
|
|
3
|
+
fileName: string;
|
|
4
|
+
name?: string | null;
|
|
5
|
+
mimeType: string;
|
|
6
|
+
fileSize: number;
|
|
7
|
+
type?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface AttachmentRowProps {
|
|
10
|
+
file: AttachmentRowFile;
|
|
11
|
+
typeOptions: Array<{
|
|
12
|
+
value: string;
|
|
13
|
+
label: string;
|
|
14
|
+
}>;
|
|
15
|
+
autoAttached?: boolean;
|
|
16
|
+
onRename?: (id: string, newName: string) => void;
|
|
17
|
+
onTypeChange?: (id: string, newType: string) => void;
|
|
18
|
+
onRemove?: (id: string) => void;
|
|
19
|
+
onDownload?: (id: string) => void;
|
|
20
|
+
className?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function AttachmentRow({ file, typeOptions, autoAttached, onRename, onTypeChange, onRemove, onDownload, className, }: AttachmentRowProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
//# sourceMappingURL=attachment-row.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attachment-row.d.ts","sourceRoot":"","sources":["../../src/components/attachment-row.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,iBAAiB,CAAC;IACxB,WAAW,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,YAAY,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,UAAU,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAkBD,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,YAAY,EACZ,QAAQ,EACR,UAAU,EACV,SAAS,GACV,EAAE,kBAAkB,2CA2HpB"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { cn } from "../lib/utils";
|
|
4
|
+
function formatFileSize(bytes) {
|
|
5
|
+
if (bytes < 1024)
|
|
6
|
+
return `${bytes} B`;
|
|
7
|
+
if (bytes < 1024 * 1024)
|
|
8
|
+
return `${Math.round(bytes / 1024)} KB`;
|
|
9
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
10
|
+
}
|
|
11
|
+
function getFileIcon(mimeType) {
|
|
12
|
+
if (mimeType === "application/pdf") {
|
|
13
|
+
return { label: "PDF", bgClass: "bg-red-500/15 text-red-600 dark:bg-red-500/20 dark:text-red-400" };
|
|
14
|
+
}
|
|
15
|
+
if (mimeType.startsWith("image/")) {
|
|
16
|
+
return { label: "IMG", bgClass: "bg-sky-500/15 text-sky-600 dark:bg-sky-500/20 dark:text-sky-400" };
|
|
17
|
+
}
|
|
18
|
+
return { label: "FILE", bgClass: "bg-muted text-muted-foreground" };
|
|
19
|
+
}
|
|
20
|
+
export function AttachmentRow({ file, typeOptions, autoAttached, onRename, onTypeChange, onRemove, onDownload, className, }) {
|
|
21
|
+
const [editing, setEditing] = React.useState(false);
|
|
22
|
+
const [editValue, setEditValue] = React.useState("");
|
|
23
|
+
const inputRef = React.useRef(null);
|
|
24
|
+
const displayName = file.name ?? file.fileName;
|
|
25
|
+
const icon = getFileIcon(file.mimeType);
|
|
26
|
+
React.useEffect(() => {
|
|
27
|
+
if (editing && inputRef.current) {
|
|
28
|
+
inputRef.current.focus();
|
|
29
|
+
inputRef.current.select();
|
|
30
|
+
}
|
|
31
|
+
}, [editing]);
|
|
32
|
+
function startEditing() {
|
|
33
|
+
if (!onRename)
|
|
34
|
+
return;
|
|
35
|
+
setEditValue(displayName);
|
|
36
|
+
setEditing(true);
|
|
37
|
+
}
|
|
38
|
+
function commitEdit() {
|
|
39
|
+
const trimmed = editValue.trim();
|
|
40
|
+
if (trimmed && trimmed !== displayName) {
|
|
41
|
+
onRename?.(file.id, trimmed);
|
|
42
|
+
}
|
|
43
|
+
setEditing(false);
|
|
44
|
+
}
|
|
45
|
+
function cancelEdit() {
|
|
46
|
+
setEditing(false);
|
|
47
|
+
}
|
|
48
|
+
function handleKeyDown(e) {
|
|
49
|
+
if (e.key === "Enter") {
|
|
50
|
+
e.preventDefault();
|
|
51
|
+
commitEdit();
|
|
52
|
+
}
|
|
53
|
+
else if (e.key === "Escape") {
|
|
54
|
+
e.preventDefault();
|
|
55
|
+
cancelEdit();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return (_jsxs("div", { className: cn("flex items-center gap-3 rounded-xl border border-border bg-background px-3.5 py-2.5", className), children: [_jsx("div", { className: cn("flex size-9 shrink-0 items-center justify-center rounded-lg text-xs font-bold", icon.bgClass), children: icon.label }), _jsxs("div", { className: "min-w-0 flex-1", children: [editing ? (_jsx("input", { ref: inputRef, type: "text", value: editValue, onChange: (e) => setEditValue(e.target.value), onBlur: commitEdit, onKeyDown: handleKeyDown, className: "w-full border-b border-dashed border-primary bg-transparent text-sm font-medium text-foreground outline-none" })) : (_jsx("button", { type: "button", onClick: onRename ? startEditing : onDownload ? () => onDownload(file.id) : undefined, className: cn("truncate text-left text-sm font-medium text-foreground", onRename &&
|
|
59
|
+
"cursor-text border-b border-dashed border-transparent hover:border-primary/40", !onRename && onDownload && "cursor-pointer hover:underline", !onRename && !onDownload && "cursor-default"), children: displayName })), _jsxs("p", { className: "text-[10px] text-muted-foreground", children: [formatFileSize(file.fileSize), autoAttached && (_jsx("span", { className: "ml-1.5", children: "\u00B7 Auto-attached from portfolio" }))] })] }), _jsx("select", { value: file.type ?? "generic", onChange: (e) => onTypeChange?.(file.id, e.target.value), className: "shrink-0 rounded-lg border border-border bg-background px-2 py-1 text-[11px] text-foreground", children: typeOptions.map((opt) => (_jsx("option", { value: opt.value, children: opt.label }, opt.value))) }), onRemove && (_jsx("button", { type: "button", onClick: () => onRemove(file.id), className: "shrink-0 text-sm text-muted-foreground transition-colors hover:text-red-500", "aria-label": "Remove attachment", children: "\u00D7" }))] }));
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=attachment-row.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attachment-row.js","sourceRoot":"","sources":["../../src/components/attachment-row.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
+
import { AttachmentRow } from "./attachment-row";
|
|
3
|
+
declare const meta: Meta<typeof AttachmentRow>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof meta>;
|
|
6
|
+
export declare const Default: Story;
|
|
7
|
+
export declare const AutoAttached: Story;
|
|
8
|
+
export declare const WithEditableName: Story;
|
|
9
|
+
//# sourceMappingURL=attachment-row.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attachment-row.stories.d.ts","sourceRoot":"","sources":["../../src/components/attachment-row.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAQjD,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,aAAa,CAOpC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAcrB,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAe1B,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAgB9B,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { AttachmentRow } from "./attachment-row";
|
|
3
|
+
const typeOptions = [
|
|
4
|
+
{ value: "product_image", label: "Product Image" },
|
|
5
|
+
{ value: "technical_sheet", label: "Technical Sheet" },
|
|
6
|
+
{ value: "generic", label: "Other Document" },
|
|
7
|
+
];
|
|
8
|
+
const meta = {
|
|
9
|
+
title: "Components/AttachmentRow",
|
|
10
|
+
component: AttachmentRow,
|
|
11
|
+
tags: ["autodocs"],
|
|
12
|
+
parameters: { layout: "padded" },
|
|
13
|
+
args: { typeOptions },
|
|
14
|
+
decorators: [(Story) => _jsx("div", { className: "max-w-lg", children: _jsx(Story, {}) })],
|
|
15
|
+
};
|
|
16
|
+
export default meta;
|
|
17
|
+
export const Default = {
|
|
18
|
+
args: {
|
|
19
|
+
file: {
|
|
20
|
+
id: "1",
|
|
21
|
+
fileName: "product-spec-2026.pdf",
|
|
22
|
+
mimeType: "application/pdf",
|
|
23
|
+
fileSize: 245_760,
|
|
24
|
+
type: "technical_sheet",
|
|
25
|
+
},
|
|
26
|
+
/* eslint-disable no-console */
|
|
27
|
+
onRemove: (id) => console.log("remove", id),
|
|
28
|
+
onTypeChange: (id, type) => console.log("type change", id, type),
|
|
29
|
+
/* eslint-enable no-console */
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
export const AutoAttached = {
|
|
33
|
+
args: {
|
|
34
|
+
file: {
|
|
35
|
+
id: "2",
|
|
36
|
+
fileName: "chateau-reserve-front.jpg",
|
|
37
|
+
mimeType: "image/jpeg",
|
|
38
|
+
fileSize: 1_832_960,
|
|
39
|
+
type: "product_image",
|
|
40
|
+
},
|
|
41
|
+
autoAttached: true,
|
|
42
|
+
/* eslint-disable no-console */
|
|
43
|
+
onRemove: (id) => console.log("remove", id),
|
|
44
|
+
onTypeChange: (id, type) => console.log("type change", id, type),
|
|
45
|
+
/* eslint-enable no-console */
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
export const WithEditableName = {
|
|
49
|
+
args: {
|
|
50
|
+
file: {
|
|
51
|
+
id: "3",
|
|
52
|
+
fileName: "compliance-report-final.pdf",
|
|
53
|
+
name: "Compliance Report",
|
|
54
|
+
mimeType: "application/pdf",
|
|
55
|
+
fileSize: 524_288,
|
|
56
|
+
type: "generic",
|
|
57
|
+
},
|
|
58
|
+
/* eslint-disable no-console */
|
|
59
|
+
onRename: (id, name) => console.log("rename", id, name),
|
|
60
|
+
onRemove: (id) => console.log("remove", id),
|
|
61
|
+
onTypeChange: (id, type) => console.log("type change", id, type),
|
|
62
|
+
/* eslint-enable no-console */
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
//# sourceMappingURL=attachment-row.stories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attachment-row.stories.js","sourceRoot":"","sources":["../../src/components/attachment-row.stories.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,MAAM,WAAW,GAAG;IAClB,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,eAAe,EAAE;IAClD,EAAE,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE,iBAAiB,EAAE;IACtD,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,gBAAgB,EAAE;CAC9C,CAAC;AAEF,MAAM,IAAI,GAA+B;IACvC,KAAK,EAAE,0BAA0B;IACjC,SAAS,EAAE,aAAa;IACxB,IAAI,EAAE,CAAC,UAAU,CAAC;IAClB,UAAU,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE;IAChC,IAAI,EAAE,EAAE,WAAW,EAAE;IACrB,UAAU,EAAE,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,cAAK,SAAS,EAAC,UAAU,YAAC,KAAC,KAAK,KAAG,GAAM,CAAC;CACnE,CAAC;AAEF,eAAe,IAAI,CAAC;AAGpB,MAAM,CAAC,MAAM,OAAO,GAAU;IAC5B,IAAI,EAAE;QACJ,IAAI,EAAE;YACJ,EAAE,EAAE,GAAG;YACP,QAAQ,EAAE,uBAAuB;YACjC,QAAQ,EAAE,iBAAiB;YAC3B,QAAQ,EAAE,OAAO;YACjB,IAAI,EAAE,iBAAiB;SACxB;QACD,+BAA+B;QAC/B,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC;QAC3C,YAAY,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,EAAE,EAAE,IAAI,CAAC;QAChE,8BAA8B;KAC/B;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAU;IACjC,IAAI,EAAE;QACJ,IAAI,EAAE;YACJ,EAAE,EAAE,GAAG;YACP,QAAQ,EAAE,2BAA2B;YACrC,QAAQ,EAAE,YAAY;YACtB,QAAQ,EAAE,SAAS;YACnB,IAAI,EAAE,eAAe;SACtB;QACD,YAAY,EAAE,IAAI;QAClB,+BAA+B;QAC/B,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC;QAC3C,YAAY,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,EAAE,EAAE,IAAI,CAAC;QAChE,8BAA8B;KAC/B;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAU;IACrC,IAAI,EAAE;QACJ,IAAI,EAAE;YACJ,EAAE,EAAE,GAAG;YACP,QAAQ,EAAE,6BAA6B;YACvC,IAAI,EAAE,mBAAmB;YACzB,QAAQ,EAAE,iBAAiB;YAC3B,QAAQ,EAAE,OAAO;YACjB,IAAI,EAAE,SAAS;SAChB;QACD,+BAA+B;QAC/B,QAAQ,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,EAAE,IAAI,CAAC;QACvD,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC;QAC3C,YAAY,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,EAAE,EAAE,IAAI,CAAC;QAChE,8BAA8B;KAC/B;CACF,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export type CertStatus = "required" | "filled" | "optional";
|
|
3
|
+
export interface CertificationUploadCardProps {
|
|
4
|
+
type: string;
|
|
5
|
+
label: string;
|
|
6
|
+
icon: React.ReactNode;
|
|
7
|
+
status: CertStatus;
|
|
8
|
+
file?: {
|
|
9
|
+
name: string;
|
|
10
|
+
size?: number;
|
|
11
|
+
} | null;
|
|
12
|
+
autoAttached?: boolean;
|
|
13
|
+
onUpload: (file: File) => void;
|
|
14
|
+
onRemove?: () => void;
|
|
15
|
+
onReplace?: () => void;
|
|
16
|
+
className?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function CertificationUploadCard({ label, icon, status, file, autoAttached, onUpload, onRemove, onReplace, className, }: CertificationUploadCardProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
//# sourceMappingURL=certification-upload-card.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"certification-upload-card.d.ts","sourceRoot":"","sources":["../../src/components/certification-upload-card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE5D,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;IACtB,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC9C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAuCD,wBAAgB,uBAAuB,CAAC,EACtC,KAAK,EACL,IAAI,EACJ,MAAM,EACN,IAAI,EACJ,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,SAAS,GACV,EAAE,4BAA4B,2CA4J9B"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { cn } from "../lib/utils";
|
|
4
|
+
const ACCEPTED_TYPES = ".pdf,.jpg,.jpeg,.png,.webp";
|
|
5
|
+
const containerStyles = {
|
|
6
|
+
filled: "border border-emerald-200 bg-emerald-50/60 dark:border-emerald-500/20 dark:bg-emerald-950/20",
|
|
7
|
+
required: "border border-dashed border-amber-300 bg-amber-50/40 dark:border-amber-500/20 dark:bg-amber-950/20",
|
|
8
|
+
optional: "border border-dashed border-border/60 bg-muted/30 opacity-70",
|
|
9
|
+
};
|
|
10
|
+
const iconStyles = {
|
|
11
|
+
filled: "bg-emerald-100 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-300",
|
|
12
|
+
required: "bg-amber-100 text-amber-700 dark:bg-amber-900/40 dark:text-amber-300",
|
|
13
|
+
optional: "bg-muted text-muted-foreground",
|
|
14
|
+
};
|
|
15
|
+
const labelStyles = {
|
|
16
|
+
filled: "text-emerald-700 dark:text-emerald-300",
|
|
17
|
+
required: "text-amber-700 dark:text-amber-300",
|
|
18
|
+
optional: "text-muted-foreground",
|
|
19
|
+
};
|
|
20
|
+
const dropZoneBorderStyles = {
|
|
21
|
+
required: "border-amber-300 text-amber-700 hover:bg-amber-50 dark:border-amber-500/30 dark:text-amber-300 dark:hover:bg-amber-950/30",
|
|
22
|
+
optional: "border-border/60 text-muted-foreground hover:bg-muted/40 dark:hover:bg-muted/20",
|
|
23
|
+
};
|
|
24
|
+
function formatFileSize(bytes) {
|
|
25
|
+
if (bytes < 1024)
|
|
26
|
+
return `${bytes} B`;
|
|
27
|
+
if (bytes < 1024 * 1024)
|
|
28
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
29
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
30
|
+
}
|
|
31
|
+
export function CertificationUploadCard({ label, icon, status, file, autoAttached, onUpload, onRemove, onReplace, className, }) {
|
|
32
|
+
const inputRef = React.useRef(null);
|
|
33
|
+
const [dragOver, setDragOver] = React.useState(false);
|
|
34
|
+
const handleFileChange = (e) => {
|
|
35
|
+
const selected = e.target.files?.[0];
|
|
36
|
+
if (selected) {
|
|
37
|
+
onUpload(selected);
|
|
38
|
+
// Reset input so the same file can be re-selected
|
|
39
|
+
e.target.value = "";
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
const handleDragOver = (e) => {
|
|
43
|
+
e.preventDefault();
|
|
44
|
+
e.stopPropagation();
|
|
45
|
+
setDragOver(true);
|
|
46
|
+
};
|
|
47
|
+
const handleDragLeave = (e) => {
|
|
48
|
+
e.preventDefault();
|
|
49
|
+
e.stopPropagation();
|
|
50
|
+
setDragOver(false);
|
|
51
|
+
};
|
|
52
|
+
const handleDrop = (e) => {
|
|
53
|
+
e.preventDefault();
|
|
54
|
+
e.stopPropagation();
|
|
55
|
+
setDragOver(false);
|
|
56
|
+
const droppedFile = e.dataTransfer.files[0];
|
|
57
|
+
if (droppedFile) {
|
|
58
|
+
onUpload(droppedFile);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const handleDropZoneClick = () => {
|
|
62
|
+
inputRef.current?.click();
|
|
63
|
+
};
|
|
64
|
+
const handleReplaceClick = () => {
|
|
65
|
+
if (onReplace) {
|
|
66
|
+
onReplace();
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
inputRef.current?.click();
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
return (_jsxs("div", { className: cn("relative flex flex-col items-center rounded-xl p-4 text-center transition-all", containerStyles[status], dragOver && "ring-2 ring-primary/40", className), onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, children: [status === "filled" && autoAttached && (_jsx("span", { className: "absolute -top-2 right-2 rounded-full bg-emerald-600 px-2 py-0.5 text-[9px] font-bold text-white", children: "AUTO" })), _jsx("div", { className: cn("mb-2 flex size-9 items-center justify-center rounded-lg", iconStyles[status]), children: icon }), _jsx("span", { className: cn("text-[11px] font-bold uppercase tracking-[0.06em]", labelStyles[status]), children: label }), status === "filled" && file ? (_jsxs("div", { className: "mt-2 w-full", children: [_jsxs("div", { className: "inline-flex items-center gap-1.5 rounded-full bg-emerald-100/80 px-2.5 py-1 dark:bg-emerald-900/30", children: [_jsx("span", { className: "max-w-[120px] truncate text-[11px] font-medium text-emerald-800 dark:text-emerald-200", children: file.name }), file.size != null && (_jsx("span", { className: "text-[10px] text-emerald-600 dark:text-emerald-400", children: formatFileSize(file.size) }))] }), _jsxs("div", { className: "mt-1.5 flex items-center justify-center gap-2", children: [_jsx("button", { type: "button", onClick: handleReplaceClick, className: "text-[10px] font-medium text-emerald-700 underline-offset-2 hover:underline dark:text-emerald-300", children: "Replace" }), onRemove && (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-emerald-300 dark:text-emerald-700", children: "|" }), _jsx("button", { type: "button", onClick: onRemove, className: "text-[10px] font-medium text-red-600 underline-offset-2 hover:underline dark:text-red-400", children: "Remove" })] }))] })] })) : (_jsxs("div", { className: "mt-2 w-full", children: [status === "required" && (_jsx("p", { className: "mb-1.5 text-[10px] text-amber-600 dark:text-amber-400", children: "Required \u00B7 Not uploaded" })), _jsx("button", { type: "button", onClick: handleDropZoneClick, className: cn("w-full cursor-pointer rounded-lg border border-dashed px-3 py-1.5 text-[11px] font-medium transition-colors", dropZoneBorderStyles[status === "required" ? "required" : "optional"]), children: "Drop file or click" })] })), _jsx("input", { ref: inputRef, type: "file", accept: ACCEPTED_TYPES, className: "hidden", onChange: handleFileChange, tabIndex: -1 })] }));
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=certification-upload-card.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"certification-upload-card.js","sourceRoot":"","sources":["../../src/components/certification-upload-card.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
+
import { CertificationUploadCard } from "./certification-upload-card";
|
|
3
|
+
declare const meta: Meta<typeof CertificationUploadCard>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof meta>;
|
|
6
|
+
export declare const Required: Story;
|
|
7
|
+
export declare const Filled: Story;
|
|
8
|
+
export declare const Optional: Story;
|
|
9
|
+
//# sourceMappingURL=certification-upload-card.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"certification-upload-card.stories.d.ts","sourceRoot":"","sources":["../../src/components/certification-upload-card.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAEtE,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,uBAAuB,CAM9C,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAmBnC,eAAO,MAAM,QAAQ,EAAE,KAQtB,CAAC;AAEF,eAAO,MAAM,MAAM,EAAE,KAYpB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAQtB,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { CertificationUploadCard } from "./certification-upload-card";
|
|
3
|
+
const meta = {
|
|
4
|
+
title: "Components/CertificationUploadCard",
|
|
5
|
+
component: CertificationUploadCard,
|
|
6
|
+
tags: ["autodocs"],
|
|
7
|
+
parameters: { layout: "padded" },
|
|
8
|
+
decorators: [(Story) => _jsx("div", { className: "w-48", children: _jsx(Story, {}) })],
|
|
9
|
+
};
|
|
10
|
+
export default meta;
|
|
11
|
+
/** Inline leaf icon — avoids importing lucide into the ui package */
|
|
12
|
+
const LeafIcon = () => (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", className: "size-5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M11 20A7 7 0 0 1 9.8 6.9C15.5 4.9 17 3.5 19 2c1 2 2 4.5 2 8 0 5.5-4.78 10-10 10Z" }), _jsx("path", { d: "M2 21c0-3 1.85-5.36 5.08-6C9.5 14.52 12 13 13 12" })] }));
|
|
13
|
+
export const Required = {
|
|
14
|
+
args: {
|
|
15
|
+
type: "organic",
|
|
16
|
+
label: "Organic",
|
|
17
|
+
icon: _jsx(LeafIcon, {}),
|
|
18
|
+
status: "required",
|
|
19
|
+
onUpload: (file) => console.warn("Upload:", file.name),
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
export const Filled = {
|
|
23
|
+
args: {
|
|
24
|
+
type: "organic",
|
|
25
|
+
label: "Organic",
|
|
26
|
+
icon: _jsx(LeafIcon, {}),
|
|
27
|
+
status: "filled",
|
|
28
|
+
file: { name: "organic-cert-2026.pdf", size: 245_000 },
|
|
29
|
+
autoAttached: true,
|
|
30
|
+
onUpload: (file) => console.warn("Upload:", file.name),
|
|
31
|
+
onRemove: () => console.warn("Remove"),
|
|
32
|
+
onReplace: () => console.warn("Replace"),
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
export const Optional = {
|
|
36
|
+
args: {
|
|
37
|
+
type: "sustainable",
|
|
38
|
+
label: "Sustainable",
|
|
39
|
+
icon: _jsx(LeafIcon, {}),
|
|
40
|
+
status: "optional",
|
|
41
|
+
onUpload: (file) => console.warn("Upload:", file.name),
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=certification-upload-card.stories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"certification-upload-card.stories.js","sourceRoot":"","sources":["../../src/components/certification-upload-card.stories.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAEtE,MAAM,IAAI,GAAyC;IACjD,KAAK,EAAE,oCAAoC;IAC3C,SAAS,EAAE,uBAAuB;IAClC,IAAI,EAAE,CAAC,UAAU,CAAC;IAClB,UAAU,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE;IAChC,UAAU,EAAE,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,cAAK,SAAS,EAAC,MAAM,YAAC,KAAC,KAAK,KAAG,GAAM,CAAC;CAC/D,CAAC;AAEF,eAAe,IAAI,CAAC;AAGpB,qEAAqE;AACrE,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,CACrB,eACE,KAAK,EAAC,4BAA4B,EAClC,SAAS,EAAC,QAAQ,EAClB,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAE,GAAG,EAChB,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,aAEtB,eAAM,CAAC,EAAC,kFAAkF,GAAG,EAC7F,eAAM,CAAC,EAAC,kDAAkD,GAAG,IACzD,CACP,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAU;IAC7B,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,KAAC,QAAQ,KAAG;QAClB,MAAM,EAAE,UAAU;QAClB,QAAQ,EAAE,CAAC,IAAU,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC;KAC7D;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,MAAM,GAAU;IAC3B,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,KAAC,QAAQ,KAAG;QAClB,MAAM,EAAE,QAAQ;QAChB,IAAI,EAAE,EAAE,IAAI,EAAE,uBAAuB,EAAE,IAAI,EAAE,OAAO,EAAE;QACtD,YAAY,EAAE,IAAI;QAClB,QAAQ,EAAE,CAAC,IAAU,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC;QAC5D,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;QACtC,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC;KACzC;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAU;IAC7B,IAAI,EAAE;QACJ,IAAI,EAAE,aAAa;QACnB,KAAK,EAAE,aAAa;QACpB,IAAI,EAAE,KAAC,QAAQ,KAAG;QAClB,MAAM,EAAE,UAAU;QAClB,QAAQ,EAAE,CAAC,IAAU,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC;KAC7D;CACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"confirmation-dialog.d.ts","sourceRoot":"","sources":["../../src/components/confirmation-dialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAQ/B,MAAM,MAAM,sBAAsB,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;AAEnE,MAAM,WAAW,uBAAuB;IACtC,kCAAkC;IAClC,IAAI,EAAE,OAAO,CAAC;IACd,0EAA0E;IAC1E,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,2FAA2F;IAC3F,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtC,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,4EAA4E;IAC5E,IAAI,CAAC,EAAE,sBAAsB,CAAC;IAC9B,wFAAwF;IACxF,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,uDAAuD;IACvD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,uFAAuF;IACvF,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AA8FD,wBAAgB,kBAAkB,CAAC,EACjC,IAAI,EACJ,OAAO,EACP,SAAS,EACT,KAAK,EACL,WAAW,EACX,OAAO,EACP,IAAe,EACf,IAAI,EACJ,YAAwB,EACxB,WAAsB,EACtB,SAAS,EAAE,eAAuB,EAClC,QAAQ,GACT,EAAE,uBAAuB,
|
|
1
|
+
{"version":3,"file":"confirmation-dialog.d.ts","sourceRoot":"","sources":["../../src/components/confirmation-dialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAQ/B,MAAM,MAAM,sBAAsB,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;AAEnE,MAAM,WAAW,uBAAuB;IACtC,kCAAkC;IAClC,IAAI,EAAE,OAAO,CAAC;IACd,0EAA0E;IAC1E,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,2FAA2F;IAC3F,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtC,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,4EAA4E;IAC5E,IAAI,CAAC,EAAE,sBAAsB,CAAC;IAC9B,wFAAwF;IACxF,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,uDAAuD;IACvD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,uFAAuF;IACvF,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AA8FD,wBAAgB,kBAAkB,CAAC,EACjC,IAAI,EACJ,OAAO,EACP,SAAS,EACT,KAAK,EACL,WAAW,EACX,OAAO,EACP,IAAe,EACf,IAAI,EACJ,YAAwB,EACxB,WAAsB,EACtB,SAAS,EAAE,eAAuB,EAClC,QAAQ,GACT,EAAE,uBAAuB,2CAwEzB"}
|
|
@@ -62,6 +62,7 @@ export function ConfirmationDialog({ open, onClose, onConfirm, title, descriptio
|
|
|
62
62
|
};
|
|
63
63
|
// Reset submitting state when dialog closes
|
|
64
64
|
React.useEffect(() => {
|
|
65
|
+
// eslint-disable-next-line @eslint-react/set-state-in-effect -- intentional reset on prop change
|
|
65
66
|
if (!open)
|
|
66
67
|
setSubmitting(false);
|
|
67
68
|
}, [open]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"confirmation-dialog.js","sourceRoot":"","sources":["../../src/components/confirmation-dialog.tsx"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"confirmation-dialog.js","sourceRoot":"","sources":["../../src/components/confirmation-dialog.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,iBAAiB,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC7F,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAqClC,8EAA8E;AAC9E,sDAAsD;AACtD,8EAA8E;AAE9E,SAAS,sBAAsB,CAAC,KAAoC;IAClE,OAAO,CACL,cACE,KAAK,EAAC,4BAA4B,EAClC,IAAI,EAAC,MAAM,EACX,OAAO,EAAC,WAAW,EACnB,WAAW,EAAE,GAAG,EAChB,MAAM,EAAC,cAAc,iBACT,MAAM,KACd,KAAK,YAET,eACE,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EACtB,CAAC,EAAC,kLAAkL,GACpL,GACE,CACP,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAoC;IAChE,OAAO,CACL,cACE,KAAK,EAAC,4BAA4B,EAClC,IAAI,EAAC,MAAM,EACX,OAAO,EAAC,WAAW,EACnB,WAAW,EAAE,GAAG,EAChB,MAAM,EAAC,cAAc,iBACT,MAAM,KACd,KAAK,YAET,eACE,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EACtB,CAAC,EAAC,0JAA0J,GAC5J,GACE,CACP,CAAC;AACJ,CAAC;AAgBD,MAAM,WAAW,GAA+C;IAC9D,MAAM,EAAE;QACN,MAAM,EAAE,kCAAkC;QAC1C,SAAS,EAAE,gCAAgC;QAC3C,aAAa,EAAE,2CAA2C;QAC1D,SAAS,EAAE,kCAAkC;QAC7C,WAAW,EAAE,oCAAoC;QACjD,WAAW,EAAE,KAAK;QAClB,WAAW,EAAE,KAAC,sBAAsB,IAAC,SAAS,EAAC,QAAQ,GAAG;KAC3D;IACD,OAAO,EAAE;QACP,MAAM,EAAE,sCAAsC;QAC9C,SAAS,EAAE,oCAAoC;QAC/C,aAAa,EAAE,2CAA2C;QAC1D,SAAS,EAAE,kCAAkC;QAC7C,WAAW,EAAE,oCAAoC;QACjD,WAAW,EAAE,OAAO;QACpB,WAAW,EAAE,KAAC,sBAAsB,IAAC,SAAS,EAAC,QAAQ,GAAG;KAC3D;IACD,IAAI,EAAE;QACJ,MAAM,EAAE,oCAAoC;QAC5C,SAAS,EAAE,kCAAkC;QAC7C,aAAa,EAAE,yCAAyC;QACxD,SAAS,EAAE,gCAAgC;QAC3C,WAAW,EAAE,kCAAkC;QAC/C,WAAW,EAAE,MAAM;QACnB,WAAW,EAAE,KAAC,oBAAoB,IAAC,SAAS,EAAC,QAAQ,GAAG;KACzD;CACF,CAAC;AAEF,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E,MAAM,UAAU,kBAAkB,CAAC,EACjC,IAAI,EACJ,OAAO,EACP,SAAS,EACT,KAAK,EACL,WAAW,EACX,OAAO,EACP,IAAI,GAAG,QAAQ,EACf,IAAI,EACJ,YAAY,GAAG,SAAS,EACxB,WAAW,GAAG,QAAQ,EACtB,SAAS,EAAE,eAAe,GAAG,KAAK,EAClC,QAAQ,GACgB;IACxB,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC1D,MAAM,SAAS,GAAG,eAAe,IAAI,UAAU,CAAC;IAEhD,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAEjC,MAAM,aAAa,GAAG,KAAK,IAAI,EAAE;QAC/B,aAAa,CAAC,IAAI,CAAC,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,SAAS,EAAE,CAAC;YAClB,OAAO,EAAE,CAAC;QACZ,CAAC;QAAC,MAAM,CAAC;YACP,0DAA0D;QAC5D,CAAC;gBAAS,CAAC;YACT,aAAa,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC;IAEF,4CAA4C;IAC5C,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,iGAAiG;QACjG,IAAI,CAAC,IAAI;YAAE,aAAa,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,OAAO,CACL,MAAC,MAAM,IAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAC,IAAI,aAE7C,cAAK,SAAS,EAAC,qBAAqB,YAClC,cACE,SAAS,EAAE,yDAAyD,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,SAAS,EAAE,YAEtG,IAAI,IAAI,MAAM,CAAC,WAAW,GACvB,GACF,EAGN,KAAC,WAAW,IAAC,SAAS,EAAC,kBAAkB,YAAE,KAAK,GAAe,EAC9D,WAAW,IAAI,CACd,KAAC,iBAAiB,IAAC,SAAS,EAAC,aAAa,YACvC,WAAW,GACM,CACrB,EAGA,CAAC,OAAO,IAAI,QAAQ,CAAC,IAAI,CACxB,MAAC,UAAU,eACR,OAAO,IAAI,CACV,cACE,SAAS,EAAE,iCAAiC,MAAM,CAAC,aAAa,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,WAAW,EAAE,YAE3G,OAAO,GACJ,CACP,EACA,QAAQ,IACE,CACd,EAGD,MAAC,aAAa,eACZ,KAAC,MAAM,IAAC,KAAK,QAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,YAChD,WAAW,GACL,EACT,KAAC,MAAM,IACL,KAAK,EAAE,MAAM,CAAC,WAAW,EACzB,OAAO,EAAE,aAAa,EACtB,QAAQ,EAAE,SAAS,YAElB,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,GACxB,IACK,IACT,CACV,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface ContactPerson {
|
|
2
|
+
id: string;
|
|
3
|
+
name?: string | null;
|
|
4
|
+
email?: string | null;
|
|
5
|
+
role?: string | null;
|
|
6
|
+
}
|
|
7
|
+
export interface ContactPersonSelectProps {
|
|
8
|
+
members: ContactPerson[];
|
|
9
|
+
selectedId: string | null;
|
|
10
|
+
onSelect: (id: string) => void;
|
|
11
|
+
label?: string;
|
|
12
|
+
placeholder?: string;
|
|
13
|
+
className?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function ContactPersonSelect({ members, selectedId, onSelect, label, placeholder, className, }: ContactPersonSelectProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
//# sourceMappingURL=contact-person-select.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contact-person-select.d.ts","sourceRoot":"","sources":["../../src/components/contact-person-select.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAWD,wBAAgB,mBAAmB,CAAC,EAClC,OAAO,EACP,UAAU,EACV,QAAQ,EACR,KAAwB,EACxB,WAAmC,EACnC,SAAS,GACV,EAAE,wBAAwB,2CA2F1B"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../lib/utils";
|
|
3
|
+
function getInitials(name, email) {
|
|
4
|
+
if (name) {
|
|
5
|
+
const parts = name.split(/\s+/).filter(Boolean);
|
|
6
|
+
if (parts.length >= 2)
|
|
7
|
+
return `${parts[0][0]}${parts[1][0]}`.toUpperCase();
|
|
8
|
+
return parts[0]?.[0]?.toUpperCase() ?? "?";
|
|
9
|
+
}
|
|
10
|
+
return email?.[0]?.toUpperCase() ?? "?";
|
|
11
|
+
}
|
|
12
|
+
export function ContactPersonSelect({ members, selectedId, onSelect, label = "Contact Person", placeholder = "Select a contact...", className, }) {
|
|
13
|
+
const selected = members.find((m) => m.id === selectedId) ?? null;
|
|
14
|
+
function handleChange(e) {
|
|
15
|
+
onSelect(e.target.value);
|
|
16
|
+
}
|
|
17
|
+
return (_jsxs("div", { className: cn("relative", className), children: [_jsxs("span", { className: "mb-1.5 block text-[11px] font-semibold text-foreground", children: [label, _jsx("span", { className: "ml-0.5 text-red-500", children: "*" })] }), _jsxs("div", { className: "relative", children: [_jsxs("select", { value: selectedId ?? "", onChange: handleChange, className: "peer absolute inset-0 cursor-pointer opacity-0", "aria-label": label, children: [_jsx("option", { value: "", disabled: true, children: placeholder }), members.map((m) => (_jsxs("option", { value: m.id, children: [m.name ?? m.email ?? m.id, m.role ? ` - ${m.role}` : ""] }, m.id)))] }), _jsxs("div", { className: cn("flex items-center gap-2.5 rounded-xl border border-border bg-background px-3.5 py-2.5", "pointer-events-none peer-focus:ring-2 peer-focus:ring-ring peer-focus:ring-offset-1"), children: [_jsx("div", { className: "flex size-8 shrink-0 items-center justify-center rounded-lg bg-primary/10 text-xs font-bold text-primary", children: selected ? getInitials(selected.name, selected.email) : "?" }), _jsx("div", { className: "min-w-0 flex-1", children: selected ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "truncate text-sm font-semibold text-foreground", children: selected.name ?? selected.email ?? selected.id }), selected.role && (_jsx("div", { className: "truncate text-[11px] text-muted-foreground", children: selected.role }))] })) : (_jsx("div", { className: "truncate text-sm text-muted-foreground", children: placeholder })) }), _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", className: "size-4 shrink-0 text-muted-foreground", children: _jsx("path", { fillRule: "evenodd", d: "M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z", clipRule: "evenodd" }) })] })] }), selected?.email && (_jsx("p", { className: "mt-1 text-[10px] text-muted-foreground", children: selected.email }))] }));
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=contact-person-select.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contact-person-select.js","sourceRoot":"","sources":["../../src/components/contact-person-select.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { StoryObj } from "@storybook/react-vite";
|
|
2
|
+
import { ContactPersonSelect } from "./contact-person-select";
|
|
3
|
+
declare const meta: {
|
|
4
|
+
title: string;
|
|
5
|
+
component: typeof ContactPersonSelect;
|
|
6
|
+
tags: string[];
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: string;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
export default meta;
|
|
12
|
+
type Story = StoryObj<typeof meta>;
|
|
13
|
+
export declare const Default: Story;
|
|
14
|
+
export declare const WithNoRole: Story;
|
|
15
|
+
export declare const EmptyMembers: Story;
|
|
16
|
+
//# sourceMappingURL=contact-person-select.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contact-person-select.stories.d.ts","sourceRoot":"","sources":["../../src/components/contact-person-select.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EACL,mBAAmB,EAEpB,MAAM,yBAAyB,CAAC;AAuBjC,QAAA,MAAM,IAAI;;;;;;;CAKkC,CAAC;AAE7C,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAsBnC,eAAO,MAAM,OAAO,EAAE,KAGrB,CAAC;AAgBF,eAAO,MAAM,UAAU,EAAE,KAGxB,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAW1B,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { ContactPersonSelect, } from "./contact-person-select";
|
|
4
|
+
const MOCK_MEMBERS = [
|
|
5
|
+
{
|
|
6
|
+
id: "1",
|
|
7
|
+
name: "Marcus Lindgren",
|
|
8
|
+
email: "marcus@marcuswines.se",
|
|
9
|
+
role: "Export Manager",
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
id: "2",
|
|
13
|
+
name: "Sofia Andersson",
|
|
14
|
+
email: "sofia@marcuswines.se",
|
|
15
|
+
role: "Sales Director",
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: "3",
|
|
19
|
+
name: "Erik Johansson",
|
|
20
|
+
email: "erik@marcuswines.se",
|
|
21
|
+
role: null,
|
|
22
|
+
},
|
|
23
|
+
];
|
|
24
|
+
const meta = {
|
|
25
|
+
title: "Components/ContactPersonSelect",
|
|
26
|
+
component: ContactPersonSelect,
|
|
27
|
+
tags: ["autodocs"],
|
|
28
|
+
parameters: { layout: "centered" },
|
|
29
|
+
};
|
|
30
|
+
export default meta;
|
|
31
|
+
const stubArgs = {
|
|
32
|
+
members: MOCK_MEMBERS,
|
|
33
|
+
selectedId: null,
|
|
34
|
+
onSelect: () => { },
|
|
35
|
+
};
|
|
36
|
+
function DefaultRender() {
|
|
37
|
+
const [selectedId, setSelectedId] = useState("1");
|
|
38
|
+
return (_jsx("div", { className: "w-full max-w-xs", children: _jsx(ContactPersonSelect, { members: MOCK_MEMBERS, selectedId: selectedId, onSelect: setSelectedId }) }));
|
|
39
|
+
}
|
|
40
|
+
export const Default = {
|
|
41
|
+
args: stubArgs,
|
|
42
|
+
render: () => _jsx(DefaultRender, {}),
|
|
43
|
+
};
|
|
44
|
+
function WithNoRoleRender() {
|
|
45
|
+
const [selectedId, setSelectedId] = useState("3");
|
|
46
|
+
return (_jsx("div", { className: "w-full max-w-xs", children: _jsx(ContactPersonSelect, { members: MOCK_MEMBERS, selectedId: selectedId, onSelect: setSelectedId }) }));
|
|
47
|
+
}
|
|
48
|
+
export const WithNoRole = {
|
|
49
|
+
args: stubArgs,
|
|
50
|
+
render: () => _jsx(WithNoRoleRender, {}),
|
|
51
|
+
};
|
|
52
|
+
export const EmptyMembers = {
|
|
53
|
+
args: stubArgs,
|
|
54
|
+
render: () => (_jsx("div", { className: "w-full max-w-xs", children: _jsx(ContactPersonSelect, { members: [], selectedId: null, onSelect: () => { } }) })),
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=contact-person-select.stories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contact-person-select.stories.js","sourceRoot":"","sources":["../../src/components/contact-person-select.stories.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EACL,mBAAmB,GAEpB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,YAAY,GAAoB;IACpC;QACE,EAAE,EAAE,GAAG;QACP,IAAI,EAAE,iBAAiB;QACvB,KAAK,EAAE,uBAAuB;QAC9B,IAAI,EAAE,gBAAgB;KACvB;IACD;QACE,EAAE,EAAE,GAAG;QACP,IAAI,EAAE,iBAAiB;QACvB,KAAK,EAAE,sBAAsB;QAC7B,IAAI,EAAE,gBAAgB;KACvB;IACD;QACE,EAAE,EAAE,GAAG;QACP,IAAI,EAAE,gBAAgB;QACtB,KAAK,EAAE,qBAAqB;QAC5B,IAAI,EAAE,IAAI;KACX;CACF,CAAC;AAEF,MAAM,IAAI,GAAG;IACX,KAAK,EAAE,gCAAgC;IACvC,SAAS,EAAE,mBAAmB;IAC9B,IAAI,EAAE,CAAC,UAAU,CAAC;IAClB,UAAU,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE;CACQ,CAAC;AAE7C,eAAe,IAAI,CAAC;AAGpB,MAAM,QAAQ,GAAG;IACf,OAAO,EAAE,YAAY;IACrB,UAAU,EAAE,IAAI;IAChB,QAAQ,EAAE,GAAG,EAAE,GAAE,CAAC;CACnB,CAAC;AAEF,SAAS,aAAa;IACpB,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAgB,GAAG,CAAC,CAAC;IAEjE,OAAO,CACL,cAAK,SAAS,EAAC,iBAAiB,YAC9B,KAAC,mBAAmB,IAClB,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,aAAa,GACvB,GACE,CACP,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAU;IAC5B,IAAI,EAAE,QAAQ;IACd,MAAM,EAAE,GAAG,EAAE,CAAC,KAAC,aAAa,KAAG;CAChC,CAAC;AAEF,SAAS,gBAAgB;IACvB,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAgB,GAAG,CAAC,CAAC;IAEjE,OAAO,CACL,cAAK,SAAS,EAAC,iBAAiB,YAC9B,KAAC,mBAAmB,IAClB,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,aAAa,GACvB,GACE,CACP,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAU;IAC/B,IAAI,EAAE,QAAQ;IACd,MAAM,EAAE,GAAG,EAAE,CAAC,KAAC,gBAAgB,KAAG;CACnC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAU;IACjC,IAAI,EAAE,QAAQ;IACd,MAAM,EAAE,GAAG,EAAE,CAAC,CACZ,cAAK,SAAS,EAAC,iBAAiB,YAC9B,KAAC,mBAAmB,IAClB,OAAO,EAAE,EAAE,EACX,UAAU,EAAE,IAAI,EAChB,QAAQ,EAAE,GAAG,EAAE,GAAE,CAAC,GAClB,GACE,CACP;CACF,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface PriceComparisonProps {
|
|
2
|
+
targetPrice: number | string | null;
|
|
3
|
+
targetLabel?: string;
|
|
4
|
+
targetSubLabel?: string;
|
|
5
|
+
currency?: string;
|
|
6
|
+
offeredPrice: string;
|
|
7
|
+
onPriceChange: (value: string) => void;
|
|
8
|
+
offeredLabel?: string;
|
|
9
|
+
offeredHint?: string;
|
|
10
|
+
className?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function PriceComparison({ targetPrice, targetLabel, targetSubLabel, currency, offeredPrice, onPriceChange, offeredLabel, offeredHint, className, }: PriceComparisonProps): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
//# sourceMappingURL=price-comparison.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"price-comparison.d.ts","sourceRoot":"","sources":["../../src/components/price-comparison.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA8DD,wBAAgB,eAAe,CAAC,EAC9B,WAAW,EACX,WAAoC,EACpC,cAAc,EACd,QAAgB,EAChB,YAAY,EACZ,aAAa,EACb,YAAmC,EACnC,WAA8C,EAC9C,SAAS,GACV,EAAE,oBAAoB,2CAoEtB"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { cn } from "../lib/utils";
|
|
4
|
+
function formatPrice(value, currency) {
|
|
5
|
+
return `${value.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} ${currency}`;
|
|
6
|
+
}
|
|
7
|
+
function computeDelta(target, offered, currency) {
|
|
8
|
+
if (target === 0)
|
|
9
|
+
return null;
|
|
10
|
+
const diff = offered - target;
|
|
11
|
+
const pct = Math.abs((diff / target) * 100);
|
|
12
|
+
const absDiff = Math.abs(diff).toFixed(2);
|
|
13
|
+
if (diff === 0) {
|
|
14
|
+
return { diff: 0, pct: 0, tone: "emerald", label: "At target price" };
|
|
15
|
+
}
|
|
16
|
+
if (diff < 0) {
|
|
17
|
+
return {
|
|
18
|
+
diff,
|
|
19
|
+
pct,
|
|
20
|
+
tone: "emerald",
|
|
21
|
+
label: `▼ ${absDiff} ${currency} below target (${pct.toFixed(0)}%) — Competitive`,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
if (pct > 15) {
|
|
25
|
+
return {
|
|
26
|
+
diff,
|
|
27
|
+
pct,
|
|
28
|
+
tone: "red",
|
|
29
|
+
label: `▲ ${absDiff} ${currency} above target (${pct.toFixed(0)}%) — Above range`,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
diff,
|
|
34
|
+
pct,
|
|
35
|
+
tone: "amber",
|
|
36
|
+
label: `▲ ${absDiff} ${currency} above target (${pct.toFixed(0)}%)`,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
const deltaClasses = {
|
|
40
|
+
emerald: "border-emerald-200 bg-emerald-50/60 text-emerald-700 dark:border-emerald-500/25 dark:bg-emerald-950/30 dark:text-emerald-300",
|
|
41
|
+
amber: "border-amber-200 bg-amber-50/60 text-amber-700 dark:border-amber-500/25 dark:bg-amber-950/30 dark:text-amber-300",
|
|
42
|
+
red: "border-red-200 bg-red-50/60 text-red-700 dark:border-red-500/25 dark:bg-red-950/30 dark:text-red-300",
|
|
43
|
+
};
|
|
44
|
+
export function PriceComparison({ targetPrice, targetLabel = "Buyer's Target Price", targetSubLabel, currency = "SEK", offeredPrice, onPriceChange, offeredLabel = "Your Offered Price", offeredHint = "Price you're offering per unit", className, }) {
|
|
45
|
+
const parsedTarget = targetPrice !== null ? Number(targetPrice) : null;
|
|
46
|
+
const parsedOffered = Number(offeredPrice);
|
|
47
|
+
const delta = React.useMemo(() => {
|
|
48
|
+
if (parsedTarget === null ||
|
|
49
|
+
Number.isNaN(parsedTarget) ||
|
|
50
|
+
Number.isNaN(parsedOffered) ||
|
|
51
|
+
offeredPrice.trim() === "") {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
return computeDelta(parsedTarget, parsedOffered, currency);
|
|
55
|
+
}, [parsedTarget, parsedOffered, currency, offeredPrice]);
|
|
56
|
+
return (_jsxs("div", { className: cn("grid grid-cols-2 gap-3", className), children: [_jsxs("div", { className: "rounded-xl border border-sky-200/60 bg-sky-50/50 px-4 py-3.5 text-right dark:border-sky-500/15 dark:bg-sky-950/20", children: [_jsx("p", { className: "text-[10px] font-semibold uppercase tracking-[0.08em] text-sky-700 dark:text-sky-300", children: targetLabel }), targetSubLabel && (_jsx("p", { className: "mt-0.5 text-[11px] text-sky-600/70 dark:text-sky-400/60", children: targetSubLabel })), _jsx("p", { className: "mt-1.5 text-2xl font-bold tabular-nums text-sky-800 dark:text-sky-200", children: parsedTarget !== null && !Number.isNaN(parsedTarget)
|
|
57
|
+
? formatPrice(parsedTarget, currency)
|
|
58
|
+
: "—" })] }), _jsxs("div", { children: [_jsxs("label", { className: "mb-1 block text-[11px] font-semibold text-foreground", children: [offeredLabel, _jsx("span", { className: "ml-0.5 text-red-500", "aria-hidden": "true", children: "*" })] }), _jsx("input", { type: "text", inputMode: "decimal", value: offeredPrice, onChange: (e) => onPriceChange(e.target.value), className: "w-full rounded-lg border border-border bg-background px-3 py-2.5 text-lg font-semibold tabular-nums text-foreground outline-hidden transition-shadow focus:ring-2 focus:ring-ring", "aria-label": offeredLabel }), _jsx("p", { className: "mt-1 text-[10px] text-muted-foreground", children: offeredHint })] }), delta && (_jsx("div", { className: cn("col-span-2 rounded-lg border px-3 py-1.5 text-center text-[11px] font-semibold", deltaClasses[delta.tone]), children: delta.label }))] }));
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=price-comparison.js.map
|