"chore: update frontend dev script to include lint checks and add ESLint config file"

This commit is contained in:
louiscklaw
2025-06-04 02:35:32 +08:00
parent c0fad42f0a
commit 22fb620eef
48 changed files with 3315 additions and 97 deletions

View File

@@ -1,7 +1,7 @@
// src/actions/invoice.ts
import { useMemo } from 'react';
import axiosInstance, { endpoints, fetcher } from 'src/lib/axios';
import type { IInvoiceItem } from 'src/types/invoice';
import type { IInvoiceItem, SaveInvoiceData } from 'src/types/invoice';
import type { SWRConfiguration } from 'swr';
import useSWR from 'swr';
@@ -97,7 +97,7 @@ export function useSearchInvoices(query: string) {
// ----------------------------------------------------------------------
type SaveInvoiceData = IInvoiceItem;
// type SaveInvoiceData = IInvoiceItem;
export async function saveInvoice(invoiceId: string, saveInvoiceData: SaveInvoiceData) {
const url = endpoints.invoice.saveInvoice(invoiceId);

View File

@@ -99,6 +99,7 @@ export function useSearchProducts(query: string) {
type SaveProductData = {
// id: string;
sku: string;
name: string;
code: string;

View File

@@ -17,6 +17,8 @@ export type SignUpParams = {
lastName: string;
};
const ERR_ACCESS_TOKEN_NOT_FOUND = `Access token not found in response`;
/** **************************************
* Sign in
*************************************** */
@@ -29,7 +31,7 @@ export const signInWithPassword = async ({ email, password }: SignInParams): Pro
const { accessToken } = res.data;
if (!accessToken) {
throw new Error('Access token not found in response');
throw new Error(ERR_ACCESS_TOKEN_NOT_FOUND);
}
setSession(accessToken);

View File

@@ -69,6 +69,8 @@ export function tokenExpired(exp: number) {
// ----------------------------------------------------------------------
const INVALID_ACCESS_TOKEN = 'Invalid access token!';
export async function setSession(accessToken: string | null) {
try {
if (accessToken) {
@@ -81,7 +83,7 @@ export async function setSession(accessToken: string | null) {
if (decodedToken && 'exp' in decodedToken) {
tokenExpired(decodedToken.exp);
} else {
throw new Error('Invalid access token!');
throw new Error(INVALID_ACCESS_TOKEN);
}
} else {
sessionStorage.removeItem(JWT_STORAGE_KEY);

View File

@@ -11,7 +11,7 @@ const metadata = { title: `User edit | Dashboard - ${CONFIG.appName}` };
export default function Page() {
const { id = '' } = useParams();
// TODO: remove me
// TODO: remove unused code
// const currentUser = _userList.find((user) => user.id === id);
const { user } = useGetUser(id);

View File

@@ -106,7 +106,8 @@ export function CalendarToolbar({
<Iconify icon="eva:arrow-ios-back-fill" />
</IconButton>
<Typography variant="h6">{date}</Typography>
{/* FIXME: no raw json output in html */}
<Typography variant="h6">{JSON.stringify({ date })}</Typography>
<IconButton onClick={onNextDate}>
<Iconify icon="eva:arrow-ios-forward-fill" />

View File

@@ -37,19 +37,22 @@ export function InvoiceDetails({ invoice }: Props) {
const { t } = useTranslation();
const [currentStatus, setCurrentStatus] = useState(invoice?.status);
const handleChangeStatus = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
// setCurrentStatus(event.target.value);
const handleChangeStatus = useCallback(
(event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
// setCurrentStatus(event.target.value);
try {
changeStatus(invoice.id, event.target.value);
setCurrentStatus(event.target.value);
try {
changeStatus(invoice.id, event.target.value);
setCurrentStatus(event.target.value);
toast.success('status changed!');
} catch (error) {
console.error(error);
toast.warning('error during changing status');
}
}, []);
toast.success('status changed!');
} catch (error) {
console.error(error);
toast.warning('error during changing status');
}
},
[]
);
const renderFooter = () => (
<Box

View File

@@ -1,4 +1,4 @@
import type { IInvoiceItem } from 'src/types/invoice';
import type { IInvoiceItem, IInvoiceItemItem } from 'src/types/invoice';
import { sumBy } from 'es-toolkit';
import { useEffect, useCallback } from 'react';
@@ -22,7 +22,7 @@ import { InvoiceTotalSummary } from './invoice-total-summary';
// ----------------------------------------------------------------------
export const defaultItem: Omit<IInvoiceItem, 'id'> = {
export const defaultItem: Omit<IInvoiceItemItem, 'id'> = {
title: '',
description: '',
service: INVOICE_SERVICE_OPTIONS[0].name,
@@ -50,7 +50,7 @@ export function InvoiceNewEditDetails() {
const discount = getValues('discount');
const shipping = getValues('shipping');
const subtotal = sumBy(items, (item: IInvoiceItem) => item.quantity * item.price);
const subtotal = sumBy(items, (item: IInvoiceItemItem) => item.quantity * item.price);
const subtotalWithTax = subtotal + subtotal * (taxes / 100);
const totalAmount = subtotalWithTax - discount - shipping;

View File

@@ -81,6 +81,8 @@ export function InvoiceNewEditForm({ currentInvoice }: Props) {
const loadingSend = useBoolean();
const defaultValues: NewInvoiceSchemaType = {
id: '',
sent: 0,
invoiceNumber: 'INV-1990',
createDate: today(),
dueDate: null,
@@ -129,6 +131,8 @@ export function InvoiceNewEditForm({ currentInvoice }: Props) {
try {
if (currentInvoice) {
data.dueDate = '2029-01-01';
await saveInvoice(currentInvoice.id, data);
}

View File

@@ -27,7 +27,7 @@ type Props = {
invoice?: IInvoiceItem;
currentStatus: string;
statusOptions: { value: string; label: string }[];
onChangeStatus: (event: React.ChangeEvent<HTMLInputElement>) => void;
onChangeStatus: (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
};
export function InvoiceToolbar({ invoice, currentStatus, statusOptions, onChangeStatus }: Props) {

View File

@@ -19,7 +19,7 @@ export type IAddressItem = {
addressType?: string;
};
export type IDateValue = string | number | null;
export type IDateValue = string | number | Date | null;
export type IDatePickerControl = Dayjs | null;

View File

@@ -13,15 +13,16 @@ export type IInvoiceTableFilters = {
export type IInvoiceItemItem = {
id: string;
title: string;
service: string;
price: number;
total: number;
service: string;
quantity: number;
description: string;
};
export type IInvoiceItem = {
id: string;
sent: number;
taxes: number;
status: string;
@@ -36,3 +37,26 @@ export type IInvoiceItem = {
invoiceTo: IAddressItem;
invoiceFrom: IAddressItem;
};
export type SaveInvoiceData = {
sent: number;
taxes: number;
status: string;
subtotal: number;
discount: number;
shipping: number;
totalAmount: number;
dueDate: IDateValue;
invoiceNumber: string;
items: {
title: string;
service: string;
price: number;
total: number;
quantity: number;
description: string;
}[];
createDate: IDateValue;
invoiceTo: IAddressItem | null;
invoiceFrom: IAddressItem | null;
};