Facturas de cliente
This commit is contained in:
parent
3b16556f84
commit
a5af168e6b
@ -1,5 +1,12 @@
|
||||
{
|
||||
"common": {},
|
||||
"common": {
|
||||
"append_empty_row": "Append row",
|
||||
"append_empty_row_tooltip": "Append a empty row",
|
||||
"duplicate_row": "Duplicate",
|
||||
"insert_row_above": "Insert row above",
|
||||
"insert_row_below": "Insert row below",
|
||||
"remove_row": "Remove"
|
||||
},
|
||||
"pages": {
|
||||
"title": "Customer invoices",
|
||||
"description": "Manage your customer invoices",
|
||||
@ -45,6 +52,16 @@
|
||||
"placeholder": "",
|
||||
"description": ""
|
||||
},
|
||||
"issue_date": {
|
||||
"label": "Date",
|
||||
"placeholder": "Select a date",
|
||||
"description": "Invoice issue date"
|
||||
},
|
||||
"operation_date": {
|
||||
"label": "Operation date",
|
||||
"placeholder": "Select a date",
|
||||
"description": "Invoice operation date"
|
||||
},
|
||||
"items": {
|
||||
"quantity": {
|
||||
"label": "Quantity",
|
||||
|
||||
@ -1,5 +1,12 @@
|
||||
{
|
||||
"common": {},
|
||||
"common": {
|
||||
"append_empty_row": "Añadir fila",
|
||||
"append_empty_row_tooltip": "Añadir una fila vacía",
|
||||
"duplicate_row": "Duplicar fila",
|
||||
"insert_row_above": "Insertar fila encima",
|
||||
"insert_row_below": "Insertar fila debajo",
|
||||
"remove_row": "Eliminar"
|
||||
},
|
||||
"pages": {
|
||||
"title": "Facturas",
|
||||
"description": "Gestiona tus facturas",
|
||||
@ -45,6 +52,16 @@
|
||||
"placeholder": "",
|
||||
"description": ""
|
||||
},
|
||||
"issue_date": {
|
||||
"label": "Fecha",
|
||||
"placeholder": "Seleccionar una fecha",
|
||||
"description": "Fecha de emisión de la factura"
|
||||
},
|
||||
"operation_date": {
|
||||
"label": "Intervención",
|
||||
"placeholder": "Seleccionar una fecha",
|
||||
"description": "Fecha de intervención de los trabajos"
|
||||
},
|
||||
"items": {
|
||||
"quantity": {
|
||||
"label": "Cantidad",
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
import { Button } from "@repo/shadcn-ui/components";
|
||||
import { t } from "i18next";
|
||||
import { PackagePlusIcon } from "lucide-react";
|
||||
import { JSX, forwardRef } from "react";
|
||||
|
||||
export interface AppendBlockRowButtonProps extends React.ComponentProps<typeof Button> {
|
||||
label?: string;
|
||||
}
|
||||
|
||||
export const AppendBlockRowButton = forwardRef<HTMLButtonElement, AppendBlockRowButtonProps>(
|
||||
(
|
||||
{ label = t("common.append_block"), className, ...props }: AppendBlockRowButtonProps,
|
||||
ref
|
||||
): JSX.Element => (
|
||||
<Button type='button' variant='outline' ref={ref} {...props}>
|
||||
{" "}
|
||||
<PackagePlusIcon className={label ? "w-4 h-4 mr-2" : "w-4 h-4"} />
|
||||
{label && <>{label}</>}
|
||||
</Button>
|
||||
)
|
||||
);
|
||||
|
||||
AppendBlockRowButton.displayName = "AppendBlockRowButton";
|
||||
@ -1,26 +0,0 @@
|
||||
import { Button } from "@repo/shadcn-ui/components";
|
||||
import { t } from "i18next";
|
||||
import { PackagePlusIcon } from "lucide-react";
|
||||
import { JSX, forwardRef } from "react";
|
||||
|
||||
export interface AppendCatalogArticleRowButtonProps extends React.ComponentProps<typeof Button> {
|
||||
label?: string;
|
||||
}
|
||||
|
||||
export const AppendCatalogArticleRowButton = forwardRef<
|
||||
HTMLButtonElement,
|
||||
AppendCatalogArticleRowButtonProps
|
||||
>(
|
||||
(
|
||||
{ label = t("common.append_article"), className, ...props }: AppendCatalogArticleRowButtonProps,
|
||||
ref
|
||||
): JSX.Element => (
|
||||
<Button type='button' variant='outline' ref={ref} {...props}>
|
||||
{" "}
|
||||
<PackagePlusIcon className={label ? "w-4 h-4 mr-2" : "w-4 h-4"} />
|
||||
{label && <>{label}</>}
|
||||
</Button>
|
||||
)
|
||||
);
|
||||
|
||||
AppendCatalogArticleRowButton.displayName = "AppendCatalogArticleRowButton";
|
||||
@ -1,7 +1,8 @@
|
||||
import { Button } from "@repo/shadcn-ui/components";
|
||||
import { t } from "i18next";
|
||||
import { PlusCircleIcon } from "lucide-react";
|
||||
import { JSX, forwardRef } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { MODULE_NAME } from "../../manifest";
|
||||
|
||||
export interface AppendEmptyRowButtonProps extends React.ComponentProps<typeof Button> {
|
||||
label?: string;
|
||||
@ -9,15 +10,17 @@ export interface AppendEmptyRowButtonProps extends React.ComponentProps<typeof B
|
||||
}
|
||||
|
||||
export const AppendEmptyRowButton = forwardRef<HTMLButtonElement, AppendEmptyRowButtonProps>(
|
||||
(
|
||||
{ label = t("common.append_empty_row"), className, ...props }: AppendEmptyRowButtonProps,
|
||||
ref
|
||||
): JSX.Element => (
|
||||
<Button type='button' variant='outline' ref={ref} {...props}>
|
||||
<PlusCircleIcon className={label ? "w-4 h-4 mr-2" : "w-4 h-4"} />
|
||||
{label && <>{label}</>}
|
||||
</Button>
|
||||
)
|
||||
({ label, className, ...props }: AppendEmptyRowButtonProps, ref): JSX.Element => {
|
||||
const { t } = useTranslation(MODULE_NAME);
|
||||
const _label = label || t("common.append_empty_row");
|
||||
|
||||
return (
|
||||
<Button type='button' variant='outline' ref={ref} {...props}>
|
||||
<PlusCircleIcon className={_label ? "w-4 h-4 mr-2" : "w-4 h-4"} />
|
||||
{_label && <>{_label}</>}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
AppendEmptyRowButton.displayName = "AppendEmptyRowButton";
|
||||
|
||||
@ -1,3 +1 @@
|
||||
export * from "./append-block-row-button";
|
||||
export * from "./append-catalog-article-row-button";
|
||||
export * from "./append-empty-row-button";
|
||||
|
||||
@ -76,7 +76,7 @@ export const CustomerInvoiceItemsCardEditor = ({
|
||||
{
|
||||
id: "description" as const,
|
||||
accessorKey: "description",
|
||||
header: t("customer_invoices.form_fields.description.label"),
|
||||
header: t("form_fields.items.description.label"),
|
||||
cell: ({ row: { index, original } }) => (
|
||||
<FormField
|
||||
control={control}
|
||||
@ -85,7 +85,7 @@ export const CustomerInvoiceItemsCardEditor = ({
|
||||
<FormItem className='md:col-span-2'>
|
||||
<FormControl>
|
||||
<Textarea
|
||||
placeholder={t("customer_invoices.form_fields.description.placeholder")}
|
||||
placeholder={t("form_fields.items.description.placeholder")}
|
||||
{...field}
|
||||
/>
|
||||
</FormControl>
|
||||
@ -100,9 +100,7 @@ export const CustomerInvoiceItemsCardEditor = ({
|
||||
{
|
||||
id: "quantity" as const,
|
||||
accessorKey: "quantity",
|
||||
header: () => (
|
||||
<div className='text-right'>{t("customer_invoices.form_fields.quantity.label")}</div>
|
||||
),
|
||||
header: () => <div className='text-right'>{t("form_fields.items.quantity.label")}</div>,
|
||||
cell: ({ row: { index } }) => (
|
||||
<FormField
|
||||
control={control}
|
||||
@ -129,11 +127,7 @@ export const CustomerInvoiceItemsCardEditor = ({
|
||||
{
|
||||
id: "unit_price" as const,
|
||||
accessorKey: "unit_price",
|
||||
header: () => (
|
||||
<div className='text-right'>
|
||||
{t("customer_invoices.form_fields.items.unit_price.label")}
|
||||
</div>
|
||||
),
|
||||
header: () => <div className='text-right'>{t("form_fields.items.unit_price.label")}</div>,
|
||||
cell: ({ row: { index } }) => (
|
||||
<FormField
|
||||
control={control}
|
||||
@ -161,9 +155,7 @@ export const CustomerInvoiceItemsCardEditor = ({
|
||||
id: "subtotal_price" as const,
|
||||
accessorKey: "subtotal_price",
|
||||
header: () => (
|
||||
<div className='text-right'>
|
||||
{t("customer_invoices.form_fields.items.subtotal_price.label")}
|
||||
</div>
|
||||
<div className='text-right'>{t("form_fields.items.subtotal_price.label")}</div>
|
||||
),
|
||||
cell: ({ row: { index } }) => {
|
||||
/*return (
|
||||
@ -184,11 +176,7 @@ export const CustomerInvoiceItemsCardEditor = ({
|
||||
{
|
||||
id: "discount" as const,
|
||||
accessorKey: "discount",
|
||||
header: () => (
|
||||
<div className='text-right'>
|
||||
{t("customer_invoices.form_fields.items.discount.label")}
|
||||
</div>
|
||||
),
|
||||
header: () => <div className='text-right'>{t("form_fields.items.discount.label")}</div>,
|
||||
cell: ({ row: { index } }) => (
|
||||
<FormField
|
||||
control={control}
|
||||
@ -216,11 +204,7 @@ export const CustomerInvoiceItemsCardEditor = ({
|
||||
{
|
||||
id: "total_price" as const,
|
||||
accessorKey: "total_price",
|
||||
header: () => (
|
||||
<div className='text-right'>
|
||||
{t("customer_invoices.form_fields.items.total_price.label")}
|
||||
</div>
|
||||
),
|
||||
header: () => <div className='text-right'>{t("form_fields.items.total_price.label")}</div>,
|
||||
cell: ({ row: { index } }) => (
|
||||
<>
|
||||
{formatCurrency(
|
||||
@ -324,8 +308,6 @@ export const CustomerInvoiceItemsCardEditor = ({
|
||||
const defaultLayout = [265, 440, 655];
|
||||
const navCollapsedSize = 4;
|
||||
|
||||
console.log(columns);
|
||||
|
||||
return (
|
||||
<div className='relative'>
|
||||
<CustomerInvoiceItemsSortableDataTable
|
||||
|
||||
@ -8,11 +8,7 @@ import {
|
||||
import { Table } from "@tanstack/react-table";
|
||||
import { t } from "i18next";
|
||||
import { CopyPlusIcon, ScanIcon, Trash2Icon } from "lucide-react";
|
||||
import {
|
||||
AppendBlockRowButton,
|
||||
AppendCatalogArticleRowButton,
|
||||
AppendEmptyRowButton,
|
||||
} from "../buttons";
|
||||
import { AppendEmptyRowButton } from "../buttons";
|
||||
|
||||
export const CustomerInvoiceItemsSortableDataTableToolbar = ({ table }: { table: Table<any> }) => {
|
||||
const selectedRowsCount = table.getSelectedRowModel().rows.length;
|
||||
@ -84,32 +80,6 @@ export const CustomerInvoiceItemsSortableDataTableToolbar = ({ table }: { table:
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{t("common.append_empty_row_tooltip")}</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<AppendCatalogArticleRowButton
|
||||
variant='link'
|
||||
onClick={() => {
|
||||
if (table.options.meta && table.options.meta.pickCatalogArticle) {
|
||||
table.options.meta?.pickCatalogArticle();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{t("common.append_article_tooltip")}</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<AppendBlockRowButton
|
||||
variant='link'
|
||||
onClick={() => {
|
||||
if (table.options.meta && table.options.meta.pickBlock) {
|
||||
table.options.meta?.pickBlock();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{t("common.append_block_tooltip")}</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className='flex items-center gap-2 ml-auto' />
|
||||
</nav>
|
||||
|
||||
@ -48,11 +48,7 @@ import {
|
||||
import { useMemo, useState } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import { FieldValues, UseFieldArrayReturn } from "react-hook-form";
|
||||
import {
|
||||
AppendBlockRowButton,
|
||||
AppendCatalogArticleRowButton,
|
||||
AppendEmptyRowButton,
|
||||
} from "../buttons";
|
||||
import { AppendEmptyRowButton } from "../buttons";
|
||||
import { CustomerInvoiceItemsSortableDataTableToolbar } from "./customer-invoice-items-sortable-datatable-toolbar";
|
||||
import { CustomerInvoiceItemsSortableTableRow } from "./customer-invoice-items-sortable-table-row";
|
||||
|
||||
@ -509,20 +505,6 @@ export function CustomerInvoiceItemsSortableDataTable<
|
||||
<CardFooter>
|
||||
<ButtonGroup>
|
||||
<AppendEmptyRowButton onClick={() => table.options.meta?.appendItem()} />
|
||||
<AppendCatalogArticleRowButton
|
||||
onClick={() => {
|
||||
if (table.options.meta && table.options.meta.pickCatalogArticle) {
|
||||
table.options.meta?.pickCatalogArticle();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<AppendBlockRowButton
|
||||
onClick={() => {
|
||||
if (table.options.meta && table.options.meta.pickBlock) {
|
||||
table.options.meta?.pickBlock();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</ButtonGroup>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
@source "./components";
|
||||
@source "./pages";
|
||||
@ -4,7 +4,7 @@ import * as z from "zod";
|
||||
|
||||
import { ClientSelector } from "@erp/customers/components";
|
||||
|
||||
import { formatDate } from "@erp/core/client";
|
||||
import { DatePickerField } from "@repo/rdx-ui/components";
|
||||
import {
|
||||
Button,
|
||||
Calendar,
|
||||
@ -264,254 +264,68 @@ export const CustomerInvoiceEditForm = ({
|
||||
return (
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(handleSubmit, handleError)} className='grid gap-6'>
|
||||
{/* Cliente */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Cliente</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className='grid grid-cols-1 gap-4 space-y-6'>
|
||||
<ClientSelector />
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='customer_id'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>ID Cliente</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder='ID del cliente' {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Información básica */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Información Básica</CardTitle>
|
||||
<CardDescription>Detalles generales de la factura</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className='grid grid-cols-1 gap-4 space-y-6'>
|
||||
<div className='grid grid-cols-1'>
|
||||
<ClientSelector />
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='customer_id'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>ID Cliente</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder='ID del cliente' {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className='grid grid-cols-4'>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='invoice_number'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("form_fields.invoice_number.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder='1' {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='issue_date'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Fecha de Emisión</FormLabel>
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<FormControl>
|
||||
<Button
|
||||
variant='outline'
|
||||
className='w-full justify-start text-left font-normal'
|
||||
>
|
||||
<CalendarIcon className='mr-2 h-4 w-4' />
|
||||
{field.value ? formatDate(field.value) : "Seleccionar fecha"}
|
||||
</Button>
|
||||
</FormControl>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className='w-auto p-0'>
|
||||
<Calendar
|
||||
mode='single'
|
||||
selected={field.value ? new Date(field.value) : undefined}
|
||||
onSelect={(date) => field.onChange(date?.toISOString())}
|
||||
initialFocus
|
||||
/>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='invoice_series'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Serie</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder='A' {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='invoice_status'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Estado</FormLabel>
|
||||
<Select onValueChange={field.onChange} defaultValue={field.value}>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder='Seleccionar estado' />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value='draft'>Borrador</SelectItem>
|
||||
<SelectItem value='sent'>Enviada</SelectItem>
|
||||
<SelectItem value='paid'>Pagada</SelectItem>
|
||||
<SelectItem value='cancelled'>Cancelada</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='operation_date'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Fecha de Operación</FormLabel>
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<FormControl>
|
||||
<Button
|
||||
variant='outline'
|
||||
className='w-full justify-start text-left font-normal'
|
||||
>
|
||||
<CalendarIcon className='mr-2 h-4 w-4' />
|
||||
{field.value ? formatDate(field.value) : "Seleccionar fecha"}
|
||||
</Button>
|
||||
</FormControl>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className='w-auto p-0'>
|
||||
<Calendar
|
||||
mode='single'
|
||||
selected={field.value ? new Date(field.value) : undefined}
|
||||
onSelect={(date) => field.onChange(date?.toISOString())}
|
||||
initialFocus
|
||||
/>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='operation_date'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Inicio periodo de facturación</FormLabel>
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<FormControl>
|
||||
<Button
|
||||
variant='outline'
|
||||
className='w-full justify-start text-left font-normal'
|
||||
>
|
||||
<CalendarIcon className='mr-2 h-4 w-4' />
|
||||
{field.value ? formatDate(field.value) : "Seleccionar fecha"}
|
||||
</Button>
|
||||
</FormControl>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className='w-auto p-0'>
|
||||
<Calendar
|
||||
mode='single'
|
||||
selected={field.value ? new Date(field.value) : undefined}
|
||||
onSelect={(date) => field.onChange(date?.toISOString())}
|
||||
initialFocus
|
||||
/>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='operation_date'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Fin periodo de facturación</FormLabel>
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<FormControl>
|
||||
<Button
|
||||
variant='outline'
|
||||
className='w-full justify-start text-left font-normal'
|
||||
>
|
||||
<CalendarIcon className='mr-2 h-4 w-4' />
|
||||
{field.value ? formatDate(field.value) : "Seleccionar fecha"}
|
||||
</Button>
|
||||
</FormControl>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className='w-auto p-0'>
|
||||
<Calendar
|
||||
mode='single'
|
||||
selected={field.value ? new Date(field.value) : undefined}
|
||||
onSelect={(date) => field.onChange(date?.toISOString())}
|
||||
initialFocus
|
||||
/>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<CardContent className='grid gap-6 md:grid-cols-6'>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='language_code'
|
||||
name='invoice_number'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Idioma</FormLabel>
|
||||
<Select onValueChange={field.onChange} defaultValue={field.value}>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder='Seleccionar idioma' />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value='ES'>Español</SelectItem>
|
||||
<SelectItem value='EN'>English</SelectItem>
|
||||
<SelectItem value='FR'>Français</SelectItem>
|
||||
<SelectItem value='DE'>Deutsch</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormLabel>{t("form_fields.invoice_number.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("form_fields.invoice_number.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<DatePickerField
|
||||
control={form.control}
|
||||
name='issue_date'
|
||||
required
|
||||
label={t("form_fields.issue_date.label")}
|
||||
placeholder={t("form_fields.issue_date.placeholder")}
|
||||
description={t("form_fields.issue_date.description")}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='currency'
|
||||
name='invoice_series'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Moneda</FormLabel>
|
||||
<Select onValueChange={field.onChange} defaultValue={field.value}>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder='Seleccionar moneda' />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value='EUR'>EUR</SelectItem>
|
||||
<SelectItem value='USD'>USD</SelectItem>
|
||||
<SelectItem value='GBP'>GBP</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormLabel>Serie</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder='A' {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
@source "./components";
|
||||
@source "./pages";
|
||||
@ -14,6 +14,13 @@
|
||||
"./locales/*": "./src/locales/*",
|
||||
"./hooks/*": ["./src/hooks/*.tsx", "./src/hooks/*.ts"]
|
||||
},
|
||||
"peerDependencies": {
|
||||
"date-fns": "^4.1.0",
|
||||
"i18next": "^25.1.1",
|
||||
"react-hook-form": "^7.58.1",
|
||||
"typescript": "^5.8.3",
|
||||
"zod": "^3.25.67"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "1.9.4",
|
||||
"@repo/typescript-config": "workspace:*",
|
||||
@ -40,7 +47,6 @@
|
||||
"@repo/shadcn-ui": "workspace:*",
|
||||
"@tanstack/react-table": "^8.21.3",
|
||||
"esbuild-raw-plugin": "^0.2.0",
|
||||
"i18next": "^25.0.2",
|
||||
"lucide-react": "^0.503.0",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
|
||||
89
packages/rdx-ui/src/components/form/DatePickerField.tsx
Normal file
89
packages/rdx-ui/src/components/form/DatePickerField.tsx
Normal file
@ -0,0 +1,89 @@
|
||||
// DatePickerField.tsx
|
||||
|
||||
import {
|
||||
Button,
|
||||
Calendar,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@repo/shadcn-ui/components";
|
||||
import { CalendarIcon } from "lucide-react";
|
||||
|
||||
import { useTranslation } from "@repo/rdx-ui/locales/i18n.ts";
|
||||
import { cn } from "@repo/shadcn-ui/lib/utils";
|
||||
import { format } from "date-fns";
|
||||
import { Control, FieldPath, FieldValues } from "react-hook-form";
|
||||
|
||||
type DatePickerFieldProps<TFormValues extends FieldValues> = {
|
||||
control: Control<TFormValues>;
|
||||
name: FieldPath<TFormValues>;
|
||||
label: string;
|
||||
placeholder?: string;
|
||||
description?: string;
|
||||
disabled?: boolean;
|
||||
required?: boolean;
|
||||
className?: string;
|
||||
formatDateFn?: (iso: string) => string;
|
||||
};
|
||||
|
||||
export function DatePickerField<TFormValues extends FieldValues>({
|
||||
control,
|
||||
name,
|
||||
label,
|
||||
placeholder,
|
||||
description,
|
||||
disabled = false,
|
||||
required = false,
|
||||
className,
|
||||
formatDateFn = (iso) => format(new Date(iso), "dd/MM/yyyy"),
|
||||
}: DatePickerFieldProps<TFormValues>) {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<FormField
|
||||
control={control}
|
||||
name={name}
|
||||
render={({ field }) => (
|
||||
<FormItem className={cn("space-y-2", className)}>
|
||||
<div className='flex justify-between items-center'>
|
||||
<FormLabel className='m-0'>{label}</FormLabel>
|
||||
{required && <span className='text-xs text-destructive'>{t("common.required")}</span>}
|
||||
</div>{" "}
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<FormControl>
|
||||
<Button
|
||||
variant='outline'
|
||||
disabled={disabled}
|
||||
className={cn(
|
||||
"w-full justify-start text-left font-normal",
|
||||
!field.value && "text-muted-foreground"
|
||||
)}
|
||||
>
|
||||
<CalendarIcon className='mr-2 h-4 w-4' />
|
||||
{field.value ? formatDateFn(field.value) : placeholder}
|
||||
</Button>
|
||||
</FormControl>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className='w-auto p-0'>
|
||||
<Calendar
|
||||
mode='single'
|
||||
selected={field.value ? new Date(field.value) : undefined}
|
||||
onSelect={(date) => field.onChange(date?.toISOString())}
|
||||
initialFocus
|
||||
/>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<p className={cn("text-xs text-muted-foreground", !description && "invisible")}>
|
||||
{description || "\u00A0"}
|
||||
</p>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
1
packages/rdx-ui/src/components/form/index.tsx
Normal file
1
packages/rdx-ui/src/components/form/index.tsx
Normal file
@ -0,0 +1 @@
|
||||
export * from "./DatePickerField.tsx";
|
||||
@ -2,6 +2,7 @@ export * from "./buttons/index.tsx";
|
||||
export * from "./custom-dialog.tsx";
|
||||
export * from "./datatable/index.tsx";
|
||||
export * from "./error-overlay.tsx";
|
||||
export * from "./form/index.tsx";
|
||||
export * from "./layout/index.tsx";
|
||||
export * from "./loading-overlay/index.tsx";
|
||||
export * from "./scroll-to-top.tsx";
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
"use client";
|
||||
|
||||
export const PACKAGE_NAME = "rdx-ui";
|
||||
export * from "./components/index.tsx";
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
{
|
||||
"common": {
|
||||
"required": "required"
|
||||
},
|
||||
"components": {
|
||||
"loading_indicator": {
|
||||
"title": "Loading..."
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
{
|
||||
"common": {
|
||||
"required": "obligatorio"
|
||||
},
|
||||
"components": {
|
||||
"LoadingIndicator": {
|
||||
"title": "Cargando..."
|
||||
|
||||
14
packages/rdx-ui/src/locales/i18n.ts
Normal file
14
packages/rdx-ui/src/locales/i18n.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import i18next from "i18next";
|
||||
import { useTranslation as useTrans } from "react-i18next";
|
||||
import { PACKAGE_NAME } from "../index.ts";
|
||||
import enResources from "./en.json" with { type: "json" };
|
||||
import esResources from "./es.json" with { type: "json" };
|
||||
|
||||
export const useTranslation = () => {
|
||||
if (!i18next.hasLoadedNamespace(PACKAGE_NAME)) {
|
||||
i18next.addResourceBundle("en", PACKAGE_NAME, enResources, true, true);
|
||||
i18next.addResourceBundle("es", PACKAGE_NAME, esResources, true, true);
|
||||
}
|
||||
|
||||
return useTrans(PACKAGE_NAME);
|
||||
};
|
||||
@ -0,0 +1 @@
|
||||
@source "../components";
|
||||
@ -5,8 +5,9 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* https://www.windpalette.com/app
|
||||
|
||||
https://themecn.dev/api/registry/eyJsIjp7ImJnIjoiMCwwLDEwMCIsImZnIjoiMjE5LDEwLDQiLCJwIjoiMjE5LDgzLDU4IiwicyI6IjIxOSwyMyw5NiIsImEiOiIyMDUsMTAwLDY3IiwiZCI6IjM1Ny4xOCwxMDAsNDUifSwiciI6MC41fQ==
|
||||
https://themecn.dev/dashboard?theme=eyJsIjp7ImJnIjoiMCwwLDEwMCIsImZnIjoiMjI2LDEwLDQiLCJwIjoiMjI2LDEwMCw1NSIsInMiOiIyMjYsMjUsOTUiLCJhIjoiMjI2LDEwMCw4NSIsImQiOiIzNTcuMTgsMTAwLDQ1In0sImYiOlsiTGF0byIsIlBvcHBpbnMiXSwiciI6MC41fQ==
|
||||
|
||||
**/
|
||||
|
||||
@ -48,149 +49,115 @@
|
||||
--magenta-950: #660031;
|
||||
}
|
||||
|
||||
:root {
|
||||
--background: oklch(0.9911 0 0);
|
||||
--foreground: oklch(0.2046 0 0);
|
||||
--card: oklch(0.9911 0 0);
|
||||
--card-foreground: oklch(0.2046 0 0);
|
||||
--popover: oklch(0.9911 0 0);
|
||||
--popover-foreground: oklch(0.4386 0 0);
|
||||
--primary: var(--sapphire-600);
|
||||
--primary-foreground: var(--sapphire-50);
|
||||
--secondary: var(--graphite-600);
|
||||
--secondary-foreground: var(--graphite-50);
|
||||
--muted: oklch(0.9461 0 0);
|
||||
--muted-foreground: oklch(0.2435 0 0);
|
||||
--accent: var(--magenta-60);
|
||||
--accent-foreground: var(--magenta-50);
|
||||
--destructive: oklch(0.5795 0.2369 28.4251);
|
||||
--destructive-foreground: oklch(0.9934 0.0032 17.2118);
|
||||
--border: var(--graphite-300);
|
||||
--input: var(--graphite-300);
|
||||
--ring: var(--sapphire-500);
|
||||
--chart-1: oklch(0.6202 0.1561 261.2713);
|
||||
--chart-2: oklch(0.6611 0.1491 261.8026);
|
||||
--chart-3: oklch(0.7537 0.1098 262.1599);
|
||||
--chart-4: oklch(0.4174 0.1322 261.2301);
|
||||
--chart-5: oklch(0.3372 0.0777 261.8039);
|
||||
--sidebar: var(--graphite-800);
|
||||
--sidebar-foreground: var(--graphite-50);
|
||||
--sidebar-primary: var(--sapphire-500);
|
||||
--sidebar-primary-foreground: var(--graphite-900);
|
||||
--sidebar-accent: var(--graphite-200);
|
||||
--sidebar-accent-foreground: var(--graphite-700);
|
||||
--sidebar-border: var(--graphite-200);
|
||||
--sidebar-ring: var(--sapphire-500);
|
||||
--font-sans: Geist, sans-serif;
|
||||
--font-serif: Merriweather, serif;
|
||||
--font-mono: Geist Mono, monospace;
|
||||
--radius: 0.5rem;
|
||||
--shadow-2xs: 0px 1px 3px 0px hsl(0 0% 0% / 0.09);
|
||||
--shadow-xs: 0px 1px 3px 0px hsl(0 0% 0% / 0.09);
|
||||
--shadow-sm: 0px 1px 3px 0px hsl(0 0% 0% / 0.17), 0px 1px 2px -1px hsl(0 0% 0% / 0.17);
|
||||
--shadow: 0px 1px 3px 0px hsl(0 0% 0% / 0.17), 0px 1px 2px -1px hsl(0 0% 0% / 0.17);
|
||||
--shadow-md: 0px 1px 3px 0px hsl(0 0% 0% / 0.17), 0px 2px 4px -1px hsl(0 0% 0% / 0.17);
|
||||
--shadow-lg: 0px 1px 3px 0px hsl(0 0% 0% / 0.17), 0px 4px 6px -1px hsl(0 0% 0% / 0.17);
|
||||
--shadow-xl: 0px 1px 3px 0px hsl(0 0% 0% / 0.17), 0px 8px 10px -1px hsl(0 0% 0% / 0.17);
|
||||
--shadow-2xl: 0px 1px 3px 0px hsl(0 0% 0% / 0.43);
|
||||
--tracking-normal: 0em;
|
||||
--spacing: 0.25rem;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: oklch(0.1822 0 0);
|
||||
--foreground: oklch(0.9288 0.0126 255.5078);
|
||||
--card: oklch(0.2046 0 0);
|
||||
--card-foreground: oklch(0.9288 0.0126 255.5078);
|
||||
--popover: oklch(0.2603 0 0);
|
||||
--popover-foreground: oklch(0.7348 0 0);
|
||||
--primary: oklch(0.4365 0.1044 156.7556);
|
||||
--primary-foreground: oklch(0.9213 0.0135 167.1556);
|
||||
--secondary: oklch(0.2603 0 0);
|
||||
--secondary-foreground: oklch(0.9851 0 0);
|
||||
--muted: oklch(0.2393 0 0);
|
||||
--muted-foreground: oklch(0.7122 0 0);
|
||||
--accent: oklch(0.3132 0 0);
|
||||
--accent-foreground: oklch(0.9851 0 0);
|
||||
--destructive: oklch(0.3123 0.0852 29.7877);
|
||||
--destructive-foreground: oklch(0.9368 0.0045 34.3092);
|
||||
--border: oklch(0.2809 0 0);
|
||||
--input: oklch(0.2603 0 0);
|
||||
--ring: oklch(0.8003 0.1821 151.711);
|
||||
--chart-1: oklch(0.8003 0.1821 151.711);
|
||||
--chart-2: oklch(0.7137 0.1434 254.624);
|
||||
--chart-3: oklch(0.709 0.1592 293.5412);
|
||||
--chart-4: oklch(0.8369 0.1644 84.4286);
|
||||
--chart-5: oklch(0.7845 0.1325 181.912);
|
||||
--sidebar: oklch(0.1822 0 0);
|
||||
--sidebar-foreground: oklch(0.6301 0 0);
|
||||
--sidebar-primary: oklch(0.4365 0.1044 156.7556);
|
||||
--sidebar-primary-foreground: oklch(0.9213 0.0135 167.1556);
|
||||
--sidebar-accent: oklch(0.3132 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.9851 0 0);
|
||||
--sidebar-border: oklch(0.2809 0 0);
|
||||
--sidebar-ring: oklch(0.8003 0.1821 151.711);
|
||||
@theme inline {
|
||||
--font-sans: Geist, sans-serif;
|
||||
--font-serif: Merriweather, serif;
|
||||
--font-mono: "Geist Mono", monospace;
|
||||
--radius: 0.5rem;
|
||||
--shadow-2xs: 0px 1px 3px 0px hsl(0 0% 0% / 0.09);
|
||||
--shadow-xs: 0px 1px 3px 0px hsl(0 0% 0% / 0.09);
|
||||
--shadow-sm: 0px 1px 3px 0px hsl(0 0% 0% / 0.17), 0px 1px 2px -1px hsl(0 0% 0% / 0.17);
|
||||
--shadow: 0px 1px 3px 0px hsl(0 0% 0% / 0.17), 0px 1px 2px -1px hsl(0 0% 0% / 0.17);
|
||||
--shadow-md: 0px 1px 3px 0px hsl(0 0% 0% / 0.17), 0px 2px 4px -1px hsl(0 0% 0% / 0.17);
|
||||
--shadow-lg: 0px 1px 3px 0px hsl(0 0% 0% / 0.17), 0px 4px 6px -1px hsl(0 0% 0% / 0.17);
|
||||
--shadow-xl: 0px 1px 3px 0px hsl(0 0% 0% / 0.17), 0px 8px 10px -1px hsl(0 0% 0% / 0.17);
|
||||
--shadow-2xl: 0px 1px 3px 0px hsl(0 0% 0% / 0.43);
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--color-card: var(--card);
|
||||
--color-card-foreground: var(--card-foreground);
|
||||
--color-popover: var(--popover);
|
||||
--color-popover-foreground: var(--popover-foreground);
|
||||
--color-primary: var(--primary);
|
||||
--color-primary-foreground: var(--primary-foreground);
|
||||
--color-secondary: var(--secondary);
|
||||
--color-secondary-foreground: var(--secondary-foreground);
|
||||
--color-muted: var(--muted);
|
||||
--color-muted-foreground: var(--muted-foreground);
|
||||
--color-accent: var(--accent);
|
||||
--color-accent-foreground: var(--accent-foreground);
|
||||
--color-destructive: var(--destructive);
|
||||
--color-destructive-foreground: var(--destructive-foreground);
|
||||
--color-border: var(--border);
|
||||
--color-input: var(--input);
|
||||
--color-ring: var(--ring);
|
||||
--color-chart-1: var(--chart-1);
|
||||
--color-chart-2: var(--chart-2);
|
||||
--color-chart-3: var(--chart-3);
|
||||
--color-chart-4: var(--chart-4);
|
||||
--color-chart-5: var(--chart-5);
|
||||
--color-sidebar: var(--sidebar);
|
||||
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||
--color-sidebar-primary: var(--sidebar-primary);
|
||||
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
||||
--color-sidebar-accent: var(--sidebar-accent);
|
||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||
--color-sidebar-border: var(--sidebar-border);
|
||||
--color-sidebar-ring: var(--sidebar-ring);
|
||||
|
||||
--color-sidebar-border: var(--sidebar-border);
|
||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||
--color-sidebar-accent: var(--sidebar-accent);
|
||||
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
||||
--color-sidebar-primary: var(--sidebar-primary);
|
||||
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||
--color-sidebar: var(--sidebar);
|
||||
--color-chart-5: var(--chart-5);
|
||||
--color-chart-4: var(--chart-4);
|
||||
--color-chart-3: var(--chart-3);
|
||||
--color-chart-2: var(--chart-2);
|
||||
--color-chart-1: var(--chart-1);
|
||||
--color-ring: var(--ring);
|
||||
--color-input: var(--input);
|
||||
--color-border: var(--border);
|
||||
--color-destructive: var(--destructive);
|
||||
--color-accent-foreground: var(--accent-foreground);
|
||||
--color-accent: var(--accent);
|
||||
--color-muted-foreground: var(--muted-foreground);
|
||||
--color-muted: var(--muted);
|
||||
--color-secondary-foreground: var(--secondary-foreground);
|
||||
--color-secondary: var(--secondary);
|
||||
--color-primary-foreground: var(--primary-foreground);
|
||||
--color-primary: var(--primary);
|
||||
--color-popover-foreground: var(--popover-foreground);
|
||||
--color-popover: var(--popover);
|
||||
--color-card-foreground: var(--card-foreground);
|
||||
--color-card: var(--card);
|
||||
--radius-sm: calc(var(--radius) - 4px);
|
||||
--radius-md: calc(var(--radius) - 2px);
|
||||
--radius-lg: var(--radius);
|
||||
--radius-xl: calc(var(--radius) + 4px);
|
||||
}
|
||||
|
||||
--shadow-2xs: var(--shadow-2xs);
|
||||
--shadow-xs: var(--shadow-xs);
|
||||
--shadow-sm: var(--shadow-sm);
|
||||
--shadow: var(--shadow);
|
||||
--shadow-md: var(--shadow-md);
|
||||
--shadow-lg: var(--shadow-lg);
|
||||
--shadow-xl: var(--shadow-xl);
|
||||
--shadow-2xl: var(--shadow-2xl);
|
||||
:root {
|
||||
--radius: 0.5rem;
|
||||
--background: oklch(1.0 0.0 0);
|
||||
--foreground: oklch(0.143 0.003 271.9282674829111);
|
||||
--card: oklch(1.0 0.0 0);
|
||||
--card-foreground: oklch(0.143 0.003 271.9282674829111);
|
||||
--popover: oklch(1.0 0.0 0);
|
||||
--popover-foreground: oklch(0.143 0.003 271.9282674829111);
|
||||
--primary: oklch(0.527 0.263 264.6358829854314);
|
||||
--primary-foreground: oklch(0.96 0.003 272.6281326778613);
|
||||
--secondary: oklch(0.957 0.007 272.5840410480741);
|
||||
--secondary-foreground: oklch(0.2 0.024 271.03952637990255);
|
||||
--muted: oklch(0.957 0.007 272.5840410480741);
|
||||
--muted-foreground: oklch(0.501 0.087 270.1873691459851);
|
||||
--accent: oklch(0.893 0.011 270.0165724649083);
|
||||
--accent-foreground: oklch(0.194 0.039 267.55460547761646);
|
||||
--destructive: oklch(0.58 0.237 28.43022926835137);
|
||||
--border: oklch(0.87 0.021 272.39716219522893);
|
||||
--input: oklch(0.87 0.021 272.39716219522893);
|
||||
--ring: oklch(0.527 0.263 264.6358829854314);
|
||||
--chart-1: oklch(0.527 0.263 264.6358829854314);
|
||||
--chart-2: oklch(0.587 0.17 268.089554204009);
|
||||
--chart-3: oklch(0.698 0.107 270.5337309213311);
|
||||
--chart-4: oklch(0.344 0.167 264.8096356890612);
|
||||
--chart-5: oklch(0.265 0.121 265.17321408623843);
|
||||
--sidebar: oklch(0.957 0.007 272.5840410480741);
|
||||
--sidebar-foreground: oklch(0.2 0.024 271.03952637990255);
|
||||
--sidebar-primary: oklch(0.527 0.263 264.6358829854314);
|
||||
--sidebar-primary-foreground: oklch(0.96 0.003 272.6281326778613);
|
||||
--sidebar-accent: oklch(0.893 0.011 270.0165724649083);
|
||||
--sidebar-accent-foreground: oklch(0.194 0.039 267.55460547761646);
|
||||
--sidebar-border: oklch(0.87 0.021 272.39716219522893);
|
||||
--sidebar-ring: oklch(0.527 0.263 264.6358829854314);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: oklch(0.18 0.02 271.2071690195347);
|
||||
--foreground: oklch(0.96 0.003 272.6281326778613);
|
||||
--card: oklch(0.219 0.028 270.9064636444989);
|
||||
--card-foreground: oklch(0.96 0.003 272.6281326778613);
|
||||
--popover: oklch(0.219 0.028 270.9064636444989);
|
||||
--popover-foreground: oklch(0.96 0.003 272.6281326778613);
|
||||
--primary: oklch(0.572 0.216 266.49817452939124);
|
||||
--primary-foreground: oklch(0.96 0.003 272.6281326778613);
|
||||
--secondary: oklch(0.297 0.037 271.01211769802813);
|
||||
--secondary-foreground: oklch(0.956 0.008 272.5689802513852);
|
||||
--muted: oklch(0.297 0.037 271.01211769802813);
|
||||
--muted-foreground: oklch(0.703 0.031 272.154700569603);
|
||||
--accent: oklch(0.645 0.061 269.1114142997618);
|
||||
--accent-foreground: oklch(0.953 0.013 270.00473513692674);
|
||||
--destructive: oklch(0.58 0.237 28.43022926835137);
|
||||
--border: oklch(0.38 0.062 270.35456036349854);
|
||||
--input: oklch(0.38 0.062 270.35456036349854);
|
||||
--ring: oklch(0.572 0.216 266.49817452939124);
|
||||
--chart-1: oklch(0.572 0.216 266.49817452939124);
|
||||
--chart-2: oklch(0.628 0.168 268.4986758327506);
|
||||
--chart-3: oklch(0.728 0.124 270.22825208762697);
|
||||
--chart-4: oklch(0.388 0.15 266.35164847353985);
|
||||
--chart-5: oklch(0.32 0.089 268.3276964633901);
|
||||
--sidebar: oklch(0.293 0.044 270.5701620578212);
|
||||
--sidebar-foreground: oklch(0.96 0.003 272.6281326778613);
|
||||
--sidebar-primary: oklch(0.572 0.216 266.49817452939124);
|
||||
--sidebar-primary-foreground: oklch(0.96 0.003 272.6281326778613);
|
||||
--sidebar-accent: oklch(0.645 0.061 269.1114142997618);
|
||||
--sidebar-accent-foreground: oklch(0.953 0.013 270.00473513692674);
|
||||
--sidebar-border: oklch(0.38 0.062 270.35456036349854);
|
||||
--sidebar-ring: oklch(0.572 0.216 266.49817452939124);
|
||||
}
|
||||
|
||||
@layer base {
|
||||
|
||||
@ -173,7 +173,7 @@ importers:
|
||||
version: 29.7.0(@types/node@22.15.32)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.15.32)(typescript@5.8.3))
|
||||
ts-jest:
|
||||
specifier: ^29.2.5
|
||||
version: 29.4.0(@babel/core@7.27.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.4))(jest-util@29.7.0)(jest@29.7.0(@types/node@22.15.32)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.15.32)(typescript@5.8.3)))(typescript@5.8.3)
|
||||
version: 29.4.0(@babel/core@7.27.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.4))(esbuild@0.25.5)(jest-util@29.7.0)(jest@29.7.0(@types/node@22.15.32)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.15.32)(typescript@5.8.3)))(typescript@5.8.3)
|
||||
tsconfig-paths:
|
||||
specifier: ^4.2.0
|
||||
version: 4.2.0
|
||||
@ -712,11 +712,14 @@ importers:
|
||||
'@tanstack/react-table':
|
||||
specifier: ^8.21.3
|
||||
version: 8.21.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
date-fns:
|
||||
specifier: ^4.1.0
|
||||
version: 4.1.0
|
||||
esbuild-raw-plugin:
|
||||
specifier: ^0.2.0
|
||||
version: 0.2.0
|
||||
i18next:
|
||||
specifier: ^25.0.2
|
||||
specifier: ^25.1.1
|
||||
version: 25.2.1(typescript@5.8.3)
|
||||
lucide-react:
|
||||
specifier: ^0.503.0
|
||||
@ -727,6 +730,9 @@ importers:
|
||||
react-dom:
|
||||
specifier: ^19.1.0
|
||||
version: 19.1.0(react@19.1.0)
|
||||
react-hook-form:
|
||||
specifier: ^7.58.1
|
||||
version: 7.58.1(react@19.1.0)
|
||||
react-i18next:
|
||||
specifier: ^15.5.1
|
||||
version: 15.5.3(i18next@25.2.1(typescript@5.8.3))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3)
|
||||
@ -11828,7 +11834,7 @@ snapshots:
|
||||
|
||||
ts-interface-checker@0.1.13: {}
|
||||
|
||||
ts-jest@29.4.0(@babel/core@7.27.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.4))(jest-util@29.7.0)(jest@29.7.0(@types/node@22.15.32)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.15.32)(typescript@5.8.3)))(typescript@5.8.3):
|
||||
ts-jest@29.4.0(@babel/core@7.27.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.4))(esbuild@0.25.5)(jest-util@29.7.0)(jest@29.7.0(@types/node@22.15.32)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.15.32)(typescript@5.8.3)))(typescript@5.8.3):
|
||||
dependencies:
|
||||
bs-logger: 0.2.6
|
||||
ejs: 3.1.10
|
||||
@ -11846,6 +11852,7 @@ snapshots:
|
||||
'@jest/transform': 29.7.0
|
||||
'@jest/types': 29.6.3
|
||||
babel-jest: 29.7.0(@babel/core@7.27.4)
|
||||
esbuild: 0.25.5
|
||||
jest-util: 29.7.0
|
||||
|
||||
ts-node@10.9.2(@types/node@22.15.32)(typescript@5.8.3):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user