Cambios
This commit is contained in:
parent
1bbaf0aaee
commit
5f9405d1a0
@ -1,8 +1,9 @@
|
|||||||
import { Avatar, AvatarFallback, Badge } from "@repo/shadcn-ui/components";
|
import { InitialsAvatar } from "@repo/rdx-ui/components";
|
||||||
|
import { Badge } from "@repo/shadcn-ui/components";
|
||||||
import { Building2Icon, CopyIcon, UserIcon } from "lucide-react";
|
import { Building2Icon, CopyIcon, UserIcon } from "lucide-react";
|
||||||
|
|
||||||
import type { Proforma } from "../../../../shared";
|
import type { Proforma } from "../../../../shared";
|
||||||
import { Initials, ProformaStatusBadge } from "../../components";
|
import { ProformaStatusBadge } from "../../components";
|
||||||
|
|
||||||
export const ProformaHeader = ({ proforma }: { proforma: Proforma }) => {
|
export const ProformaHeader = ({ proforma }: { proforma: Proforma }) => {
|
||||||
const handleCopyTin = async () => {
|
const handleCopyTin = async () => {
|
||||||
@ -16,17 +17,7 @@ export const ProformaHeader = ({ proforma }: { proforma: Proforma }) => {
|
|||||||
return (
|
return (
|
||||||
<div className="p-4">
|
<div className="p-4">
|
||||||
<div className="flex items-start gap-4">
|
<div className="flex items-start gap-4">
|
||||||
<Avatar className="size-10 border-2 border-background shadow-sm">
|
<InitialsAvatar name={proforma.recipient.name} />
|
||||||
<AvatarFallback
|
|
||||||
className={
|
|
||||||
proforma.status !== "draft"
|
|
||||||
? "bg-blue-100 text-blue-700"
|
|
||||||
: "bg-muted text-muted-foreground"
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Initials name={proforma.recipient.name} />
|
|
||||||
</AvatarFallback>
|
|
||||||
</Avatar>
|
|
||||||
|
|
||||||
<div className="min-w-0 flex-1">
|
<div className="min-w-0 flex-1">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
|
|||||||
@ -103,7 +103,6 @@ export function useProformasGridColumns(
|
|||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger>
|
<TooltipTrigger>
|
||||||
<Button
|
<Button
|
||||||
asChild
|
|
||||||
className="size-6 text-foreground hover:text-primary"
|
className="size-6 text-foreground hover:text-primary"
|
||||||
size="icon"
|
size="icon"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
@ -143,7 +142,7 @@ export function useProformasGridColumns(
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
className="text-primary hover:underline font-semibold"
|
className="text-primary hover:underline font-semibold text-ellipsis"
|
||||||
onClick={() => actionHandlers.onPreviewClick?.(proforma)}
|
onClick={() => actionHandlers.onPreviewClick?.(proforma)}
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
@ -158,10 +157,6 @@ export function useProformasGridColumns(
|
|||||||
accessorKey: "series",
|
accessorKey: "series",
|
||||||
header: "Serie",
|
header: "Serie",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
accessorKey: "reference",
|
|
||||||
header: "Reference",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
accessorKey: "invoiceDate",
|
accessorKey: "invoiceDate",
|
||||||
header: ({ column }) => {
|
header: ({ column }) => {
|
||||||
|
|||||||
@ -97,7 +97,7 @@ export const ListProformasPage = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<section>
|
||||||
<AppHeader>
|
<AppHeader>
|
||||||
<PageHeader
|
<PageHeader
|
||||||
description={t("pages.proformas.list.description")}
|
description={t("pages.proformas.list.description")}
|
||||||
@ -193,6 +193,6 @@ export const ListProformasPage = () => {
|
|||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
</AppContent>
|
</AppContent>
|
||||||
</>
|
</section>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -103,6 +103,7 @@ export const ProformaUpdatePage = () => {
|
|||||||
isSubmitting={updateCtrl.isUpdating}
|
isSubmitting={updateCtrl.isUpdating}
|
||||||
onChangeCustomerClick={selectCustomerCtrl.selectCtrl.openDialog}
|
onChangeCustomerClick={selectCustomerCtrl.selectCtrl.openDialog}
|
||||||
//onCreateCustomerClick={selectCustomerCtrl.createCtrl.openDialog}
|
//onCreateCustomerClick={selectCustomerCtrl.createCtrl.openDialog}
|
||||||
|
onCreateCustomerClick={() => null}
|
||||||
onReset={updateCtrl.resetForm}
|
onReset={updateCtrl.resetForm}
|
||||||
onSubmit={updateCtrl.onSubmit}
|
onSubmit={updateCtrl.onSubmit}
|
||||||
selectedCustomer={updateCtrl.selectedCustomer}
|
selectedCustomer={updateCtrl.selectedCustomer}
|
||||||
|
|||||||
@ -3,43 +3,20 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
|
DialogFooter,
|
||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
Item,
|
|
||||||
ItemContent,
|
|
||||||
ItemDescription,
|
|
||||||
ItemGroup,
|
|
||||||
ItemTitle,
|
|
||||||
} from "@repo/shadcn-ui/components";
|
} from "@repo/shadcn-ui/components";
|
||||||
import { cn } from "@repo/shadcn-ui/lib/utils";
|
import { useState } from "react";
|
||||||
|
|
||||||
import type { CustomerSelectionOption } from "../../../../../common/features";
|
import type { CustomerSelectionOption } from "../../../../../common/features";
|
||||||
import { useTranslation } from "../../../../../web/i18n";
|
import { useTranslation } from "../../../../../web/i18n";
|
||||||
import type { useSelectCustomerDialogController } from "../../controllers";
|
import type { useSelectCustomerDialogController } from "../../controllers";
|
||||||
|
|
||||||
import { SelectCustomerEmptyCard } from "./select-customer-empty-card";
|
import { SelectCustomerSelectionList } from "./select-customer-selection-list";
|
||||||
|
|
||||||
type SelectCustomerDialogController = ReturnType<typeof useSelectCustomerDialogController>;
|
type SelectCustomerDialogController = ReturnType<typeof useSelectCustomerDialogController>;
|
||||||
|
|
||||||
/*export const useSelectCustomerDialogController = () => {
|
|
||||||
isOpen: boolean;
|
|
||||||
closeDialog: () => void;
|
|
||||||
|
|
||||||
search: string;
|
|
||||||
setSearchValue: (value: string) => void;
|
|
||||||
|
|
||||||
customers: CustomerSelectionOption[];
|
|
||||||
isLoading: boolean;
|
|
||||||
isFetching: boolean;
|
|
||||||
|
|
||||||
isErrror: boolean;
|
|
||||||
error: unknown;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
selectCustomer: (customer: CustomerSelectionOption) => void;
|
|
||||||
};*/
|
|
||||||
|
|
||||||
type SelectCustomerDialogProps = {
|
type SelectCustomerDialogProps = {
|
||||||
ctrl: SelectCustomerDialogController;
|
ctrl: SelectCustomerDialogController;
|
||||||
onCreateNewCustomerClick?: () => void;
|
onCreateNewCustomerClick?: () => void;
|
||||||
@ -49,8 +26,21 @@ export const SelectCustomerDialog = ({
|
|||||||
ctrl,
|
ctrl,
|
||||||
onCreateNewCustomerClick,
|
onCreateNewCustomerClick,
|
||||||
}: SelectCustomerDialogProps) => {
|
}: SelectCustomerDialogProps) => {
|
||||||
|
const [selectedCustomer, setSelectedCustomer] = useState<CustomerSelectionOption | undefined>(
|
||||||
|
undefined
|
||||||
|
);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const handleSelect = (customer: CustomerSelectionOption) => {
|
||||||
|
setSelectedCustomer((prev) => (prev?.id === customer.id ? undefined : customer));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleConfirm = () => {
|
||||||
|
if (selectedCustomer) {
|
||||||
|
ctrl.selectCustomer(selectedCustomer);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog onOpenChange={(open) => !open && ctrl.closeDialog()} open={ctrl.isOpen}>
|
<Dialog onOpenChange={(open) => !open && ctrl.closeDialog()} open={ctrl.isOpen}>
|
||||||
<DialogContent className="flex max-h-[85vh] flex-col sm:max-w-3xl">
|
<DialogContent className="flex max-h-[85vh] flex-col sm:max-w-3xl">
|
||||||
@ -80,60 +70,23 @@ export const SelectCustomerDialog = ({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="min-h-0 flex-1 overflow-hidden">
|
<div className="min-h-0 flex-1 overflow-hidden">
|
||||||
<CustomerSelectionList
|
<SelectCustomerSelectionList
|
||||||
customers={ctrl.customers}
|
customers={ctrl.customers}
|
||||||
isLoading={ctrl.isLoading}
|
isLoading={ctrl.isLoading}
|
||||||
onSelect={ctrl.selectCustomer}
|
onSelect={handleSelect}
|
||||||
|
selectedCustomer={selectedCustomer}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<DialogFooter className="gap-2">
|
||||||
|
<Button onClick={ctrl.closeDialog} variant="outline">
|
||||||
|
Cancelar
|
||||||
|
</Button>
|
||||||
|
<Button disabled={ctrl.isLoading || !selectedCustomer} onClick={handleConfirm}>
|
||||||
|
{selectedCustomer ? "Confirmar selección" : "Seleccionar cliente"}
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
type CustomerSelectionListProps = {
|
|
||||||
customers: CustomerSelectionOption[];
|
|
||||||
isLoading: boolean;
|
|
||||||
onSelect: (customer: CustomerSelectionOption) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
const CustomerSelectionList = ({ customers, isLoading, onSelect }: CustomerSelectionListProps) => {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
//const columns = useCustomersGridColumns({});
|
|
||||||
|
|
||||||
if (isLoading) {
|
|
||||||
return (
|
|
||||||
<div className="space-y-2 py-2">
|
|
||||||
<div className="h-14 rounded-md border" />
|
|
||||||
<div className="h-14 rounded-md border" />
|
|
||||||
<div className="h-14 rounded-md border" />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (customers.length === 0) {
|
|
||||||
return <SelectCustomerEmptyCard />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ItemGroup>
|
|
||||||
{customers.map((customer) => (
|
|
||||||
<Item
|
|
||||||
asChild
|
|
||||||
className={cn("bg-muted/50 font-medium transition hover:text-primary hover:bg-muted")}
|
|
||||||
key={customer.id}
|
|
||||||
onClick={() => onSelect(customer)}
|
|
||||||
role="listitem"
|
|
||||||
>
|
|
||||||
<a href="#" rel="noopener noreferrer" target="_blank">
|
|
||||||
<ItemContent>
|
|
||||||
<ItemTitle className="line-clamp-1">{customer.name}</ItemTitle>
|
|
||||||
<ItemDescription>{customer.tin}</ItemDescription>
|
|
||||||
</ItemContent>
|
|
||||||
</a>
|
|
||||||
</Item>
|
|
||||||
))}
|
|
||||||
</ItemGroup>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|||||||
@ -0,0 +1,77 @@
|
|||||||
|
import { InitialsAvatar } from "@repo/rdx-ui/components";
|
||||||
|
import {
|
||||||
|
Item,
|
||||||
|
ItemContent,
|
||||||
|
ItemDescription,
|
||||||
|
ItemGroup,
|
||||||
|
ItemMedia,
|
||||||
|
ItemTitle,
|
||||||
|
} from "@repo/shadcn-ui/components";
|
||||||
|
import { cn } from "@repo/shadcn-ui/lib/utils";
|
||||||
|
|
||||||
|
import { useTranslation } from "../../../../../web/i18n";
|
||||||
|
import type { CustomerSelectionOption } from "../../entities";
|
||||||
|
|
||||||
|
import { SelectCustomerEmptyCard } from "./select-customer-empty-card";
|
||||||
|
|
||||||
|
type SelectCustomerSelectionListProps = {
|
||||||
|
customers: CustomerSelectionOption[];
|
||||||
|
isLoading: boolean;
|
||||||
|
selectedCustomer?: CustomerSelectionOption;
|
||||||
|
onSelect: (customer: CustomerSelectionOption) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SelectCustomerSelectionList = ({
|
||||||
|
customers,
|
||||||
|
isLoading,
|
||||||
|
selectedCustomer,
|
||||||
|
onSelect,
|
||||||
|
}: SelectCustomerSelectionListProps) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
//const columns = useCustomersGridColumns({});
|
||||||
|
console.log(selectedCustomer);
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return (
|
||||||
|
<div className="space-y-2 py-2">
|
||||||
|
<div className="h-14 rounded-md border" />
|
||||||
|
<div className="h-14 rounded-md border" />
|
||||||
|
<div className="h-14 rounded-md border" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (customers.length === 0) {
|
||||||
|
return <SelectCustomerEmptyCard />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ItemGroup>
|
||||||
|
{customers.map((customer) => (
|
||||||
|
<Item
|
||||||
|
className={cn(
|
||||||
|
"cursor-pointer",
|
||||||
|
customer.id === selectedCustomer?.id && "border-primary bg-accent"
|
||||||
|
)}
|
||||||
|
key={customer.id}
|
||||||
|
onClick={() => onSelect(customer)}
|
||||||
|
role="listitem"
|
||||||
|
variant={"outline"}
|
||||||
|
>
|
||||||
|
<ItemMedia>
|
||||||
|
<InitialsAvatar
|
||||||
|
name={customer.name}
|
||||||
|
variant={customer.id === selectedCustomer?.id ? "primary" : "muted"}
|
||||||
|
/>
|
||||||
|
</ItemMedia>
|
||||||
|
|
||||||
|
<ItemContent>
|
||||||
|
<ItemTitle className="line-clamp-1">{customer.name}</ItemTitle>
|
||||||
|
<ItemDescription>{customer.tin}</ItemDescription>
|
||||||
|
</ItemContent>
|
||||||
|
</Item>
|
||||||
|
))}
|
||||||
|
</ItemGroup>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -1,24 +1,14 @@
|
|||||||
import { Avatar, AvatarFallback, Badge } from "@repo/shadcn-ui/components";
|
import { InitialsAvatar } from "@repo/rdx-ui/components";
|
||||||
|
import { Badge } from "@repo/shadcn-ui/components";
|
||||||
import { Building2Icon, CopyIcon, UserIcon } from "lucide-react";
|
import { Building2Icon, CopyIcon, UserIcon } from "lucide-react";
|
||||||
|
|
||||||
import type { Customer } from "../../../../shared";
|
import type { Customer } from "../../../../shared";
|
||||||
import { Initials } from "../../components";
|
|
||||||
|
|
||||||
export const CustomerHeader = ({ customer }: { customer: Customer }) => {
|
export const CustomerHeader = ({ customer }: { customer: Customer }) => {
|
||||||
return (
|
return (
|
||||||
<div className="p-4">
|
<div className="p-4">
|
||||||
<div className="flex items-start gap-4">
|
<div className="flex items-start gap-4">
|
||||||
<Avatar className="size-10 border-2 border-background shadow-sm">
|
<InitialsAvatar name={customer.name} />
|
||||||
<AvatarFallback
|
|
||||||
className={
|
|
||||||
customer.status === "active"
|
|
||||||
? "bg-blue-100 text-blue-700"
|
|
||||||
: "bg-muted text-muted-foreground"
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Initials name={customer.name} />
|
|
||||||
</AvatarFallback>
|
|
||||||
</Avatar>
|
|
||||||
|
|
||||||
<div className="min-w-0 flex-1">
|
<div className="min-w-0 flex-1">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
import { safeHTTPUrl } from "@erp/core/client";
|
import { safeHTTPUrl } from "@erp/core/client";
|
||||||
import { DataTableColumnHeader } from "@repo/rdx-ui/components";
|
import { DataTableColumnHeader, InitialsAvatar } from "@repo/rdx-ui/components";
|
||||||
import {
|
import {
|
||||||
Avatar,
|
|
||||||
AvatarFallback,
|
|
||||||
Badge,
|
Badge,
|
||||||
Button,
|
Button,
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
@ -18,7 +16,7 @@ import * as React from "react";
|
|||||||
|
|
||||||
import { useTranslation } from "../../../../i18n";
|
import { useTranslation } from "../../../../i18n";
|
||||||
import type { CustomerListRow } from "../../../../shared";
|
import type { CustomerListRow } from "../../../../shared";
|
||||||
import { AddressCell, ContactCell, Initials } from "../../components";
|
import { AddressCell, ContactCell } from "../../components";
|
||||||
|
|
||||||
type GridActionHandlers = {
|
type GridActionHandlers = {
|
||||||
onEditClick?: (customer: CustomerListRow) => void;
|
onEditClick?: (customer: CustomerListRow) => void;
|
||||||
@ -58,17 +56,7 @@ export function useCustomersGridColumns(
|
|||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
<div className="flex items-start gap-3">
|
<div className="flex items-start gap-3">
|
||||||
<Avatar className="size-10 border-2 border-background shadow-sm">
|
<InitialsAvatar name={customer.name} variant="primary" />
|
||||||
<AvatarFallback
|
|
||||||
className={
|
|
||||||
customer.status === "active"
|
|
||||||
? "bg-blue-100 text-blue-700"
|
|
||||||
: "bg-muted text-muted-foreground"
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Initials name={customer.name} />
|
|
||||||
</AvatarFallback>
|
|
||||||
</Avatar>
|
|
||||||
|
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
export * from "./address-cell";
|
export * from "./address-cell";
|
||||||
export * from "./contact-cell";
|
export * from "./contact-cell";
|
||||||
export * from "./initials";
|
|
||||||
export * from "./kind-badge";
|
export * from "./kind-badge";
|
||||||
export * from "./soft";
|
export * from "./soft";
|
||||||
|
|||||||
@ -1,4 +0,0 @@
|
|||||||
export const Initials = ({ name }: { name: string }) => {
|
|
||||||
const parts = name.trim().split(/\s+/).slice(0, 2);
|
|
||||||
return <> {parts.map((p) => p[0]?.toUpperCase() ?? "").join("") || "?"} </>;
|
|
||||||
};
|
|
||||||
Loading…
Reference in New Issue
Block a user