Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

♻️ Ledger Details page #73

Merged
merged 9 commits into from
Dec 6, 2024
Merged
2 changes: 1 addition & 1 deletion src/app/(auth-routes)/signin/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ const SignInPage = () => {
loading={form.formState.isSubmitting}
size="xl"
icon={<ArrowRight />}
iconPlacement="end"
iconPlacement="far-end"
>
{intl.formatMessage({
id: 'signIn.buttonSignIn',
Expand Down
61 changes: 3 additions & 58 deletions src/app/(routes)/ledgers/[id]/ledger-details-view.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
'use client'

import { BottomDrawer } from '@/components/bottom-drawer'
import { Breadcrumb } from '@/components/breadcrumb'
import { PageHeader } from '@/components/page-header'
import useCustomToast from '@/hooks/use-custom-toast'
import React, { useEffect, useState } from 'react'
import React from 'react'
import { cn } from '@/lib/utils'
import { useFormState } from '@/context/form-details-context'
import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs'
import { useIntl } from 'react-intl'
import { ProductsTabContent } from './products/products-tab-content'
import { useTabs } from '@/hooks/use-tabs'
import { getBreadcrumbPaths } from '@/components/breadcrumb/get-breadcrumb-paths'
import { useOrganization } from '@/context/organization-provider/organization-provider-client'
import { ILedgerType } from '@/types/ledgers-type'
import { useUpdateLedger } from '@/client/ledgers'
import { LedgerDetailsSkeleton } from './ledger-details-skeleton'
import { OverviewTabContent } from './overview/overview-tab-content'
import { AssetsTabContent } from './assets/assets-tab-content'
Expand All @@ -37,40 +32,10 @@ type LedgerDetailsViewProps = {

const LedgerDetailsView = ({ data }: LedgerDetailsViewProps) => {
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([
{
Expand Down Expand Up @@ -117,25 +82,12 @@ const LedgerDetailsView = ({ data }: LedgerDetailsViewProps) => {
}
])

const handleGlobalSubmit = async () => {
const dataToSend = {
...formData
}

updateLedger(dataToSend)
}

const handleCancel = () => {
setIsDrawerOpen(false)
resetForm()
}

if (!data) {
return <LedgerDetailsSkeleton />
}

return (
<div className={cn(isDirty && 'pb-40')}>
<div>
<Breadcrumb paths={breadcrumbPaths} />

<PageHeader.Root>
Expand Down Expand Up @@ -211,13 +163,6 @@ const LedgerDetailsView = ({ data }: LedgerDetailsViewProps) => {
<AccountsTabContent />
</TabsContent>
</Tabs>

<BottomDrawer
isOpen={isDrawerOpen}
handleSubmit={handleGlobalSubmit}
handleCancel={handleCancel}
isPending={updatePending}
/>
</div>
)
}
Expand Down
193 changes: 165 additions & 28 deletions src/app/(routes)/ledgers/[id]/overview/overview-tab-content.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,182 @@
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<typeof formSchema>

type OverviewTabContentProps = {
data: ILedgerType
}

export const OverviewTabContent = ({ data }: OverviewTabContentProps) => {
const intl = useIntl()
const { currentOrganization } = useOrganization()

return (
<div className="flex gap-6">
<div className="flex flex-1 flex-col gap-6">
<Card.Root>
<Card.Header
title={intl.formatMessage({
id: 'common.identification',
defaultMessage: 'Identification'
})}
className="text-lg font-semibold capitalize text-[#52525B]"
/>
const { showSuccess, showError } = useCustomToast()

<Card.Content data={data} />
</Card.Root>
const form = useForm<FormSchema>({
resolver: zodResolver(formSchema),
defaultValues: {
...initialValues,
...data
}
})

<Card.Root>
<Card.Header title="Metadados" className="text-lg capitalize" />
<Card.Metadata data={data} />
</Card.Root>
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'
})
)
}
})

<Card.Root className="py-4">
<Card.Header
title={intl.formatMessage({
id: 'common.resources',
defaultMessage: 'Resources'
})}
/>
const handleSubmit = async (values: FormSchema) => {
updateLedger(values)
form.reset(values)
}

const handleCancel = () => {
form.reset()
}

<Card.Resources />
</Card.Root>
return (
<Form {...form}>
<div className="grid grid-cols-4 gap-6">
<div className="col-span-2 flex flex-1 flex-col gap-6">
<Card>
<CardHeader>
<h2 className="pb-3 text-lg font-semibold capitalize text-[#52525B]">
{intl.formatMessage({
id: 'common.identification',
defaultMessage: 'Identification'
})}
</h2>
</CardHeader>
<CardContent>
<InputField
name="name"
label={intl.formatMessage({
id: 'entity.ledger.name',
defaultMessage: 'Ledger Name'
})}
control={form.control}
/>
</CardContent>
</Card>
<Card>
<CardHeader>
<h2 className="pb-3 text-lg font-semibold capitalize text-[#52525B]">
{intl.formatMessage({
id: 'common.metadata',
defaultMessage: 'Metadata'
})}
</h2>
</CardHeader>
<CardContent>
<MetadataField name="metadata" control={form.control} />
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>
{intl.formatMessage({
id: 'common.resources',
defaultMessage: 'Resources'
})}
</CardTitle>
</CardHeader>
<CardContent>
<div className="grid grid-cols-4 justify-items-start">
<Button
className="text-shadcn-400"
icon={<Github size={16} />}
variant="link"
size="link"
onClick={() =>
window.open('https://github.com/LerianStudio', '_blank')
}
>
Github
</Button>
<Button
className="text-shadcn-400"
icon={<LifeBuoy size={16} />}
variant="link"
size="link"
>
{intl.formatMessage({
id: 'common.support',
defaultMessage: 'Support'
})}
</Button>
<Button
className="text-shadcn-400"
icon={<ExternalLink size={16} />}
variant="link"
size="link"
>
CLI Docs
</Button>
<Button
className="text-shadcn-400"
icon={<ExternalLink size={16} />}
variant="link"
size="link"
onClick={() =>
window.open('https://docs.lerian.studio', '_blank')
}
>
Docs
</Button>
</div>
</CardContent>
</Card>

<SaveSheet
open={form.formState.isDirty}
loading={updatePending}
onSubmit={form.handleSubmit(handleSubmit)}
onCancel={handleCancel}
/>
</div>
<div className="col-span-1" />
<div className="col-span-1" />
</div>
</div>
</Form>
)
}
Original file line number Diff line number Diff line change
@@ -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 (
<div
className={cn(
'fixed inset-x-0 bottom-0 z-50 ml-[136px] mr-16 transform rounded-t-2xl bg-white shadow-drawer transition-transform',
isOpen ? 'translate-y-0' : 'translate-y-full',
!isCollapsed && 'ml-[315px]',
open ? 'translate-y-0' : 'translate-y-full',
!true && 'ml-[315px]',
'duration-300 ease-in-out'
)}
aria-hidden={!isOpen}
aria-hidden={!open}
>
<div className="flex w-full justify-center px-16 py-12">
<div className="flex w-[292px] flex-col gap-2">
<LoadingButton
type="submit"
fullWidth
loading={isPending}
onClick={handleSubmit}
loading={loading}
onClick={onSubmit}
>
{intl.formatMessage({
id: 'common.saveChanges',
defaultMessage: 'Save changes'
})}
</LoadingButton>
<Button variant="outline" onClick={handleCancel}>
<Button variant="outline" onClick={onCancel}>
{intl.formatMessage({
id: 'common.cancel',
defaultMessage: 'Cancel'
Expand Down
Loading
Loading