diff --git a/src/app/(routes)/ledgers/[id]/accounts/accounts-tab-content.tsx b/src/app/(routes)/ledgers/[id]/accounts/accounts-tab-content.tsx
index e74e63ca..f3ac0054 100644
--- a/src/app/(routes)/ledgers/[id]/accounts/accounts-tab-content.tsx
+++ b/src/app/(routes)/ledgers/[id]/accounts/accounts-tab-content.tsx
@@ -19,6 +19,7 @@ import useCustomToast from '@/hooks/use-custom-toast'
import { AccountType } from '@/types/accounts-type'
import { AccountSheet } from './accounts-sheet'
import { AccountsDataTable } from './accounts-data-table'
+import { EntityDataTable } from '@/components/entity-data-table'
export const AccountsTabContent = () => {
const intl = useIntl()
@@ -223,16 +224,33 @@ export const AccountsTabContent = () => {
- {accountsList && (
-
- )}
+
+ {accountsList && (
+
+ )}
+
+
+ {intl.formatMessage(
+ {
+ id: 'ledgers.accounts.showing',
+ defaultMessage:
+ 'Showing {count} {number, plural, =0 {accounts} one {account} other {accounts}}.'
+ },
+ {
+ number: accountsList?.length,
+ count: {accountsList?.length}
+ }
+ )}
+
+
+
)
}
diff --git a/src/app/(routes)/ledgers/[id]/assets/assets-tab-content.tsx b/src/app/(routes)/ledgers/[id]/assets/assets-tab-content.tsx
index 513f787a..b6013332 100644
--- a/src/app/(routes)/ledgers/[id]/assets/assets-tab-content.tsx
+++ b/src/app/(routes)/ledgers/[id]/assets/assets-tab-content.tsx
@@ -20,6 +20,7 @@ import { useParams } from 'next/navigation'
import { useConfirmDialog } from '@/components/confirmation-dialog/use-confirm-dialog'
import ConfirmationDialog from '@/components/confirmation-dialog'
import useCustomToast from '@/hooks/use-custom-toast'
+import { EntityDataTable } from '@/components/entity-data-table'
type AssetsTabContentProps = {
data: ILedgerType
@@ -142,18 +143,38 @@ export const AssetsTabContent = ({ data }: AssetsTabContentProps) => {
- {isLoading &&
}
+
+ {isLoading && }
- {assets && (
-
- )}
+ {assets && (
+
+ )}
+
+
+
+ {intl.formatMessage(
+ {
+ id: 'ledgers.assets.showing',
+ defaultMessage:
+ 'Showing {count} {number, plural, =0 {assets} one {asset} other {assets}}.'
+ },
+ {
+ number: assets?.items?.length,
+ count: (
+ {assets?.items?.length}
+ )
+ }
+ )}
+
+
+
{
const intl = useIntl()
- const { currentOrganization } = useOrganization()
+
const { activeTab, handleTabChange } = useTabs({
initialValue: DEFAULT_TAB_VALUE
})
- const { formData, isDirty, resetForm } = useFormState()
- const { showSuccess, showError } = useCustomToast()
- const [isDrawerOpen, setIsDrawerOpen] = useState(false)
-
- const { mutate: updateLedger, isPending: updatePending } = useUpdateLedger({
- organizationId: currentOrganization!.id!,
- ledgerId: data?.id!,
- onSuccess: () => {
- setIsDrawerOpen(false)
- resetForm()
- showSuccess(
- intl.formatMessage({
- id: 'ledgers.toast.update.success',
- defaultMessage: 'Ledger changes saved successfully'
- })
- )
- },
- onError: () => {
- showError(
- intl.formatMessage({
- id: 'ledgers.toast.update.error',
- defaultMessage: 'Error updating Ledger'
- })
- )
- }
- })
-
- useEffect(() => {
- setIsDrawerOpen(isDirty)
- }, [isDirty])
const breadcrumbPaths = getBreadcrumbPaths([
{
@@ -117,25 +82,12 @@ const LedgerDetailsView = ({ data }: LedgerDetailsViewProps) => {
}
])
- const handleGlobalSubmit = async () => {
- const dataToSend = {
- ...formData
- }
-
- updateLedger(dataToSend)
- }
-
- const handleCancel = () => {
- setIsDrawerOpen(false)
- resetForm()
- }
-
if (!data) {
return
}
return (
-
+
@@ -211,13 +163,6 @@ const LedgerDetailsView = ({ data }: LedgerDetailsViewProps) => {
-
-
)
}
diff --git a/src/app/(routes)/ledgers/[id]/overview/overview-tab-content.tsx b/src/app/(routes)/ledgers/[id]/overview/overview-tab-content.tsx
index 54731e22..a09c4d72 100644
--- a/src/app/(routes)/ledgers/[id]/overview/overview-tab-content.tsx
+++ b/src/app/(routes)/ledgers/[id]/overview/overview-tab-content.tsx
@@ -1,6 +1,30 @@
-import { Card } from '@/components/card'
+import { InputField, MetadataField } from '@/components/form'
+import { Button } from '@/components/ui/button'
+import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { ILedgerType } from '@/types/ledgers-type'
+import { ExternalLink, Github, LifeBuoy } from 'lucide-react'
+import { useForm } from 'react-hook-form'
import { useIntl } from 'react-intl'
+import { SaveSheet } from './save-sheet'
+import { useUpdateLedger } from '@/client/ledgers'
+import { useOrganization } from '@/context/organization-provider/organization-provider-client'
+import useCustomToast from '@/hooks/use-custom-toast'
+import { z } from 'zod'
+import { ledger } from '@/schema/ledger'
+import { zodResolver } from '@hookform/resolvers/zod'
+import { Form } from '@/components/ui/form'
+
+const initialValues = {
+ name: '',
+ metadata: {}
+}
+
+const formSchema = z.object({
+ name: ledger.name,
+ metadata: ledger.metadata
+})
+
+type FormSchema = z.infer
type OverviewTabContentProps = {
data: ILedgerType
@@ -8,38 +32,151 @@ type OverviewTabContentProps = {
export const OverviewTabContent = ({ data }: OverviewTabContentProps) => {
const intl = useIntl()
+ const { currentOrganization } = useOrganization()
- return (
-
-
-
-
+ const { showSuccess, showError } = useCustomToast()
-
-
+ const form = useForm
({
+ resolver: zodResolver(formSchema),
+ defaultValues: {
+ ...initialValues,
+ ...data
+ }
+ })
-
-
-
-
+ const { mutate: updateLedger, isPending: updatePending } = useUpdateLedger({
+ organizationId: currentOrganization!.id!,
+ ledgerId: data?.id!,
+ onSuccess: () => {
+ showSuccess(
+ intl.formatMessage({
+ id: 'ledgers.toast.update.success',
+ defaultMessage: 'Ledger changes saved successfully'
+ })
+ )
+ },
+ onError: () => {
+ showError(
+ intl.formatMessage({
+ id: 'ledgers.toast.update.error',
+ defaultMessage: 'Error updating Ledger'
+ })
+ )
+ }
+ })
-
-
+ const handleSubmit = async (values: FormSchema) => {
+ updateLedger(values)
+ form.reset(values)
+ }
+
+ const handleCancel = () => {
+ form.reset()
+ }
-
-
+ return (
+
+
)
}
diff --git a/src/components/bottom-drawer.tsx b/src/app/(routes)/ledgers/[id]/overview/save-sheet.tsx
similarity index 56%
rename from src/components/bottom-drawer.tsx
rename to src/app/(routes)/ledgers/[id]/overview/save-sheet.tsx
index dc64f8b4..ffa1aebf 100644
--- a/src/components/bottom-drawer.tsx
+++ b/src/app/(routes)/ledgers/[id]/overview/save-sheet.tsx
@@ -1,49 +1,47 @@
+import { Button } from '@/components/ui/button'
+import { LoadingButton } from '@/components/ui/loading-button'
import { cn } from '@/lib/utils'
-import { Button } from './ui/button'
-import { useSidebar } from './sidebar/primitive'
import { useIntl } from 'react-intl'
-import { LoadingButton } from './ui/loading-button'
-interface BottomDrawerProps {
- isOpen: boolean
- isPending: boolean
- handleSubmit: () => void
- handleCancel: () => void
+export type SaveSheetProps = {
+ open?: boolean
+ loading?: boolean
+ onSubmit?: () => void
+ onCancel?: () => void
}
-export const BottomDrawer = ({
- isOpen,
- handleCancel,
- handleSubmit,
- isPending
-}: BottomDrawerProps) => {
+export const SaveSheet = ({
+ open = true,
+ loading,
+ onSubmit,
+ onCancel
+}: SaveSheetProps) => {
const intl = useIntl()
- const { isCollapsed } = useSidebar()
return (
{intl.formatMessage({
id: 'common.saveChanges',
defaultMessage: 'Save changes'
})}
-
+
{intl.formatMessage({
id: 'common.cancel',
defaultMessage: 'Cancel'
diff --git a/src/app/(routes)/ledgers/[id]/overview/total-amount-card.tsx b/src/app/(routes)/ledgers/[id]/overview/total-amount-card.tsx
deleted file mode 100644
index 4e4a6656..00000000
--- a/src/app/(routes)/ledgers/[id]/overview/total-amount-card.tsx
+++ /dev/null
@@ -1,37 +0,0 @@
-import { Card } from '@/components/card'
-import { Skeleton } from '@/components/ui/skeleton'
-import { Coins } from 'lucide-react'
-
-type ChartData = {
- instrumentCode: string
- totalAmount: string
-}
-
-export const TotalAmountCard = ({
- isLoading,
- data
-}: {
- isLoading: boolean
- data: any
-}) =>
- isLoading ? (
-
-
-
-
-
- ) : (
- data.map((instrument: ChartData, index: number) => (
-
-
-
-
- ))
- )
diff --git a/src/app/(routes)/ledgers/[id]/overview/transaction-card.tsx b/src/app/(routes)/ledgers/[id]/overview/transaction-card.tsx
deleted file mode 100644
index 389de9d0..00000000
--- a/src/app/(routes)/ledgers/[id]/overview/transaction-card.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import { Card } from '@/components/card'
-import { Skeleton } from '@/components/ui/skeleton'
-import { ArrowUpRight } from 'lucide-react'
-
-export const TransactionCard = ({
- isLoading,
- count
-}: {
- isLoading: boolean
- count: number
-}) =>
- isLoading ? (
-
- ) : (
-
-
-
-
- )
diff --git a/src/app/(routes)/ledgers/[id]/overview/transaction-status-card.tsx b/src/app/(routes)/ledgers/[id]/overview/transaction-status-card.tsx
deleted file mode 100644
index 95ca13cd..00000000
--- a/src/app/(routes)/ledgers/[id]/overview/transaction-status-card.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import { Card } from '@/components/card'
-import { Skeleton } from '@/components/ui/skeleton'
-import { BarChart } from 'lucide-react'
-
-export const TransactionStatusCard = ({
- isLoading,
- chartData
-}: {
- isLoading: boolean
- chartData: any
-}) =>
- isLoading ? (
-
- ) : (
-
-
-
-
- )
diff --git a/src/app/(routes)/ledgers/[id]/portfolios/portfolios-tab-content.tsx b/src/app/(routes)/ledgers/[id]/portfolios/portfolios-tab-content.tsx
index 985f47ec..38ea91a8 100644
--- a/src/app/(routes)/ledgers/[id]/portfolios/portfolios-tab-content.tsx
+++ b/src/app/(routes)/ledgers/[id]/portfolios/portfolios-tab-content.tsx
@@ -46,6 +46,7 @@ import {
} from '@/components/ui/tooltip'
import useCustomToast from '@/hooks/use-custom-toast'
import { Arrow } from '@radix-ui/react-tooltip'
+import { EntityDataTable } from '@/components/entity-data-table'
export const PortfoliosTabContent = () => {
const intl = useIntl()
@@ -164,172 +165,194 @@ export const PortfoliosTabContent = () => {
- {!isNil(portfoliosData?.items) && portfoliosData?.items.length > 0 && (
-
-
-
-
-
- {intl.formatMessage({
- id: 'common.id',
- defaultMessage: 'ID'
- })}
-
-
- {intl.formatMessage({
- id: 'common.name',
- defaultMessage: 'Name'
- })}
-
-
- {intl.formatMessage({
- id: 'common.metadata',
- defaultMessage: 'Metadata'
- })}
-
-
- {intl.formatMessage({
- id: 'common.accounts',
- defaultMessage: 'Accounts'
- })}
-
-
- {intl.formatMessage({
- id: 'common.actions',
- defaultMessage: 'Actions'
- })}
-
-
-
-
- {table.getRowModel().rows.map((portfolio) => {
- const metadataCount = Object.entries(
- portfolio.original.metadata || []
- ).length
- const displayId =
- portfolio.original.id && portfolio.original.id.length > 8
- ? `${truncateString(portfolio.original.id, 8)}`
- : portfolio.original.id
+
+ {!isNil(portfoliosData?.items) && portfoliosData?.items.length > 0 && (
+
+
+
+
+
+ {intl.formatMessage({
+ id: 'common.id',
+ defaultMessage: 'ID'
+ })}
+
+
+ {intl.formatMessage({
+ id: 'common.name',
+ defaultMessage: 'Name'
+ })}
+
+
+ {intl.formatMessage({
+ id: 'common.metadata',
+ defaultMessage: 'Metadata'
+ })}
+
+
+ {intl.formatMessage({
+ id: 'common.accounts',
+ defaultMessage: 'Accounts'
+ })}
+
+
+ {intl.formatMessage({
+ id: 'common.actions',
+ defaultMessage: 'Actions'
+ })}
+
+
+
+
+ {table.getRowModel().rows.map((portfolio) => {
+ const metadataCount = Object.entries(
+ portfolio.original.metadata || []
+ ).length
+ const displayId =
+ portfolio.original.id && portfolio.original.id.length > 8
+ ? `${truncateString(portfolio.original.id, 8)}`
+ : portfolio.original.id
- return (
-
-
-
-
-
- handleCopyToClipboard(
- portfolio.original.id,
- intl.formatMessage({
- id: 'ledgers.toast.copyId',
- defaultMessage:
- 'The id has been copied to your clipboard.'
- })
- )
+ return (
+
+
+
+
+
+ handleCopyToClipboard(
+ portfolio.original.id,
+ intl.formatMessage({
+ id: 'ledgers.toast.copyId',
+ defaultMessage:
+ 'The id has been copied to your clipboard.'
+ })
+ )
+ }
+ >
+
+ {displayId}
+
+
+
+
+ {portfolio.original.id}
+
+
+ {intl.formatMessage({
+ id: 'ledgers.columnsTable.tooltipCopyText',
+ defaultMessage: 'Click to copy'
+ })}
+
+
+
+
+
+
+ {portfolio.original.name}
+
+ {metadataCount === 0 ? (
+
+ ) : (
+ intl.formatMessage(
+ {
+ id: 'common.table.metadata',
+ defaultMessage:
+ '{number, plural, =0 {-} one {# record} other {# records}}'
+ },
+ {
+ number: metadataCount
}
- >
-
- {displayId}
-
-
-
-
- {portfolio.original.id}
-
-
- {intl.formatMessage({
- id: 'ledgers.columnsTable.tooltipCopyText',
- defaultMessage: 'Click to copy'
- })}
-
-
-
-
-
-
- {portfolio.original.name}
-
- {metadataCount === 0 ? (
-
- ) : (
- intl.formatMessage(
+ )
+ )}
+
+
+ {intl.formatMessage(
{
- id: 'common.table.metadata',
+ id: 'common.table.accounts',
defaultMessage:
- '{number, plural, =0 {-} one {# record} other {# records}}'
+ '{number, plural, =0 {No accounts} one {# account} other {# accounts}}'
},
{
- number: metadataCount
+ number: portfolio.original.accounts?.length || 0
}
- )
- )}
-
-
- {intl.formatMessage(
- {
- id: 'common.table.accounts',
- defaultMessage:
- '{number, plural, =0 {No accounts} one {# account} other {# accounts}}'
- },
- {
- number: portfolio.original.accounts?.length || 0
- }
- )}
-
+ )}
+
-
-
-
-
- {}} />
-
-
-
-
- handleEdit({
- ...portfolio.original,
- entityId: portfolio.original.id,
- status: {
- ...portfolio.original.status,
- description:
- portfolio.original.status.description ?? ''
- }
- } as PortfolioResponseDto)
- }
- >
- {intl.formatMessage({
- id: `common.edit`,
- defaultMessage: 'Edit'
- })}
-
-
- {
- handleDialogOpen(portfolio?.original?.id!)
- }}
- >
- {intl.formatMessage({
- id: `common.delete`,
- defaultMessage: 'Delete'
- })}
-
-
-
-
-
+
+
+
+
+ {}} />
+
+
+
+
+ handleEdit({
+ ...portfolio.original,
+ entityId: portfolio.original.id,
+ status: {
+ ...portfolio.original.status,
+ description:
+ portfolio.original.status.description ??
+ ''
+ }
+ } as PortfolioResponseDto)
+ }
+ >
+ {intl.formatMessage({
+ id: `common.edit`,
+ defaultMessage: 'Edit'
+ })}
+
+
+ {
+ handleDialogOpen(portfolio?.original?.id!)
+ }}
+ >
+ {intl.formatMessage({
+ id: `common.delete`,
+ defaultMessage: 'Delete'
+ })}
+
+
+
+
+
+ )
+ })}
+
+
+
+ )}
+
+
+ {intl.formatMessage(
+ {
+ id: 'ledgers.portfolios.showing',
+ defaultMessage:
+ 'Showing {count} {number, plural, =0 {portfolios} one {portifolio} other {portfolios}}.'
+ },
+ {
+ number: portfoliosData?.items?.length,
+ count: (
+
+ {portfoliosData?.items?.length}
+
)
- })}
-
-
-
- )}
+ }
+ )}
+
+
+
>
)
}
diff --git a/src/app/(routes)/ledgers/[id]/products/products-tab-content.tsx b/src/app/(routes)/ledgers/[id]/products/products-tab-content.tsx
index fd0d67bf..84b92ca8 100644
--- a/src/app/(routes)/ledgers/[id]/products/products-tab-content.tsx
+++ b/src/app/(routes)/ledgers/[id]/products/products-tab-content.tsx
@@ -35,6 +35,7 @@ import {
} from '@tanstack/react-table'
import { useOrganization } from '@/context/organization-provider/organization-provider-client'
import { useParams } from 'next/navigation'
+import { EntityDataTable } from '@/components/entity-data-table'
export const ProductsTabContent = () => {
const intl = useIntl()
@@ -127,106 +128,127 @@ export const ProductsTabContent = () => {
- {isNil(data?.items) ||
- (data?.items.length === 0 && (
-
- }>
- {intl.formatMessage({
- id: 'common.create',
- defaultMessage: 'Create'
+
+ {isNil(data?.items) ||
+ (data?.items.length === 0 && (
+
-
- ))}
+ >
+ }>
+ {intl.formatMessage({
+ id: 'common.create',
+ defaultMessage: 'Create'
+ })}
+
+
+ ))}
- {!isNil(data?.items) && data?.items.length > 0 && (
-
-
-
-
-
- {intl.formatMessage({
- id: 'common.id',
- defaultMessage: 'ID'
- })}
-
-
- {intl.formatMessage({
- id: 'common.name',
- defaultMessage: 'Name'
- })}
-
-
- {intl.formatMessage({
- id: 'common.metadata',
- defaultMessage: 'Metadata'
- })}
-
-
- {intl.formatMessage({
- id: 'common.actions',
- defaultMessage: 'Actions'
- })}
-
-
-
-
- {table.getRowModel().rows.map((product) => (
-
- {product.original.id}
- {product.original.name}
-
- {intl.formatMessage(
- {
- id: 'common.table.metadata',
- defaultMessage:
- '{number, plural, =0 {-} one {# record} other {# records}}'
- },
- {
- number: Object.entries(product.original.metadata || [])
- .length
- }
- )}
-
-
-
-
-
- {}} />
-
-
-
- handleEdit(product.original)}
- >
- {intl.formatMessage({
- id: `common.edit`,
- defaultMessage: 'Edit'
- })}
-
-
- handleDialogOpen(product.original.id)}
- >
- {intl.formatMessage({
- id: `common.delete`,
- defaultMessage: 'Delete'
- })}
-
-
-
-
+ {!isNil(data?.items) && data?.items.length > 0 && (
+
+
+
+
+
+ {intl.formatMessage({
+ id: 'common.id',
+ defaultMessage: 'ID'
+ })}
+
+
+ {intl.formatMessage({
+ id: 'common.name',
+ defaultMessage: 'Name'
+ })}
+
+
+ {intl.formatMessage({
+ id: 'common.metadata',
+ defaultMessage: 'Metadata'
+ })}
+
+
+ {intl.formatMessage({
+ id: 'common.actions',
+ defaultMessage: 'Actions'
+ })}
+
- ))}
-
-
-
- )}
+
+
+ {table.getRowModel().rows.map((product) => (
+
+ {product.original.id}
+ {product.original.name}
+
+ {intl.formatMessage(
+ {
+ id: 'common.table.metadata',
+ defaultMessage:
+ '{number, plural, =0 {-} one {# record} other {# records}}'
+ },
+ {
+ number: Object.entries(
+ product.original.metadata || []
+ ).length
+ }
+ )}
+
+
+
+
+
+ {}} />
+
+
+
+ handleEdit(product.original)}
+ >
+ {intl.formatMessage({
+ id: `common.edit`,
+ defaultMessage: 'Edit'
+ })}
+
+
+
+ handleDialogOpen(product.original.id)
+ }
+ >
+ {intl.formatMessage({
+ id: `common.delete`,
+ defaultMessage: 'Delete'
+ })}
+
+
+
+
+
+ ))}
+
+
+
+ )}
+
+
+
+ {intl.formatMessage(
+ {
+ id: 'ledgers.products.showing',
+ defaultMessage:
+ 'Showing {count} {number, plural, =0 {products} one {product} other {products}}.'
+ },
+ {
+ number: data?.items?.length,
+ count: {data?.items?.length}
+ }
+ )}
+
+
+
>
)
}
diff --git a/src/app/(routes)/ledgers/[id]/total-amount-card.tsx b/src/app/(routes)/ledgers/[id]/total-amount-card.tsx
deleted file mode 100644
index 776ebb4e..00000000
--- a/src/app/(routes)/ledgers/[id]/total-amount-card.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import { Card } from '@/components/card'
-import { Skeleton } from '@/components/ui/skeleton'
-import { Coins } from 'lucide-react'
-
-type ChartData = {
- instrumentCode: string
- totalAmount: string
-}
-
-export const TotalAmountCard = ({
- isLoading,
- data
-}: {
- isLoading: boolean
- data: any
-}) =>
- isLoading ? (
-
-
-
-
-
- ) : (
- data.map((instrument: ChartData, index: number) => (
-
-
-
-
-
- ))
- )
diff --git a/src/app/(routes)/ledgers/[id]/transaction-card.tsx b/src/app/(routes)/ledgers/[id]/transaction-card.tsx
deleted file mode 100644
index 389de9d0..00000000
--- a/src/app/(routes)/ledgers/[id]/transaction-card.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import { Card } from '@/components/card'
-import { Skeleton } from '@/components/ui/skeleton'
-import { ArrowUpRight } from 'lucide-react'
-
-export const TransactionCard = ({
- isLoading,
- count
-}: {
- isLoading: boolean
- count: number
-}) =>
- isLoading ? (
-
- ) : (
-
-
-
-
- )
diff --git a/src/app/(routes)/ledgers/[id]/transaction-status-card.tsx b/src/app/(routes)/ledgers/[id]/transaction-status-card.tsx
deleted file mode 100644
index 95ca13cd..00000000
--- a/src/app/(routes)/ledgers/[id]/transaction-status-card.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import { Card } from '@/components/card'
-import { Skeleton } from '@/components/ui/skeleton'
-import { BarChart } from 'lucide-react'
-
-export const TransactionStatusCard = ({
- isLoading,
- chartData
-}: {
- isLoading: boolean
- chartData: any
-}) =>
- isLoading ? (
-
- ) : (
-
-
-
-
- )
diff --git a/src/app/(routes)/ledgers/ledgers-data-table.tsx b/src/app/(routes)/ledgers/ledgers-data-table.tsx
index 5a5581cc..4ab27b3a 100644
--- a/src/app/(routes)/ledgers/ledgers-data-table.tsx
+++ b/src/app/(routes)/ledgers/ledgers-data-table.tsx
@@ -1,5 +1,5 @@
import React from 'react'
-import { IntlShape, useIntl } from 'react-intl'
+import { useIntl } from 'react-intl'
import {
Table,
TableBody,
@@ -35,6 +35,7 @@ import Link from 'next/link'
import { LedgerEntity } from '@/core/domain/entities/ledger-entity'
import { LedgersSheet } from './ledgers-sheet'
import { AssetsSheet } from './[id]/assets/assets-sheet'
+import { EntityDataTable } from '@/components/entity-data-table'
type LedgersTableProps = {
ledgers: { items: LedgerEntity[] }
@@ -218,7 +219,7 @@ export const LedgersDataTable: React.FC = ({
}
return (
-
+
{isNil(ledgers?.items) || ledgers.items.length === 0 ? (
= ({
)}
+
+
+ {intl.formatMessage(
+ {
+ id: 'ledgers.showing',
+ defaultMessage:
+ 'Showing {count} {number, plural, =0 {ledgers} one {ledger} other {ledgers}}.'
+ },
+ {
+ number: ledgers?.items?.length,
+ count: {ledgers?.items?.length}
+ }
+ )}
+
+
+
-
+
)
}
diff --git a/src/app/(routes)/settings/organizations-tab-content.tsx b/src/app/(routes)/settings/organizations-tab-content.tsx
index b772575b..a2d94ab9 100644
--- a/src/app/(routes)/settings/organizations-tab-content.tsx
+++ b/src/app/(routes)/settings/organizations-tab-content.tsx
@@ -31,6 +31,7 @@ import { useConfirmDialog } from '@/components/confirmation-dialog/use-confirm-d
import ConfirmationDialog from '@/components/confirmation-dialog'
import { Badge } from '@/components/ui/badge'
import { OrganizationEntity } from '@/core/domain/entities/organization-entity'
+import { EntityDataTable } from '@/components/entity-data-table'
export const OrganizationsTabContent = () => {
const intl = useIntl()
@@ -115,110 +116,127 @@ export const OrganizationsTabContent = () => {
)}
-
- {data?.items && data.items.length > 0 && (
-
-
-
-
-
- {intl.formatMessage({
- id: 'common.id',
- defaultMessage: 'ID'
- })}
-
-
- {intl.formatMessage({
- id: `entity.organization.legalName`,
- defaultMessage: 'Legal Name'
- })}
-
-
- {intl.formatMessage({
- id: `entity.organization.doingBusinessAs`,
- defaultMessage: 'Trade Name'
- })}
-
-
- {intl.formatMessage({
- id: `entity.organization.legalDocument`,
- defaultMessage: 'Document'
- })}
-
-
- {intl.formatMessage({
- id: `entity.organization.status`,
- defaultMessage: 'Status'
- })}
-
-
- {intl.formatMessage({
- id: 'common.actions',
- defaultMessage: 'Actions'
- })}
-
-
-
-
- {data.items.map((organization) => (
-
- {organization.id}
- {organization.legalName}
- {organization.doingBusinessAs}
- {organization.legalDocument}
-
-
- {organization.status.code === 'ACTIVE'
- ? intl.formatMessage({
- id: 'common.active',
- defaultMessage: 'Active'
- })
- : intl.formatMessage({
- id: 'common.inactive',
- defaultMessage: 'Inactive'
- })}
-
-
-
-
-
-
- {}} />
-
-
-
- handleEdit(organization)}
- >
- {intl.formatMessage({
- id: `common.edit`,
- defaultMessage: 'Edit'
- })}
-
-
- handleDialogOpen(organization.id!)}
- >
- {intl.formatMessage({
- id: `common.delete`,
- defaultMessage: 'Delete'
- })}
-
-
-
-
+
+ {data?.items && data.items.length > 0 && (
+
+
+
+
+
+ {intl.formatMessage({
+ id: 'common.id',
+ defaultMessage: 'ID'
+ })}
+
+
+ {intl.formatMessage({
+ id: `entity.organization.legalName`,
+ defaultMessage: 'Legal Name'
+ })}
+
+
+ {intl.formatMessage({
+ id: `entity.organization.doingBusinessAs`,
+ defaultMessage: 'Trade Name'
+ })}
+
+
+ {intl.formatMessage({
+ id: `entity.organization.legalDocument`,
+ defaultMessage: 'Document'
+ })}
+
+
+ {intl.formatMessage({
+ id: `entity.organization.status`,
+ defaultMessage: 'Status'
+ })}
+
+
+ {intl.formatMessage({
+ id: 'common.actions',
+ defaultMessage: 'Actions'
+ })}
+
- ))}
-
-
-
- )}
+
+
+ {data.items.map((organization) => (
+
+ {organization.id}
+ {organization.legalName}
+ {organization.doingBusinessAs}
+ {organization.legalDocument}
+
+
+ {organization.status.code === 'ACTIVE'
+ ? intl.formatMessage({
+ id: 'common.active',
+ defaultMessage: 'Active'
+ })
+ : intl.formatMessage({
+ id: 'common.inactive',
+ defaultMessage: 'Inactive'
+ })}
+
+
+
+
+
+
+ {}} />
+
+
+
+ handleEdit(organization)}
+ >
+ {intl.formatMessage({
+ id: `common.edit`,
+ defaultMessage: 'Edit'
+ })}
+
+
+ handleDialogOpen(organization.id!)}
+ >
+ {intl.formatMessage({
+ id: `common.delete`,
+ defaultMessage: 'Delete'
+ })}
+
+
+
+
+
+ ))}
+
+
+
+ )}
+
+
+
+ {intl.formatMessage(
+ {
+ id: 'organizations.showing',
+ defaultMessage:
+ 'Showing {count} {number, plural, =0 {organizations} one {organization} other {organizations}}.'
+ },
+ {
+ number: data?.items?.length,
+ count: {data?.items?.length}
+ }
+ )}
+
+
+
)
}
diff --git a/src/client/ledgers.ts b/src/client/ledgers.ts
index fe3b44b5..d26e4674 100644
--- a/src/client/ledgers.ts
+++ b/src/client/ledgers.ts
@@ -9,7 +9,8 @@ import {
import {
useMutation,
UseMutationOptions,
- useQuery
+ useQuery,
+ useQueryClient
} from '@tanstack/react-query'
type UseCreateLedgerProps = UseMutationOptions & {
@@ -75,13 +76,22 @@ const useLedgerById = ({
const useUpdateLedger = ({
organizationId,
ledgerId,
+ onSuccess,
...options
}: UseUpdateLedgerProps) => {
+ const queryClient = useQueryClient()
+
return useMutation
({
mutationKey: [organizationId, ledgerId],
mutationFn: patchFetcher(
`/api/organizations/${organizationId}/ledgers/${ledgerId}`
),
+ onSuccess: (...args) => {
+ queryClient.invalidateQueries({
+ queryKey: ['ledger', organizationId, ledgerId]
+ })
+ onSuccess?.(...args)
+ },
...options
})
}
diff --git a/src/components/card/card-content.tsx b/src/components/card/card-content.tsx
deleted file mode 100644
index 7674354a..00000000
--- a/src/components/card/card-content.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-'use client'
-
-import { cn } from '@/lib/utils'
-import { CardContent } from '@/components/ui/card'
-import { Input } from '@/components/ui/input'
-import { zodResolver } from '@hookform/resolvers/zod'
-import { useForm } from 'react-hook-form'
-import { z } from 'zod'
-import { useFormState } from '@/context/form-details-context'
-import { Label } from '@/components/ui/label'
-import { useIntl } from 'react-intl'
-
-const formSchema = z.object({
- name: z.string()
-})
-
-export const CustomCardContent = ({ data, text, className }: any) => {
- const { updateFormData } = useFormState()
- const intl = useIntl()
-
- const { register } = useForm>({
- resolver: zodResolver(formSchema),
- defaultValues: data ? { name: data.name } : {}
- })
-
- const handleNameChange = (e: React.ChangeEvent) => {
- const newName = e.target.value
- updateFormData({ name: newName })
- }
-
- return (
-
- {text && (
-
- {text}
-
- )}
-
- {data && (
-
-
- {intl.formatMessage({
- id: 'entity.ledger.name',
- defaultMessage: 'Ledger Name'
- })}
-
-
-
- )}
-
- )
-}
diff --git a/src/components/card/card-metadata.tsx b/src/components/card/card-metadata.tsx
deleted file mode 100644
index 092f5330..00000000
--- a/src/components/card/card-metadata.tsx
+++ /dev/null
@@ -1,167 +0,0 @@
-import React, { useState } from 'react'
-import { useForm, useFieldArray } from 'react-hook-form'
-import { zodResolver } from '@hookform/resolvers/zod'
-import { CardContent } from '@/components/ui/card'
-import { Label } from '@/components/ui/label'
-import { Input } from '@/components/ui/input'
-import { Button } from '@/components/ui/button'
-import { Plus, Trash } from 'lucide-react'
-import { cn } from '@/lib/utils'
-import { useFormState } from '@/context/form-details-context'
-import { ILedgerType } from '@/types/ledgers-type'
-import { metadata } from '@/schema/metadata'
-import { MetadataValues } from '@/types/metadata-type'
-
-type Metadata = Record
-
-type CardMetadataProps = {
- data: ILedgerType
- resetFormTrigger?: boolean
-}
-
-const convertToArray = (metadata: Metadata) => {
- return Array.isArray(metadata)
- ? metadata
- : Object.entries(metadata || {}).map(([key, value]) => ({
- key,
- value: value?.toString() || ''
- }))
-}
-
-const convertArrayToObject = (array: { key: string; value: string }[]) => {
- if (array.length === 0) {
- return null
- }
-
- return array.reduce((acc: Record, item) => {
- if (item.key && item.value) {
- acc[item.key] = item.value
- }
- return acc
- }, {})
-}
-
-export const CardMetadata = ({ data, resetFormTrigger }: CardMetadataProps) => {
- const { updateFormData } = useFormState()
- const { control, register, reset } = useForm({
- resolver: zodResolver(metadata),
- defaultValues: {
- metadata: convertToArray(data.metadata)
- }
- })
-
- const { fields, append, remove } = useFieldArray({
- control,
- name: 'metadata'
- })
-
- const [newMetadata, setNewMetadata] = useState({ key: '', value: '' })
-
- const syncMetadataWithContext = (fieldsArray: MetadataValues) => {
- const metadataObject = convertArrayToObject(fieldsArray)
- updateFormData({ metadata: metadataObject })
- }
-
- const handleFieldChange =
- (index: number, field: string) =>
- (e: React.ChangeEvent) => {
- fields[index][field] = e.target.value
- syncMetadataWithContext(fields)
- }
-
- const handleNewMetadataChange =
- (field: string) => (e: React.ChangeEvent) => {
- setNewMetadata((prev) => ({ ...prev, [field]: e.target.value }))
- }
-
- const handleAddMetadata = () => {
- if (newMetadata.key && newMetadata.value) {
- append(newMetadata)
- syncMetadataWithContext([...fields, newMetadata])
- setNewMetadata({ key: '', value: '' })
- }
- }
-
- const handleRemoveMetadata = (index: number) => {
- const updatedFields = fields.filter((_, i) => i !== index)
- remove(index)
- syncMetadataWithContext(updatedFields)
- }
-
- if (resetFormTrigger) {
- reset({
- metadata: convertToArray(data.metadata)
- })
- }
-
- return (
-
-
-
- {fields.map((item, index) => (
-
- ))}
-
- )
-}
diff --git a/src/components/card/card-resources.tsx b/src/components/card/card-resources.tsx
deleted file mode 100644
index fdb2297b..00000000
--- a/src/components/card/card-resources.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-'use client'
-
-import { ExternalLink, Github, LifeBuoy } from 'lucide-react'
-import { Button } from '../ui/button'
-
-export const CardResources = () => {
- return (
-
-
-
-
- Github
-
-
-
-
-
-
- Suporte
-
-
-
-
-
-
- CLI Docs
-
-
-
-
-
-
- Docs
-
-
-
- )
-}
diff --git a/src/components/card/chart-card.tsx b/src/components/card/chart-card.tsx
deleted file mode 100644
index b3674d3b..00000000
--- a/src/components/card/chart-card.tsx
+++ /dev/null
@@ -1,88 +0,0 @@
-'use client'
-
-import React from 'react'
-import { Chart as ChartJS, ArcElement, Tooltip, Legend } from 'chart.js'
-import { Doughnut } from 'react-chartjs-2'
-
-type ChartCardProps = {
- data: {
- labels: string[]
- datasets: number[]
- colors: string[]
- }
-}
-
-type LegendItemsProps = {
- label: string
- color: string
-}
-
-const LegendItem = ({ label, color }: LegendItemsProps) => (
-
-)
-
-const CustomLegend = ({ labels, colors, datasets }: ChartCardProps['data']) => {
- const total = datasets?.reduce((acc, dataset) => acc + dataset, 0) || 0
-
- return (
-
-
- {labels.map((label, index) => (
-
- ))}
-
-
- {datasets.map((dataset, index) => {
- const percentage = ((dataset / total) * 100).toFixed(0)
-
- return (
-
-
- {dataset} /{' '}
- {percentage}%
-
-
- )
- })}
-
-
- )
-}
-
-ChartJS.register(ArcElement, Tooltip, Legend)
-
-export const ChartCard = ({ data }: ChartCardProps) => {
- if (!data.datasets) {
- return null
- }
-
- return (
-
- )
-}
diff --git a/src/components/card/index.tsx b/src/components/card/index.tsx
index d7a7d23d..736f72d3 100644
--- a/src/components/card/index.tsx
+++ b/src/components/card/index.tsx
@@ -1,15 +1,7 @@
-import { CustomCardContent } from './card-content'
-import { CardMetadata } from './card-metadata'
import { CustomCardHeader } from './card-header'
import { CardRoot } from './card-root'
-import { CardResources } from './card-resources'
-import { ChartCard } from './chart-card'
export const Card = {
Root: CardRoot,
- Header: CustomCardHeader,
- Content: CustomCardContent,
- Metadata: CardMetadata,
- Resources: CardResources,
- Chart: ChartCard
+ Header: CustomCardHeader
}
diff --git a/src/components/combobox.tsx b/src/components/combobox.tsx
deleted file mode 100644
index 41bd747f..00000000
--- a/src/components/combobox.tsx
+++ /dev/null
@@ -1,75 +0,0 @@
-'use client'
-
-import * as React from 'react'
-import { Check, ChevronsUpDown } from 'lucide-react'
-
-import { cn } from '@/lib/utils'
-import { Button } from '@/components/ui/button'
-import {
- Command,
- CommandEmpty,
- CommandGroup,
- CommandInput,
- CommandItem
-} from '@/components/ui/command'
-import {
- Popover,
- PopoverContent,
- PopoverTrigger
-} from '@/components/ui/popover'
-
-const cloud = [
- {
- value: 'aws',
- label: 'AWS'
- }
-]
-
-export function Combobox() {
- const [open, setOpen] = React.useState(false)
- const [value, setValue] = React.useState('')
-
- return (
-
-
-
- {value
- ? cloud.find((cloud) => cloud.value === value)?.label
- : 'Select...'}
-
-
-
-
-
-
- Nothing was found.
-
- {cloud.map((cloud) => (
- {
- setValue(currentValue === value ? '' : currentValue)
- setOpen(false)
- }}
- >
-
- {cloud.label}
-
- ))}
-
-
-
-
- )
-}
diff --git a/src/components/data-table.tsx b/src/components/data-table.tsx
deleted file mode 100644
index cab1360d..00000000
--- a/src/components/data-table.tsx
+++ /dev/null
@@ -1,244 +0,0 @@
-'use client'
-
-import React, { useEffect } from 'react'
-import {
- ColumnDef,
- flexRender,
- getCoreRowModel,
- getFilteredRowModel,
- getPaginationRowModel,
- useReactTable
-} from '@tanstack/react-table'
-
-import {
- Table,
- TableBody,
- TableCell,
- TableHead,
- TableHeader,
- TableRow
-} from '@/components/ui/table'
-import { Button } from '@/components/ui/button'
-import { ChevronLeft, ChevronRight, Search } from 'lucide-react'
-import { cn } from '@/lib/utils'
-import {
- Select,
- SelectContent,
- SelectItem,
- SelectTrigger,
- SelectValue
-} from './ui/select'
-import { Checkbox } from '@/components/ui/checkbox'
-import { InputWithIcon } from './ui/input-with-icon'
-import { useIntl } from 'react-intl'
-
-interface DataTableProps {
- columns: ColumnDef[]
- pageSizeOptions?: number[]
- data: TData[]
- onSelectedRowsChange?: (selectedRows: TData[]) => void
- enableRowSelection?: boolean
-}
-
-export function DataTable({
- columns,
- pageSizeOptions = [10, 50, 100],
- data,
- onSelectedRowsChange,
- enableRowSelection = false
-}: DataTableProps) {
- const intl = useIntl()
- const [columnFilters, setColumnFilters] = React.useState([])
- const [rowSelection, setRowSelection] = React.useState({})
-
- const table = useReactTable({
- data,
- columns,
- getCoreRowModel: getCoreRowModel(),
- getPaginationRowModel: getPaginationRowModel(),
- getFilteredRowModel: getFilteredRowModel(),
- onColumnFiltersChange: setColumnFilters,
- onRowSelectionChange: setRowSelection,
- state: {
- columnFilters,
- rowSelection
- },
- enableRowSelection
- })
-
- useEffect(() => {
- if (onSelectedRowsChange) {
- const selectedRows = table
- .getSelectedRowModel()
- .rows.map((row) => row.original)
- onSelectedRowsChange(selectedRows)
- }
- }, [rowSelection, onSelectedRowsChange, table])
-
- return (
-
-
-
- table.getColumn('name')?.setFilterValue(event.target.value)
- }
- className="w-full min-w-[300px]"
- icon={ }
- iconPosition={'left'}
- />
-
- {data.length > 10 ? (
-
-
- Itens por página
-
-
{
- table.setPageSize(Number(value))
- }}
- >
-
-
-
-
- {pageSizeOptions.map((pageSize) => (
-
- {pageSize}
-
- ))}
-
-
-
- ) : null}
-
-
-
-
-
- {table.getHeaderGroups().map((headerGroup) => (
-
- {enableRowSelection && (
-
-
- table.toggleAllRowsSelected(!!value)
- }
- aria-label="Select all"
- />
-
- )}
- {headerGroup.headers.map((header) => (
-
- {header.isPlaceholder
- ? null
- : flexRender(
- header.column.columnDef.header,
- header.getContext()
- )}
-
- ))}
-
- ))}
-
-
- {table.getRowModel().rows?.length ? (
- table.getRowModel().rows.map((row) => (
-
- {enableRowSelection && (
-
- row.toggleSelected(!!value)}
- aria-label="Select row"
- />
-
- )}
- {row.getVisibleCells().map((cell) => (
-
- {flexRender(
- cell.column.columnDef.cell,
- cell.getContext()
- )}
-
- ))}
-
- ))
- ) : (
-
-
- No results.
-
-
- )}
-
-
-
-
-
-
- Mostrando{' '}
-
- {table.getFilteredRowModel().rows.length}
- {' '}
- de um total de {data.length} {' '}
- Ledgers.
-
-
-
-
- table.previousPage()}
- disabled={!table.getCanPreviousPage()}
- className={cn(
- 'space-x-1.5',
- !table.getCanPreviousPage() && 'bg-shadcn-100'
- )}
- >
-
-
- {intl.formatMessage({
- id: 'common.previousPage',
- defaultMessage: 'Previous page'
- })}
-
-
-
- table.nextPage()}
- disabled={!table.getCanNextPage()}
- className={cn(
- 'space-x-1.5',
- !table.getCanNextPage() && 'bg-shadcn-100'
- )}
- >
-
- {intl.formatMessage({
- id: 'common.nextPage',
- defaultMessage: 'Next page'
- })}
-
-
-
-
-
-
-
- )
-}
diff --git a/src/components/entity-data-table/entity-data-table.mdx b/src/components/entity-data-table/entity-data-table.mdx
new file mode 100644
index 00000000..125d9f0f
--- /dev/null
+++ b/src/components/entity-data-table/entity-data-table.mdx
@@ -0,0 +1,13 @@
+import { Meta, Controls, Primary, Canvas } from '@storybook/blocks'
+import * as Story from './entity-data-table.stories'
+
+
+
+# EntityDataTable
+
+Component used to wrap Table and show auxiliary information.
+
+
+
+
+
diff --git a/src/components/entity-data-table/entity-data-table.stories.tsx b/src/components/entity-data-table/entity-data-table.stories.tsx
new file mode 100644
index 00000000..653bca71
--- /dev/null
+++ b/src/components/entity-data-table/entity-data-table.stories.tsx
@@ -0,0 +1,61 @@
+import { Meta, StoryObj } from '@storybook/react'
+import React from 'react'
+import { EntityDataTable } from '.'
+import {
+ TableHeader,
+ TableRow,
+ TableHead,
+ TableBody,
+ TableCell,
+ Table
+} from '../ui/table'
+
+const meta: Meta> = {
+ title: 'Components/EntityDataTable',
+ component: EntityDataTable.Root,
+ argTypes: {}
+}
+
+export default meta
+
+export const Primary: StoryObj> = {
+ render: (args) => (
+
+
+
+
+ Name
+ Type
+ Code
+ Metadata
+
+
+
+
+ American Dolar
+ Coin
+ USD
+ 2 registers
+
+
+ Bitcoin
+ Cripto
+ BTC
+ -
+
+
+ Tether
+ Cripto
+ USDT
+ 4 registers
+
+
+
+
+
+ Showing 3 items.
+
+
+
+ )
+}
diff --git a/src/components/entity-data-table/index.tsx b/src/components/entity-data-table/index.tsx
new file mode 100644
index 00000000..b989f2b5
--- /dev/null
+++ b/src/components/entity-data-table/index.tsx
@@ -0,0 +1,34 @@
+import { cn } from '@/lib/utils'
+import React from 'react'
+import { Paper, PaperProps } from '../ui/paper'
+
+const EntityDataTableRoot = React.forwardRef(
+ (props) =>
+)
+EntityDataTableRoot.displayName = 'EntityDataTable'
+
+const EntityDataTableFooter = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+EntityDataTableFooter.displayName = 'EntityDataTableFooter'
+
+const EntityDataTableFooterText = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+EntityDataTableFooterText.displayName = 'EntityDataTableFooterText'
+
+export const EntityDataTable = {
+ Root: EntityDataTableRoot,
+ Footer: EntityDataTableFooter,
+ FooterText: EntityDataTableFooterText
+}
diff --git a/src/components/loading-screen.tsx b/src/components/loading-screen.tsx
index 35dbc4cb..c40bd657 100644
--- a/src/components/loading-screen.tsx
+++ b/src/components/loading-screen.tsx
@@ -2,7 +2,7 @@
import React from 'react'
import Image from 'next/image'
-import LoadingImage from '@/images/loading-wallpaper.jpg'
+import LoadingImage from '@/images/loading-wallpaper.webp'
import midazLoading from '@/animations/midaz-loading.json'
import { Lottie } from '@/lib/lottie'
diff --git a/src/components/ui/button/button.mdx b/src/components/ui/button/button.mdx
index 9707f609..88f9ca82 100644
--- a/src/components/ui/button/button.mdx
+++ b/src/components/ui/button/button.mdx
@@ -31,13 +31,9 @@ This is a button component.
-### With leading icon
+### With Icons
-### With leading icon at end
-
-
-
diff --git a/src/components/ui/button/button.stories.tsx b/src/components/ui/button/button.stories.tsx
index 02744bb0..49f54d6e 100644
--- a/src/components/ui/button/button.stories.tsx
+++ b/src/components/ui/button/button.stories.tsx
@@ -70,14 +70,16 @@ export const WithIcon: StoryObj = {
args: {
children: 'Button'
},
- render: (args) => } {...args} />
-}
-
-export const WithIconEnd: StoryObj = {
- args: {
- fullWidth: true,
- iconPlacement: 'end',
- children: 'Button'
- },
- render: (args) => } {...args} />
+ render: (args) => (
+
+
+ } {...args} />
+ } {...args} />
+
+
+ } {...args} />
+ } {...args} />
+
+
+ )
}
diff --git a/src/components/ui/button/index.tsx b/src/components/ui/button/index.tsx
index 7f6cb442..bc4499b9 100644
--- a/src/components/ui/button/index.tsx
+++ b/src/components/ui/button/index.tsx
@@ -43,12 +43,21 @@ const buttonVariants = cva(
const iconVariants = cva('', {
variants: {
position: {
- default: 'ml-2',
- end: 'absolute right-4'
+ start: 'mr-2',
+ end: 'ml-2',
+ 'far-end': 'absolute right-4'
+ },
+ size: {
+ default: 'h-10',
+ sm: 'h-8',
+ lg: 'h-12',
+ icon: 'h-10',
+ link: 'h-6',
+ xl: 'h-14'
}
},
defaultVariants: {
- position: 'default'
+ position: 'start'
}
})
@@ -56,8 +65,8 @@ export interface ButtonProps
extends React.ButtonHTMLAttributes,
VariantProps {
asChild?: boolean
- icon?: JSX.Element
- iconPlacement?: 'end'
+ icon?: React.ReactNode
+ iconPlacement?: 'start' | 'end' | 'far-end'
fullWidth?: boolean
}
@@ -69,13 +78,14 @@ const Button = React.forwardRef(
size,
asChild = false,
icon,
- iconPlacement,
+ iconPlacement = 'start',
fullWidth,
...props
},
ref
) => {
const Comp = asChild ? Slot : 'button'
+
return (
(
ref={ref}
{...props}
>
+ {icon && iconPlacement === 'start' && (
+
+ {icon}
+
+ )}
{props.children}
- {icon && (
+ {icon && iconPlacement !== 'start' && (
{icon}
diff --git a/src/components/ui/card/index.tsx b/src/components/ui/card/index.tsx
index 5a473e36..b5470b7a 100644
--- a/src/components/ui/card/index.tsx
+++ b/src/components/ui/card/index.tsx
@@ -13,7 +13,7 @@ const Card = React.forwardRef<
(({ className, ...props }: CardProps, ref) => (
))
@@ -40,7 +40,7 @@ const CardTitle = React.forwardRef<
>(({ className, ...props }: CardProps, ref) => (
-
+
))
CardContent.displayName = 'CardContent'
diff --git a/src/components/ui/collapsible/collapsible.mdx b/src/components/ui/collapsible/collapsible.mdx
new file mode 100644
index 00000000..85c42d9c
--- /dev/null
+++ b/src/components/ui/collapsible/collapsible.mdx
@@ -0,0 +1,16 @@
+import { Meta, Controls, Primary, Canvas } from '@storybook/blocks'
+import * as Story from './collapsible.stories'
+
+
+
+# Collapsible
+
+An interactive component which expands/collapses a panel. \
+[Docs](https://www.radix-ui.com/primitives/docs/components/collapsible)
+
+### Primary
+
+
+
+
+
diff --git a/src/components/ui/collapsible/collapsible.stories.tsx b/src/components/ui/collapsible/collapsible.stories.tsx
new file mode 100644
index 00000000..757ab736
--- /dev/null
+++ b/src/components/ui/collapsible/collapsible.stories.tsx
@@ -0,0 +1,50 @@
+import { Meta, StoryObj } from '@storybook/react'
+import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '.'
+import React from 'react'
+import { Button } from '../button'
+import { ChevronsUpDown } from 'lucide-react'
+
+const meta: Meta> = {
+ title: 'Primitives/Collapsible',
+ component: Collapsible,
+ argTypes: {}
+}
+
+export default meta
+
+export const Primary: StoryObj = {
+ render: () => {
+ const [isOpen, setIsOpen] = React.useState(false)
+
+ return (
+
+
+
+ @peduarte starred 3 repositories
+
+
+
+
+ Toggle
+
+
+
+
+ @radix-ui/primitives
+
+
+
+ @radix-ui/colors
+
+
+ @stitches/react
+
+
+
+ )
+ }
+}
diff --git a/src/components/ui/collapsible.tsx b/src/components/ui/collapsible/index.tsx
similarity index 100%
rename from src/components/ui/collapsible.tsx
rename to src/components/ui/collapsible/index.tsx
diff --git a/src/components/ui/combobox/combobox.mdx b/src/components/ui/combobox/combobox.mdx
new file mode 100644
index 00000000..1835ca26
--- /dev/null
+++ b/src/components/ui/combobox/combobox.mdx
@@ -0,0 +1,16 @@
+import { Meta, Controls, Primary, Canvas } from '@storybook/blocks'
+import * as Story from './combobox.stories'
+
+
+
+# Combobox
+
+Autocomplete input and command palette with a list of suggestions. \
+The Combobox is built using a composition of the [Popover](/docs/primitives-popover--docs) and the [Command](/docs/primitives-command--docs) components.
+
+### Primary
+
+
+
+
+
diff --git a/src/components/ui/combobox/combobox.stories.tsx b/src/components/ui/combobox/combobox.stories.tsx
new file mode 100644
index 00000000..929b6f4f
--- /dev/null
+++ b/src/components/ui/combobox/combobox.stories.tsx
@@ -0,0 +1,98 @@
+import { Meta, StoryObj } from '@storybook/react'
+import { Popover, PopoverContent, PopoverTrigger } from '../popover'
+import React from 'react'
+import { Button } from '../button'
+import { Check, ChevronsUpDown } from 'lucide-react'
+import {
+ Command,
+ CommandEmpty,
+ CommandGroup,
+ CommandInput,
+ CommandItem,
+ CommandList
+} from '../command'
+import { cn } from '@/lib/utils'
+
+const meta: Meta = {
+ title: 'Primitives/Combobox',
+ component: Popover,
+ argTypes: {}
+}
+
+export default meta
+
+const frameworks = [
+ {
+ value: 'next.js',
+ label: 'Next.js'
+ },
+ {
+ value: 'sveltekit',
+ label: 'SvelteKit'
+ },
+ {
+ value: 'nuxt.js',
+ label: 'Nuxt.js'
+ },
+ {
+ value: 'remix',
+ label: 'Remix'
+ },
+ {
+ value: 'astro',
+ label: 'Astro'
+ }
+]
+
+export const Primary: StoryObj = {
+ render: () => {
+ const [open, setOpen] = React.useState(false)
+ const [value, setValue] = React.useState('')
+
+ return (
+
+
+
+ {value
+ ? frameworks.find((framework) => framework.value === value)?.label
+ : 'Select framework...'}
+
+
+
+
+
+
+
+ No framework found.
+
+ {frameworks.map((framework) => (
+ {
+ setValue(currentValue === value ? '' : currentValue)
+ setOpen(false)
+ }}
+ >
+ {framework.label}
+
+
+ ))}
+
+
+
+
+
+ )
+ }
+}
diff --git a/src/components/ui/command/command.mdx b/src/components/ui/command/command.mdx
new file mode 100644
index 00000000..f9b86ee8
--- /dev/null
+++ b/src/components/ui/command/command.mdx
@@ -0,0 +1,16 @@
+import { Meta, Controls, Primary, Canvas } from '@storybook/blocks'
+import * as Story from './command.stories'
+
+
+
+# Command
+
+Fast, composable, unstyled command menu for React. \
+[Docs](https://cmdk.paco.me/)
+
+### Primary
+
+
+
+
+
diff --git a/src/components/ui/command/command.stories.tsx b/src/components/ui/command/command.stories.tsx
new file mode 100644
index 00000000..1cf5f9ad
--- /dev/null
+++ b/src/components/ui/command/command.stories.tsx
@@ -0,0 +1,70 @@
+import { Meta, StoryObj } from '@storybook/react'
+import {
+ Command,
+ CommandEmpty,
+ CommandGroup,
+ CommandInput,
+ CommandItem,
+ CommandList,
+ CommandSeparator,
+ CommandShortcut
+} from '.'
+import {
+ Calendar,
+ Smile,
+ Calculator,
+ User,
+ CreditCard,
+ Settings
+} from 'lucide-react'
+
+const meta: Meta = {
+ title: 'Primitives/Command',
+ component: Command,
+ argTypes: {}
+}
+
+export default meta
+
+export const Primary: StoryObj = {
+ render: (args) => (
+
+
+
+ No results found.
+
+
+
+ Calendar
+
+
+
+ Search Emoji
+
+
+
+ Calculator
+
+
+
+
+
+
+ Profile
+ ⌘P
+
+
+
+ Billing
+ ⌘B
+
+
+
+ Settings
+ ⌘S
+
+
+
+
+ )
+}
diff --git a/src/components/ui/command.tsx b/src/components/ui/command/index.tsx
similarity index 100%
rename from src/components/ui/command.tsx
rename to src/components/ui/command/index.tsx
diff --git a/src/components/ui/paper/index.tsx b/src/components/ui/paper/index.tsx
new file mode 100644
index 00000000..f75d1e47
--- /dev/null
+++ b/src/components/ui/paper/index.tsx
@@ -0,0 +1,14 @@
+import { cn } from '@/lib/utils'
+import React from 'react'
+
+export type PaperProps = React.HTMLAttributes
+
+export const Paper = React.forwardRef(
+ ({ className, ...others }) => (
+
+ )
+)
+Paper.displayName = 'Paper'
diff --git a/src/components/ui/paper/paper.mdx b/src/components/ui/paper/paper.mdx
new file mode 100644
index 00000000..75af5235
--- /dev/null
+++ b/src/components/ui/paper/paper.mdx
@@ -0,0 +1,15 @@
+import { Meta, Controls, Primary, Canvas } from '@storybook/blocks'
+import * as Story from './paper.stories'
+
+
+
+# Paper
+
+Shows a piece of content with a little emphasis and shadow.
+
+### Primary
+
+
+
+
+
diff --git a/src/components/ui/paper/paper.stories.tsx b/src/components/ui/paper/paper.stories.tsx
new file mode 100644
index 00000000..a8930ff9
--- /dev/null
+++ b/src/components/ui/paper/paper.stories.tsx
@@ -0,0 +1,26 @@
+import { Meta, StoryObj } from '@storybook/react'
+import { Paper, PaperProps } from '.'
+
+const meta: Meta = {
+ title: 'Primitives/Paper',
+ component: Paper,
+ argTypes: {}
+}
+
+export default meta
+
+export const Primary: StoryObj = {
+ args: {
+ className: 'p-4'
+ },
+ render: (args) => (
+
+ This is a Paper component!
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi neque
+ dolor, tempus ac scelerisque sed, accumsan eget orci. Donec ac mauris
+ congue, mollis massa vel, sagittis libero.
+
+
+ )
+}
diff --git a/src/components/ui/popover/popover.mdx b/src/components/ui/popover/popover.mdx
index cf9574be..3299eccc 100644
--- a/src/components/ui/popover/popover.mdx
+++ b/src/components/ui/popover/popover.mdx
@@ -5,7 +5,8 @@ import * as Story from './popover.stories'
# Popover
-Displays rich content in a portal, triggered by a button.
+Displays rich content in a portal, triggered by a button. \
+[Docs](https://www.radix-ui.com/primitives/docs/components/popover)
### Primary
diff --git a/src/components/ui/separator.tsx b/src/components/ui/separator/index.tsx
similarity index 100%
rename from src/components/ui/separator.tsx
rename to src/components/ui/separator/index.tsx
diff --git a/src/components/ui/separator/separator.mdx b/src/components/ui/separator/separator.mdx
new file mode 100644
index 00000000..85363e8c
--- /dev/null
+++ b/src/components/ui/separator/separator.mdx
@@ -0,0 +1,16 @@
+import { Meta, Controls, Primary, Canvas } from '@storybook/blocks'
+import * as Story from './separator.stories'
+
+
+
+# Separator
+
+Visually or semantically separates content. \
+[Docs](https://www.radix-ui.com/primitives/docs/components/separator)
+
+### Primary
+
+
+
+
+
diff --git a/src/components/ui/separator/separator.stories.tsx b/src/components/ui/separator/separator.stories.tsx
new file mode 100644
index 00000000..c5c9f8d9
--- /dev/null
+++ b/src/components/ui/separator/separator.stories.tsx
@@ -0,0 +1,31 @@
+import { Meta, StoryObj } from '@storybook/react'
+import { Separator } from '.'
+
+const meta: Meta> = {
+ title: 'Primitives/Separator',
+ component: Separator,
+ argTypes: {}
+}
+
+export default meta
+
+export const Primary: StoryObj = {
+ render: () => (
+
+
+
Radix Primitives
+
+ An open-source UI component library.
+
+
+
+
+
Blog
+
+
Docs
+
+
Source
+
+
+ )
+}
diff --git a/src/components/ui/skeleton.tsx b/src/components/ui/skeleton/index.tsx
similarity index 100%
rename from src/components/ui/skeleton.tsx
rename to src/components/ui/skeleton/index.tsx
diff --git a/src/components/ui/skeleton/skeleton.mdx b/src/components/ui/skeleton/skeleton.mdx
new file mode 100644
index 00000000..bfefac92
--- /dev/null
+++ b/src/components/ui/skeleton/skeleton.mdx
@@ -0,0 +1,19 @@
+import { Meta, Controls, Primary, Canvas } from '@storybook/blocks'
+import * as Story from './skeleton.stories'
+
+
+
+# Skeleton
+
+Use to show a placeholder while content is loading.
+
+### Primary
+
+
+
+### Example
+
+
+
+
+
diff --git a/src/components/ui/skeleton/skeleton.stories.tsx b/src/components/ui/skeleton/skeleton.stories.tsx
new file mode 100644
index 00000000..6d93dd06
--- /dev/null
+++ b/src/components/ui/skeleton/skeleton.stories.tsx
@@ -0,0 +1,27 @@
+import { Meta, StoryObj } from '@storybook/react'
+import { Skeleton } from '.'
+
+const meta: Meta> = {
+ title: 'Primitives/Skeleton',
+ component: Skeleton,
+ argTypes: {}
+}
+
+export default meta
+
+export const Primary: StoryObj> = {
+ render: (args) =>
+}
+
+export const Example: StoryObj> = {
+ render: (args) => (
+
+ )
+}
diff --git a/src/components/ui/table/index.tsx b/src/components/ui/table/index.tsx
index 4b1996a4..ec3a8721 100644
--- a/src/components/ui/table/index.tsx
+++ b/src/components/ui/table/index.tsx
@@ -6,10 +6,7 @@ const TableContainer = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes
>(({ className, ...props }, ref) => (
-
+
))
TableContainer.displayName = 'TableContainer'
diff --git a/src/components/ui/tooltip/index.tsx b/src/components/ui/tooltip/index.tsx
index af1b6f3e..5704b7a0 100644
--- a/src/components/ui/tooltip/index.tsx
+++ b/src/components/ui/tooltip/index.tsx
@@ -14,16 +14,19 @@ const TooltipTrigger = TooltipPrimitive.Trigger
const TooltipContent = React.forwardRef<
React.ElementRef,
React.ComponentPropsWithoutRef
->(({ className, sideOffset = 4, ...props }, ref) => (
+>(({ className, sideOffset = 4, children, ...props }, ref) => (
+ >
+ {children}
+
+
))
TooltipContent.displayName = TooltipPrimitive.Content.displayName
diff --git a/src/components/ui/tooltip/tooltip.stories.tsx b/src/components/ui/tooltip/tooltip.stories.tsx
index be57da36..2e3b0da4 100644
--- a/src/components/ui/tooltip/tooltip.stories.tsx
+++ b/src/components/ui/tooltip/tooltip.stories.tsx
@@ -16,11 +16,11 @@ export const Primary: StoryObj = {
- Hover
+
+ Hover
+
-
- Add to library
-
+ Add to library
)
@@ -34,7 +34,9 @@ export const WithoutDelay: StoryObj = {
- Hover
+
+ Hover
+
Add to library
@@ -46,7 +48,7 @@ export const WithoutDelay: StoryObj = {
export const WithSides: StoryObj = {
render: (args) => (
-
+
diff --git a/src/core/infrastructure/observability/instrumentation-config.ts b/src/core/infrastructure/observability/instrumentation-config.ts
new file mode 100644
index 00000000..27b8980d
--- /dev/null
+++ b/src/core/infrastructure/observability/instrumentation-config.ts
@@ -0,0 +1,35 @@
+import { Resource } from '@opentelemetry/resources'
+import {
+ MeterProvider,
+ PeriodicExportingMetricReader
+} from '@opentelemetry/sdk-metrics'
+import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http'
+import { registerInstrumentations } from '@opentelemetry/instrumentation'
+import { HttpInstrumentation } from '@opentelemetry/instrumentation-http'
+import { RuntimeNodeInstrumentation } from '@opentelemetry/instrumentation-runtime-node'
+import { metrics } from '@opentelemetry/api'
+
+const metricExporter = new OTLPMetricExporter({
+ url: process.env.OTEL_URL
+})
+
+const metricReader = new PeriodicExportingMetricReader({
+ exporter: metricExporter,
+ exportIntervalMillis: 5000
+})
+
+const meterProvider = new MeterProvider({
+ resource: new Resource({
+ 'service.name': 'midaz-console'
+ }),
+ readers: [metricReader]
+})
+
+metrics.setGlobalMeterProvider(meterProvider)
+
+registerInstrumentations({
+ instrumentations: [
+ new HttpInstrumentation(),
+ new RuntimeNodeInstrumentation()
+ ]
+})
diff --git a/src/instrumentation.ts b/src/instrumentation.ts
new file mode 100644
index 00000000..cad9de5e
--- /dev/null
+++ b/src/instrumentation.ts
@@ -0,0 +1,5 @@
+export async function register() {
+ if (process.env.NEXT_RUNTIME === 'nodejs') {
+ await import('./core/infrastructure/observability/instrumentation-config')
+ }
+}
diff --git a/src/schema/ledger.ts b/src/schema/ledger.ts
index b4b753d2..97b2a990 100644
--- a/src/schema/ledger.ts
+++ b/src/schema/ledger.ts
@@ -1,6 +1,6 @@
import { z } from 'zod'
import { metadata } from './metadata'
-const name = z.string().min(1)
+const name = z.string().min(1).max(255)
export const ledger = { name, metadata }