From 3011a69432b454bed6a58b5de33bf00dc123e79f Mon Sep 17 00:00:00 2001 From: Waldemar Date: Mon, 23 Dec 2024 19:32:51 +0200 Subject: [PATCH] chore: add new rules to eslint cfg --- app/lib/actions.ts | 18 ++++++++++++++++++ app/lib/data.ts | 6 ++++++ app/lib/helpers.ts | 13 +++++++++++++ app/lib/hooks.ts | 3 +++ app/page.tsx | 3 +++ app/ui/categories/categories.tsx | 2 ++ app/ui/home/search.tsx | 2 ++ app/ui/home/transaction-form.tsx | 1 + app/ui/home/transaction-list.tsx | 1 + app/ui/limits/limits.tsx | 5 +++++ app/ui/monthly-report/monthly-report.tsx | 3 +++ app/ui/transaction-form-edit.tsx | 3 +++ eslint.config.mjs | 12 ++++++++++-- middleware.ts | 2 ++ types.d.ts | 2 +- 15 files changed, 73 insertions(+), 3 deletions(-) diff --git a/app/lib/actions.ts b/app/lib/actions.ts index f84b2c3..3b8a133 100644 --- a/app/lib/actions.ts +++ b/app/lib/actions.ts @@ -40,6 +40,7 @@ import type { export const getAuthSession = async (): Promise => { try { const session = await auth() + return session } catch (err) { throw err @@ -72,13 +73,16 @@ export async function getBalance( ] as TBalanceProjection).lean({ transform: (doc: TRawTransaction) => { delete doc?._id + return doc }, }) const balance = transactions.reduce((acc, t) => { const amount = parseFloat(t.amount) + return t.isIncome ? acc + amount : acc - amount }, 0) + return balance.toString() } catch (err) { throw err @@ -98,6 +102,7 @@ export async function getTransactionLimit( { userId }, { transactionLimit: 1, _id: 0 }, ).lean<{ transactionLimit: TTransaction['transactionLimit'] }>() + return transaction?.transactionLimit } catch (err) { throw err @@ -117,6 +122,7 @@ export async function getCurrency( { userId }, { currency: 1, _id: 0 }, ).lean<{ currency: TTransaction['currency'] }>() + return transaction?.currency } catch (err) { throw err @@ -267,6 +273,7 @@ export async function getCountDocuments( } try { await dbConnect() + return await TransactionModel.countDocuments({ userId }) } catch (err) { throw err @@ -293,12 +300,14 @@ export async function getTransactions( transform: (doc: TRawTransaction) => { delete doc?._id delete doc?.__v + return doc }, }), getCountDocuments(userId), ]) const totalPages = Math.ceil(totalEntries / limit) + return { transactions, totalEntries, totalPages } } catch (err) { throw err @@ -314,10 +323,12 @@ export async function getAllTransactions( } try { await dbConnect() + return TransactionModel.find({ userId }).lean({ transform: (doc: TRawTransaction) => { delete doc?._id delete doc?.__v + return doc }, }) @@ -458,9 +469,11 @@ export async function findTransactionById( transform: (doc: TRawTransaction) => { delete doc?._id delete doc?.__v + return doc }, }) + return transaction } catch (err) { throw err @@ -560,6 +573,7 @@ export async function editCategoryLimit( limitAmount: newLimitAmount, } } + return limit }, ) @@ -588,6 +602,7 @@ export async function getCategoryItemNameAI( const content = await CompletionAIModel.generateContent(prompt) const text = content.response.text().trim() + return text } catch (err) { throw err @@ -608,6 +623,7 @@ export async function getAmountAI( const content = await CompletionAIModel.generateContent(prompt) const text = content.response.text().trim() + return text } catch (err) { throw err @@ -627,6 +643,7 @@ export async function getTransactionTypeAI( const content = await CompletionAIModel.generateContent(prompt) const text = content.response.text().trim() + return text } catch (err) { throw err @@ -646,6 +663,7 @@ export async function getExpenseTipsAI(categories: string[]): Promise { const content = await ExpenseTipsAIModel.generateContent(prompt) const text = content.response.text().trim() + return text } catch (err) { throw err diff --git a/app/lib/data.ts b/app/lib/data.ts index d6eaaad..b96c276 100644 --- a/app/lib/data.ts +++ b/app/lib/data.ts @@ -22,6 +22,7 @@ export const filterTransactions = (transactions: TTransaction[]) => ({ export const getTransactionsTotals = (transactions: TTransaction[]) => { const { income, expense } = filterTransactions(transactions) + return { income: calculateTotalAmount(income), expense: calculateTotalAmount(expense), @@ -38,6 +39,7 @@ export const calculateChartData = ( t.category, (totals.get(t.category) || 0) + parseFloat(t.amount), ) + return totals }, new Map()) @@ -52,6 +54,7 @@ export const calculateChartData = ( const chartData: TChartData[] = Array.from(allCategories).map((category) => { const expense = categoryExpenseTotals.get(category) || 0 const income = categoryIncomeTotals.get(category) || 0 + return { category, income, @@ -73,6 +76,7 @@ export const calculateTotalsByCategory = ( : category totals[modifiedCategory] = (totals[modifiedCategory] || 0) + parseFloat(amount) + return totals }, {} as Record, @@ -117,6 +121,7 @@ export const filterTransactionsByDateRange = ( ): TTransaction[] => { return transactions.filter((t) => { const transactionDate = formatISO(t.createdAt) + return isWithinInterval(transactionDate, { start: startDate, end: endOfDay(endDate), @@ -141,6 +146,7 @@ export const getMinMaxTransactionsByDate = ( ) { acc.maxTransaction = transaction } + return acc }, { minTransaction: null, maxTransaction: null }, diff --git a/app/lib/helpers.ts b/app/lib/helpers.ts index 75418c3..8a7e5c3 100644 --- a/app/lib/helpers.ts +++ b/app/lib/helpers.ts @@ -53,6 +53,7 @@ export const getBreakpointWidth = ( export const capitalizeFirstLetter = (str: string): string => { if (!str) return str + return str.charAt(0).toUpperCase() + str.slice(1) } @@ -61,6 +62,7 @@ export const getEmojiFromCategory = ( ): string => { const regex = emojiRegex() const match = category.match(regex) + return match ? match[0] : '' } @@ -68,6 +70,7 @@ export const getCategoryWithoutEmoji = ( category: TTransaction['category'], ): string => { const regex = emojiRegex() + // Replace the emoji(s) at the beginning of the category with an empty string return category.replace(regex, '').trim() } @@ -103,6 +106,7 @@ export const formatDate = (dateStr: Date) => { if (isToday(date)) return 'Today' if (isYesterday(date)) return 'Yesterday' if (dateYear !== currentYear) return format(date, 'EEEE, MMMM d, yyyy') + return format(date, 'EEEE, MMMM d') } @@ -110,6 +114,7 @@ export const formatTime = (dateStr: Date): string => { const userTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone const date = new Date(dateStr) const formatStr = userTimeZone.includes('America') ? 'hh:mm a' : 'HH:mm' + return formatInTimeZone(date, userTimeZone || DEFAULT_TIME_ZONE, formatStr) } @@ -132,6 +137,7 @@ export const getCategoryWithEmoji = ( return `${foundCategory.emoji} ${category}` } } + return category } @@ -156,11 +162,13 @@ export const getFormattedCurrency = ( if (isAmountHidden) return '*'.repeat(numericValue.toString().length) const formattedNumber = new Intl.NumberFormat('de-DE').format(numericValue) + return formattedNumber.replace(/\./g, ' ') } export const getFormattedBalance = (balance: TTransaction['balance']) => { const formattedCurrency = getFormattedCurrency(balance) + return Number(balance) < 0 ? `- ${formattedCurrency.slice(1)}` : formattedCurrency @@ -171,6 +179,7 @@ export const formatAmount = (value: string): string => { ?.replace(/\s/g, '') ?.replace(',', '.') ?.replace(/^0+/, '') + return rawAmount } @@ -184,6 +193,7 @@ export const calculateEntryRange = ( const parsedTotalEntries = toNumber(totalEntries) const startEntry = (parsedPage - 1) * parsedLimit + 1 const endEntry = Math.min(parsedPage * parsedLimit, parsedTotalEntries) + return { startEntry, endEntry } } @@ -197,6 +207,7 @@ export const copyToClipboard = async ( if (!content) { toast.error(errorTitle) + return } try { @@ -280,6 +291,7 @@ export const pluralize = ( ): string => { const pluralRules = new Intl.PluralRules(DEFAULT_LANG) const pluralCategory = pluralRules.select(count) + return pluralCategory === 'one' || pluralCategory === 'zero' || count === 0 ? singular : plural @@ -307,6 +319,7 @@ export const getCategoryItemNames = ( categories: TTransaction['categories'], ) => { if (!categories) return [] + return categories .flatMap((subject) => subject.items.map((item) => item.name)) .filter(Boolean) // Remove empty strings diff --git a/app/lib/hooks.ts b/app/lib/hooks.ts index 52816e2..03e5830 100644 --- a/app/lib/hooks.ts +++ b/app/lib/hooks.ts @@ -30,14 +30,17 @@ const useAttemptTracker = ( // Reset attempts if attemptResetInterval or ATTEMPT_RESET_INTERVAL number value have passed. if (currentTime - lastAttemptTime > attemptResetInterval) { resetAttempts() + return true } + return count < attemptLimit }, [attemptLimit, attemptResetInterval, attemptsData, resetAttempts]) const registerAttempt = useCallback(() => { if (!attemptsData) { setAttemptsData({ count: 1, lastAttemptTime: Date.now() }) + return } const { count } = attemptsData diff --git a/app/page.tsx b/app/page.tsx index 2c4c8ee..0ca4615 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -107,6 +107,7 @@ export default async function Home(props: { acc[date] = [] } acc[date].unshift(t) + return acc }, {}) @@ -119,10 +120,12 @@ export default async function Home(props: { } else { totals.expense += parseFloat(t.amount) } + return totals }, { income: 0, expense: 0 }, ) + return [date, totals] }), ) diff --git a/app/ui/categories/categories.tsx b/app/ui/categories/categories.tsx index fc4511c..ac8cc59 100644 --- a/app/ui/categories/categories.tsx +++ b/app/ui/categories/categories.tsx @@ -80,6 +80,7 @@ function Categories({ userId, userCategories }: TProps) { setEditingIndex(null) setNewTargetName('') toast.error('No changes detected.') + return } @@ -141,6 +142,7 @@ function Categories({ userId, userCategories }: TProps) { setEditingItemIndex(null) setNewItemName('') toast.error('No changes detected.') + return } diff --git a/app/ui/home/search.tsx b/app/ui/home/search.tsx index d6a5fa1..4a296d2 100644 --- a/app/ui/home/search.tsx +++ b/app/ui/home/search.tsx @@ -52,6 +52,7 @@ export default function Search({ hasSearchedTransactionsByQuery }: TProps) { if (newState) { isInitialExpanded.current = true } + return newState }) } @@ -64,6 +65,7 @@ export default function Search({ hasSearchedTransactionsByQuery }: TProps) { // Skip the first render if (isInitialRender.current) { isInitialRender.current = false + return } diff --git a/app/ui/home/transaction-form.tsx b/app/ui/home/transaction-form.tsx index fbd4167..182b801 100644 --- a/app/ui/home/transaction-form.tsx +++ b/app/ui/home/transaction-form.tsx @@ -119,6 +119,7 @@ function TransactionForm({ currency, userCategories }: TProps) { ): Promise => { if (!trimmedDescription) { resetAIRelatedStates() + return [() => null, () => undefined] } diff --git a/app/ui/home/transaction-list.tsx b/app/ui/home/transaction-list.tsx index aef71df..6154a35 100644 --- a/app/ui/home/transaction-list.tsx +++ b/app/ui/home/transaction-list.tsx @@ -69,6 +69,7 @@ function TransactionList({ ?.sort((t1, t2) => { const t1Time = new Date(t1.createdAt).getTime() const t2Time = new Date(t2.createdAt).getTime() + return t2Time - t1Time }) .map((t) => { diff --git a/app/ui/limits/limits.tsx b/app/ui/limits/limits.tsx index 0891c9a..6b44853 100644 --- a/app/ui/limits/limits.tsx +++ b/app/ui/limits/limits.tsx @@ -171,6 +171,7 @@ function Limits({ userId, currency, transactions, userCategories }: TProps) { const getLimitAmount = (categoryName: string) => { const limit = userLimitsData.find((l) => l.categoryName === categoryName) + return limit ? limit.limitAmount : null } @@ -209,6 +210,7 @@ function Limits({ userId, currency, transactions, userCategories }: TProps) { ) => { if (!categoryName) { toast.error('Invalid category name.') + return } setIsLoadingDelete(true) @@ -245,14 +247,17 @@ function Limits({ userId, currency, transactions, userCategories }: TProps) { ) => { if (!categoryName) { toast.error('Invalid category name.') + return } if (!limitAmount) { toast.error('Invalid limit amount.') + return } if (limitAmount === tempLimitAmount) { toast.error('Limit amount is the same.') + return } setIsLoadingEdit(true) diff --git a/app/ui/monthly-report/monthly-report.tsx b/app/ui/monthly-report/monthly-report.tsx index 2476e9b..2d03a65 100644 --- a/app/ui/monthly-report/monthly-report.tsx +++ b/app/ui/monthly-report/monthly-report.tsx @@ -76,6 +76,7 @@ function MonthlyReport({ transactions, currency }: TProps) { const formattedDateRange = useMemo(() => { if (!startDate || !endDate) return '' + return `${format(startDate, 'MMMM d')} — ${format(endDate, 'MMMM d')}` }, [startDate, endDate]) @@ -106,10 +107,12 @@ function MonthlyReport({ transactions, currency }: TProps) { const getExpenseTipsAIData = useCallback(async () => { if (monthlyReportData.length === 0) { toast.error('No expenses found.') + return } if (!canAttempt()) { toast.error('Try again later.') + return } setIsLoadingTips(true) diff --git a/app/ui/transaction-form-edit.tsx b/app/ui/transaction-form-edit.tsx index 75a51d0..7412721 100644 --- a/app/ui/transaction-form-edit.tsx +++ b/app/ui/transaction-form-edit.tsx @@ -86,8 +86,10 @@ function TransactionFormEdit({ transaction }: TProps) { ...oldData, amount: getFormattedCurrency(oldData.amount, false), } + return Object.keys(newData).some((key) => { const newKey = key as keyof typeof newData + return ( newData[newKey] !== undefined && newData[newKey] !== modifiedOldData[newKey] @@ -111,6 +113,7 @@ function TransactionFormEdit({ transaction }: TProps) { if (!hasChanges(newTransactionData, transaction)) { toast.error('No changes detected.') setIsLoading(false) + return } newTransactionData.isEdited = true diff --git a/eslint.config.mjs b/eslint.config.mjs index 7f5f51a..2658d1d 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -29,6 +29,14 @@ const config = [ 'react/jsx-props-no-spreading': 'off', 'react/no-unused-prop-types': 'off', 'react/require-default-props': 'off', + 'react/function-component-definition': [ + 'error', + { namedComponents: 'function-declaration' }, + ], + 'padding-line-between-statements': [ + 'error', + { blankLine: 'always', prev: '*', next: 'return' }, + ], 'import/extensions': [ 'error', @@ -73,8 +81,8 @@ const config = [ '@typescript-eslint/explicit-module-boundary-types': 'off', 'no-use-before-define': [0], '@typescript-eslint/no-use-before-define': [1], - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/no-var-requires': 'off', + '@typescript-eslint/no-explicit-any': 'error', + '@typescript-eslint/no-var-requires': 'error', }, }, { diff --git a/middleware.ts b/middleware.ts index 585e815..b2a3c9f 100644 --- a/middleware.ts +++ b/middleware.ts @@ -10,11 +10,13 @@ export default auth((req: NextRequest & { auth: TSession }) => { if (!req.auth) { url.pathname = ROUTE.SIGNIN + return NextResponse.rewrite(url) } if (req.nextUrl.pathname === ROUTE.SIGNIN) { url.pathname = ROUTE.HOME + return NextResponse.rewrite(url) } diff --git a/types.d.ts b/types.d.ts index 98f1882..c302b29 100644 --- a/types.d.ts +++ b/types.d.ts @@ -7,7 +7,7 @@ declare module '*.svg' { } declare module '*.svg?url' { - const content: any + const content: unknown export default content }