| @@ -0,0 +1,30 @@ | |||||
| import CreateCompany from "@/components/CreateCompany"; | |||||
| import { I18nProvider, getServerI18n } from "@/i18n"; | |||||
| import Typography from "@mui/material/Typography"; | |||||
| import { Metadata } from "next"; | |||||
| export const metadata: Metadata = { | |||||
| title: "Create Comapny", | |||||
| }; | |||||
| interface Props { | |||||
| searchParams: { [key: string]: string | undefined }; | |||||
| } | |||||
| const Companys: React.FC<Props> = async ({searchParams}) => { | |||||
| const { t } = await getServerI18n("companys"); | |||||
| const companyId = searchParams["id"]; | |||||
| return( | |||||
| <> | |||||
| <Typography variant="h4">{t("Create Company")}</Typography> | |||||
| <I18nProvider namespaces={["companys"]}> | |||||
| <CreateCompany isEdit={true} companyId={companyId} /> | |||||
| </I18nProvider> | |||||
| </> | |||||
| ) | |||||
| } | |||||
| export default Companys; | |||||
| @@ -1,6 +1,6 @@ | |||||
| "use server"; | "use server"; | ||||
| import { serverFetchJson } from "@/app/utils/fetchUtil"; | |||||
| import { serverFetchJson, serverFetchWithNoContent } from "@/app/utils/fetchUtil"; | |||||
| import { BASE_API_URL } from "@/config/api"; | import { BASE_API_URL } from "@/config/api"; | ||||
| import { Dayjs } from "dayjs"; | import { Dayjs } from "dayjs"; | ||||
| import { cache } from "react"; | import { cache } from "react"; | ||||
| @@ -15,6 +15,7 @@ export interface combo { | |||||
| } | } | ||||
| export interface CreateCompanyInputs { | export interface CreateCompanyInputs { | ||||
| id?: number; | |||||
| companyCode: string; | companyCode: string; | ||||
| companyName: string; | companyName: string; | ||||
| brNo: string; | brNo: string; | ||||
| @@ -30,6 +31,23 @@ export interface CreateCompanyInputs { | |||||
| email: string; | email: string; | ||||
| } | } | ||||
| export interface EditCompanyInputs { | |||||
| id?: number; | |||||
| companyCode: string; | |||||
| name: string; | |||||
| brNo: string; | |||||
| contactName: string; | |||||
| phone: string; | |||||
| otHourTo: number[]; | |||||
| otHourFrom: number[]; | |||||
| normalHourTo: number[]; | |||||
| normalHourFrom: number[]; | |||||
| currency: string; | |||||
| address: string; | |||||
| district: string; | |||||
| email: string; | |||||
| } | |||||
| export const saveCompany = async (data: CreateCompanyInputs) => { | export const saveCompany = async (data: CreateCompanyInputs) => { | ||||
| return serverFetchJson(`${BASE_API_URL}/companys/new`, { | return serverFetchJson(`${BASE_API_URL}/companys/new`, { | ||||
| method: "POST", | method: "POST", | ||||
| @@ -43,3 +61,15 @@ export const fetchCompanyCombo = cache(async () => { | |||||
| next: { tags: ["company"] }, | next: { tags: ["company"] }, | ||||
| }); | }); | ||||
| }); | }); | ||||
| export const deleteCompany = async (id: number) => { | |||||
| const department = await serverFetchWithNoContent( | |||||
| `${BASE_API_URL}/companys/${id}`, | |||||
| { | |||||
| method: "DELETE", | |||||
| headers: { "Content-Type": "application/json" }, | |||||
| }, | |||||
| ); | |||||
| return department | |||||
| }; | |||||
| @@ -2,6 +2,7 @@ import { serverFetchJson } from "@/app/utils/fetchUtil"; | |||||
| import { BASE_API_URL } from "@/config/api"; | import { BASE_API_URL } from "@/config/api"; | ||||
| import { cache } from "react"; | import { cache } from "react"; | ||||
| import "server-only"; | import "server-only"; | ||||
| import { CreateCompanyInputs, EditCompanyInputs } from "./actions"; | |||||
| export interface CompanyResult { | export interface CompanyResult { | ||||
| id: number; | id: number; | ||||
| @@ -21,4 +22,13 @@ export const fetchCompanys = cache(async () => { | |||||
| return serverFetchJson<CompanyResult[]>(`${BASE_API_URL}/companys`, { | return serverFetchJson<CompanyResult[]>(`${BASE_API_URL}/companys`, { | ||||
| next: { tags: ["companys"] }, | next: { tags: ["companys"] }, | ||||
| }); | }); | ||||
| }); | |||||
| export const fetchCompanyDetails = cache(async (companyId: string) => { | |||||
| return serverFetchJson<EditCompanyInputs>( | |||||
| `${BASE_API_URL}/companys/companyDetails/${companyId}`, | |||||
| { | |||||
| next: { tags: [`departmentDetail${companyId}`] }, | |||||
| }, | |||||
| ); | |||||
| }); | }); | ||||
| @@ -19,6 +19,8 @@ export const INPUT_DATE_FORMAT = "YYYY-MM-DD"; | |||||
| export const OUTPUT_DATE_FORMAT = "YYYY/MM/DD"; | export const OUTPUT_DATE_FORMAT = "YYYY/MM/DD"; | ||||
| export const OUTPUT_TIME_FORMAT = "HH:mm:ss"; | |||||
| export const convertDateToString = (date: Date, format: string = OUTPUT_DATE_FORMAT) => { | export const convertDateToString = (date: Date, format: string = OUTPUT_DATE_FORMAT) => { | ||||
| return dayjs(date).format(format) | return dayjs(date).format(format) | ||||
| } | } | ||||
| @@ -38,6 +40,23 @@ export const convertDateArrayToString = (dateArray: number[], format: string = O | |||||
| } | } | ||||
| } | } | ||||
| export const convertTimeArrayToString = (timeArray: number[], format: string = OUTPUT_TIME_FORMAT, needTime: boolean = false) => { | |||||
| let timeString = ''; | |||||
| if (timeArray !== null && timeArray !== undefined) { | |||||
| const hour = timeArray[0] || 0; | |||||
| const minute = timeArray[1] || 0; | |||||
| timeString = dayjs() | |||||
| .set('hour', hour) | |||||
| .set('minute', minute) | |||||
| .set('second', 0) | |||||
| .format('HH:mm:ss'); | |||||
| } | |||||
| return timeString | |||||
| } | |||||
| const shortDateFormatter_en = new Intl.DateTimeFormat("en-HK", { | const shortDateFormatter_en = new Intl.DateTimeFormat("en-HK", { | ||||
| weekday: "short", | weekday: "short", | ||||
| year: "numeric", | year: "numeric", | ||||
| @@ -6,7 +6,10 @@ import SearchBox, { Criterion } from "../SearchBox"; | |||||
| import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
| import SearchResults, { Column } from "../SearchResults"; | import SearchResults, { Column } from "../SearchResults"; | ||||
| import EditNote from "@mui/icons-material/EditNote"; | import EditNote from "@mui/icons-material/EditNote"; | ||||
| import uniq from "lodash/uniq"; | |||||
| import { useRouter } from "next/navigation"; | |||||
| import { deleteDialog, successDialog } from "../Swal/CustomAlerts"; | |||||
| import { deleteCompany } from "@/app/api/companys/actions"; | |||||
| import DeleteIcon from '@mui/icons-material/Delete'; | |||||
| interface Props { | interface Props { | ||||
| companys: CompanyResult[]; | companys: CompanyResult[]; | ||||
| @@ -18,6 +21,8 @@ type SearchParamNames = keyof SearchQuery; | |||||
| const CompanySearch: React.FC<Props> = ({ companys }) => { | const CompanySearch: React.FC<Props> = ({ companys }) => { | ||||
| const { t } = useTranslation("companys"); | const { t } = useTranslation("companys"); | ||||
| const router = useRouter() | |||||
| const [filteredCompanys, setFilteredCompanys] = useState(companys); | const [filteredCompanys, setFilteredCompanys] = useState(companys); | ||||
| const searchCriteria: Criterion<SearchParamNames>[] = useMemo( | const searchCriteria: Criterion<SearchParamNames>[] = useMemo( | ||||
| @@ -34,10 +39,22 @@ const CompanySearch: React.FC<Props> = ({ companys }) => { | |||||
| setFilteredCompanys(companys); | setFilteredCompanys(companys); | ||||
| }, [companys]); | }, [companys]); | ||||
| const onProjectClick = useCallback((project: CompanyResult) => { | |||||
| console.log(project); | |||||
| const onProjectClick = useCallback((company: CompanyResult) => { | |||||
| console.log(company); | |||||
| router.push(`/settings/company/edit?id=${company.id}`); | |||||
| }, []); | }, []); | ||||
| const onDeleteClick = useCallback((company: CompanyResult) => { | |||||
| deleteDialog(async() => { | |||||
| await deleteCompany(company.id) | |||||
| successDialog("Delete Success", t) | |||||
| setFilteredCompanys((prev) => prev.filter((obj) => obj.id !== company.id)) | |||||
| }, t) | |||||
| }, []); | |||||
| const columns = useMemo<Column<CompanyResult>[]>( | const columns = useMemo<Column<CompanyResult>[]>( | ||||
| () => [ | () => [ | ||||
| { | { | ||||
| @@ -51,7 +68,14 @@ const CompanySearch: React.FC<Props> = ({ companys }) => { | |||||
| { name: "brNo", label: t("brNo") }, | { name: "brNo", label: t("brNo") }, | ||||
| { name: "contactName", label: t("Contact Name") }, | { name: "contactName", label: t("Contact Name") }, | ||||
| { name: "phone", label: t("Contact No.") }, | { name: "phone", label: t("Contact No.") }, | ||||
| { name: "email", label: t("Contact Email") } | |||||
| { name: "email", label: t("Contact Email") }, | |||||
| { | |||||
| name: "id", | |||||
| label: t("Delete"), | |||||
| onClick: onDeleteClick, | |||||
| buttonIcon: <DeleteIcon />, | |||||
| color: "error" | |||||
| }, | |||||
| ], | ], | ||||
| [t, onProjectClick], | [t, onProjectClick], | ||||
| ); | ); | ||||
| @@ -19,18 +19,39 @@ import { Controller, UseFormRegister, useFormContext } from "react-hook-form"; | |||||
| import { CreateCompanyInputs } from "@/app/api/companys/actions"; | import { CreateCompanyInputs } from "@/app/api/companys/actions"; | ||||
| import { TimePicker } from "@mui/x-date-pickers"; | import { TimePicker } from "@mui/x-date-pickers"; | ||||
| import dayjs from 'dayjs'; | import dayjs from 'dayjs'; | ||||
| import { useEffect } from "react"; | |||||
| import { convertTimeArrayToString } from "@/app/utils/formatUtil"; | |||||
| const CompanyDetails: React.FC = ({ | |||||
| interface Props{ | |||||
| content : Content; | |||||
| } | |||||
| interface Content { | |||||
| normalHourFrom: number[]; | |||||
| normalHourTo: number[]; | |||||
| otHourFrom: number[]; | |||||
| otHourTo: number[]; | |||||
| } | |||||
| const CompanyDetails: React.FC<Props> = ({ | |||||
| content, | |||||
| }) => { | }) => { | ||||
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| const { | const { | ||||
| register, | register, | ||||
| formState: { errors }, | formState: { errors }, | ||||
| control, | |||||
| setValue, | setValue, | ||||
| getValues, | getValues, | ||||
| } = useFormContext<CreateCompanyInputs>(); | } = useFormContext<CreateCompanyInputs>(); | ||||
| console.log(content) | |||||
| useEffect(() => { | |||||
| setValue("normalHourFrom", convertTimeArrayToString(content.normalHourFrom, "HH:mm:ss", false)); | |||||
| setValue("normalHourTo", convertTimeArrayToString(content.normalHourTo, "HH:mm:ss", false)); | |||||
| setValue("otHourFrom", convertTimeArrayToString(content.otHourFrom, "HH:mm:ss", false)); | |||||
| setValue("otHourTo", convertTimeArrayToString(content.otHourTo, "HH:mm:ss", false)); | |||||
| }, [content]) | |||||
| return ( | return ( | ||||
| <Card> | <Card> | ||||
| @@ -101,84 +122,80 @@ const CompanyDetails: React.FC = ({ | |||||
| /> | /> | ||||
| </Grid> | </Grid> | ||||
| <Grid item xs={3}> | <Grid item xs={3}> | ||||
| <Controller | |||||
| control={control} | |||||
| name="normalHourFrom" | |||||
| rules={{ required: true }} | |||||
| render={({ field }) => { | |||||
| return ( | |||||
| <TimePicker | |||||
| label="Normal Hour From" | |||||
| inputRef={field.ref} | |||||
| onChange={(time) => { | |||||
| const formattedTime = time ? dayjs(time as string).format('HH:mm:ss') : ''; | |||||
| field.onChange(formattedTime); | |||||
| }} | |||||
| sx={{ width: '100%' }} | |||||
| /> | |||||
| ); | |||||
| }} | |||||
| /> | |||||
| <FormControl fullWidth> | |||||
| <TimePicker | |||||
| label={t("Normal Hour From")} | |||||
| value={content.normalHourFrom !== undefined && content.normalHourFrom !== null ? | |||||
| dayjs().hour(content.normalHourFrom[0]).minute(content.normalHourFrom[1]) : | |||||
| dayjs().hour(9).minute(0)} | |||||
| onChange={(time) => { | |||||
| if (!time) return; | |||||
| setValue("normalHourFrom", time.format("HH:mm:ss")); | |||||
| }} | |||||
| slotProps={{ | |||||
| textField: { | |||||
| helperText: 'HH:mm:ss', | |||||
| }, | |||||
| }} | |||||
| /> | |||||
| </FormControl> | |||||
| </Grid> | </Grid> | ||||
| <Grid item xs={3}> | <Grid item xs={3}> | ||||
| <Controller | |||||
| control={control} | |||||
| name="normalHourTo" | |||||
| rules={{ required: true }} | |||||
| render={({ field }) => { | |||||
| return ( | |||||
| <TimePicker | |||||
| label="Normal Hour To" | |||||
| inputRef={field.ref} | |||||
| onChange={(time) => { | |||||
| const formattedTime = time ? dayjs(time as string).format('HH:mm:ss') : ''; | |||||
| field.onChange(formattedTime); | |||||
| }} | |||||
| sx={{ width: '100%' }} | |||||
| /> | |||||
| ); | |||||
| }} | |||||
| /> | |||||
| <FormControl fullWidth> | |||||
| <TimePicker | |||||
| label={t("Normal Hour To")} | |||||
| value={content.normalHourTo !== undefined && content.normalHourTo !== null ? | |||||
| dayjs().hour(content.normalHourTo[0]).minute(content.normalHourTo[1]) : | |||||
| dayjs().hour(18).minute(0)} | |||||
| onChange={(time) => { | |||||
| if (!time) return; | |||||
| setValue("normalHourTo", time.format("HH:mm:ss")); | |||||
| }} | |||||
| slotProps={{ | |||||
| textField: { | |||||
| helperText: 'HH:mm:ss', | |||||
| }, | |||||
| }} | |||||
| /> | |||||
| </FormControl> | |||||
| </Grid> | </Grid> | ||||
| <Grid item xs={3}> | <Grid item xs={3}> | ||||
| <Controller | |||||
| control={control} | |||||
| name="otHourFrom" | |||||
| rules={{ required: true }} | |||||
| render={({ field }) => { | |||||
| return ( | |||||
| <TimePicker | |||||
| label="OT Hour From" | |||||
| inputRef={field.ref} | |||||
| onChange={(time) => { | |||||
| const formattedTime = time ? dayjs(time as string).format('HH:mm:ss') : ''; | |||||
| field.onChange(formattedTime); | |||||
| }} | |||||
| sx={{ width: '100%' }} | |||||
| /> | |||||
| ); | |||||
| }} | |||||
| /> | |||||
| <FormControl fullWidth> | |||||
| <TimePicker | |||||
| label={t("OT Hour From")} | |||||
| value={content.otHourFrom !== undefined && content.otHourFrom !== null ? | |||||
| dayjs().hour(content.otHourFrom[0]).minute(content.otHourFrom[1]) : | |||||
| dayjs().hour(20).minute(0)} | |||||
| onChange={(time) => { | |||||
| if (!time) return; | |||||
| setValue("otHourFrom", time.format("HH:mm:ss")); | |||||
| }} | |||||
| slotProps={{ | |||||
| textField: { | |||||
| helperText: 'HH:mm:ss', | |||||
| }, | |||||
| }} | |||||
| /> | |||||
| </FormControl> | |||||
| </Grid> | </Grid> | ||||
| <Grid item xs={3}> | <Grid item xs={3}> | ||||
| <Controller | |||||
| control={control} | |||||
| name="otHourTo" | |||||
| rules={{ required: true }} | |||||
| render={({ field }) => { | |||||
| return ( | |||||
| <TimePicker | |||||
| label="OT Hour To" | |||||
| inputRef={field.ref} | |||||
| onChange={(time) => { | |||||
| const formattedTime = time ? dayjs(time as string).format('HH:mm:ss') : ''; | |||||
| field.onChange(formattedTime); | |||||
| }} | |||||
| sx={{ width: '100%' }} | |||||
| /> | |||||
| ); | |||||
| }} | |||||
| /> | |||||
| <FormControl fullWidth> | |||||
| <TimePicker | |||||
| label={t("OT Hour To")} | |||||
| value={content.otHourTo !== undefined && content.otHourTo !== null ? | |||||
| dayjs().hour(content.otHourTo[0]).minute(content.otHourTo[1]) : | |||||
| dayjs().hour(8).minute(0)} | |||||
| onChange={(time) => { | |||||
| if (!time) return; | |||||
| setValue("otHourTo", time.format("HH:mm:ss")); | |||||
| }} | |||||
| slotProps={{ | |||||
| textField: { | |||||
| helperText: 'HH:mm:ss', | |||||
| }, | |||||
| }} | |||||
| /> | |||||
| </FormControl> | |||||
| </Grid> | </Grid> | ||||
| <Grid item xs={6}> | <Grid item xs={6}> | ||||
| <TextField | <TextField | ||||
| @@ -4,9 +4,9 @@ import Check from "@mui/icons-material/Check"; | |||||
| import Close from "@mui/icons-material/Close"; | import Close from "@mui/icons-material/Close"; | ||||
| import Button from "@mui/material/Button"; | import Button from "@mui/material/Button"; | ||||
| import Stack from "@mui/material/Stack"; | import Stack from "@mui/material/Stack"; | ||||
| import { CreateCompanyInputs, saveCompany } from "@/app/api/companys/actions"; | |||||
| import { CreateCompanyInputs, EditCompanyInputs, saveCompany } from "@/app/api/companys/actions"; | |||||
| import { useRouter } from "next/navigation"; | import { useRouter } from "next/navigation"; | ||||
| import React, { useCallback, useState } from "react"; | |||||
| import React, { useCallback, useDebugValue, useEffect, useState } from "react"; | |||||
| import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
| import { | import { | ||||
| FieldErrors, | FieldErrors, | ||||
| @@ -19,9 +19,16 @@ import CompanyDetails from "./CompanyDetails"; | |||||
| import { LocalizationProvider } from '@mui/x-date-pickers'; | import { LocalizationProvider } from '@mui/x-date-pickers'; | ||||
| import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs' | import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs' | ||||
| import dayjs from "dayjs"; | import dayjs from "dayjs"; | ||||
| import { convertTimeArrayToString } from "@/app/utils/formatUtil"; | |||||
| const CreateCompany: React.FC = ({ | |||||
| interface Props { | |||||
| isEdit: Boolean; | |||||
| company?: EditCompanyInputs; | |||||
| } | |||||
| const CreateCompany: React.FC<Props> = ({ | |||||
| isEdit, | |||||
| company, | |||||
| }) => { | }) => { | ||||
| const [serverError, setServerError] = useState(""); | const [serverError, setServerError] = useState(""); | ||||
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| @@ -55,23 +62,24 @@ const CreateCompany: React.FC = ({ | |||||
| const formProps = useForm<CreateCompanyInputs>({ | const formProps = useForm<CreateCompanyInputs>({ | ||||
| defaultValues: { | defaultValues: { | ||||
| companyCode: "", | |||||
| companyName: "", | |||||
| brNo: "", | |||||
| contactName: "", | |||||
| phone: "", | |||||
| id: company?.id, | |||||
| companyCode: company?.companyCode, | |||||
| companyName: company?.name, | |||||
| brNo: company?.brNo, | |||||
| contactName: company?.contactName, | |||||
| phone: company?.phone, | |||||
| otHourTo: "", | otHourTo: "", | ||||
| otHourFrom: "", | otHourFrom: "", | ||||
| normalHourTo: dayjs().format('HH:mm:ss'), | |||||
| normalHourFrom: dayjs().format('HH:mm:ss'), | |||||
| currency: "", | |||||
| address: "", | |||||
| district: "", | |||||
| email: "", | |||||
| normalHourTo: "", | |||||
| normalHourFrom: "", | |||||
| currency: company?.currency, | |||||
| address: company?.address, | |||||
| district: company?.district, | |||||
| email: company?.email, | |||||
| }, | }, | ||||
| }); | }); | ||||
| const errors = formProps.formState.errors; | |||||
| const errors = formProps.formState.errors; | |||||
| return( | return( | ||||
| <FormProvider {...formProps}> | <FormProvider {...formProps}> | ||||
| @@ -82,7 +90,16 @@ const CreateCompany: React.FC = ({ | |||||
| > | > | ||||
| { | { | ||||
| <LocalizationProvider dateAdapter={AdapterDayjs}> | <LocalizationProvider dateAdapter={AdapterDayjs}> | ||||
| <CompanyDetails /> | |||||
| <CompanyDetails | |||||
| content={ | |||||
| { | |||||
| normalHourFrom: company?.normalHourFrom as number[], | |||||
| normalHourTo: company?.normalHourTo as number[], | |||||
| otHourFrom: company?.otHourFrom as number[], | |||||
| otHourTo: company?.otHourTo as number[] | |||||
| } | |||||
| } | |||||
| /> | |||||
| </LocalizationProvider> | </LocalizationProvider> | ||||
| } | } | ||||
| @@ -1,8 +1,24 @@ | |||||
| import { fetchCompanyDetails } from "@/app/api/companys"; | |||||
| import CreateCompany from "./CreateCompany"; | import CreateCompany from "./CreateCompany"; | ||||
| const CreateCompanyWrapper: React.FC = async () => { | |||||
| type CreateCompanyProps = {isEdit: false} | |||||
| interface EditCompanyProps { | |||||
| isEdit: true; | |||||
| companyId?: string; | |||||
| } | |||||
| type Props = CreateCompanyProps | EditCompanyProps; | |||||
| const CreateCompanyWrapper: React.FC<Props> = async (props) => { | |||||
| console.log(props) | |||||
| const companyDetails = props.isEdit | |||||
| ? await fetchCompanyDetails(props.companyId!) | |||||
| : undefined; | |||||
| return ( | return ( | ||||
| <CreateCompany | |||||
| <CreateCompany isEdit company={companyDetails} | |||||
| /> | /> | ||||
| ) | ) | ||||
| } | } | ||||
| @@ -208,7 +208,7 @@ const InvoiceSearch: React.FC<Props> = ({ issuedInvoice, receivedInvoice }) => { | |||||
| { name: "paymentMilestone", label: t("Payment Milestone") }, | { name: "paymentMilestone", label: t("Payment Milestone") }, | ||||
| { name: "invoiceDate", label: t("Invocie Date") }, | { name: "invoiceDate", label: t("Invocie Date") }, | ||||
| { name: "dueDate", label: t("Due Date") }, | { name: "dueDate", label: t("Due Date") }, | ||||
| { name: "issuedAmount", label: t("Amount (HKD") }, | |||||
| { name: "issuedAmount", label: t("Amount (HKD)") }, | |||||
| ], | ], | ||||
| [t], | [t], | ||||
| ); | ); | ||||
| @@ -316,7 +316,7 @@ const InvoiceSearch: React.FC<Props> = ({ issuedInvoice, receivedInvoice }) => { | |||||
| } | } | ||||
| <Tabs value={tabIndex} onChange={handleTabChange} variant="scrollable"> | <Tabs value={tabIndex} onChange={handleTabChange} variant="scrollable"> | ||||
| <Tab label={t("Issued Invoices")}/> | <Tab label={t("Issued Invoices")}/> | ||||
| <Tab label={t("Recieved Invoices")}/> | |||||
| <Tab label={t("Received Invoices")}/> | |||||
| </Tabs> | </Tabs> | ||||
| { | { | ||||
| tabIndex == 0 && | tabIndex == 0 && | ||||