refactor(accounts): unify account type icons via accountIconByType helper (#180)
## Why ### Problem Account type icons were defined in two separate places — `step-account-types.tsx` (onboarding) and `account-type-icon.tsx` (dashboard) — using different icon choices for the same account types. For example, `checking` showed `Building2` on the dashboard but `Wallet` in onboarding, and `retirement` showed `Umbrella` vs `TrendingUp`. This created a visually inconsistent experience. ## What ### Changes - Added `accountIconByType(type: AccountType): LucideIcon` helper to `resources/js/types/account.ts` as the single source of truth for account type icons - Updated `AccountTypeIcon` component to delegate to the new helper instead of maintaining its own map - Updated `StepAccountTypes` to derive icons from the helper instead of storing them inline per entry - Dashboard account cards now use the same icon set as the onboarding screen (Wallet, PiggyBank, CreditCard, LineChart, TrendingUp, Building2) ## Verification ### Tests No behaviour change — purely a refactor consolidating icon mapping into one place. Existing tests remain unaffected.
This commit is contained in:
parent
edcadace1a
commit
186ae57c2d
|
|
@ -1,16 +1,5 @@
|
|||
import { cn } from '@/lib/utils';
|
||||
import { AccountType } from '@/types/account';
|
||||
import {
|
||||
BadgeQuestionMarkIcon,
|
||||
Building2,
|
||||
CreditCard,
|
||||
FolderKanban,
|
||||
Landmark,
|
||||
LucideIcon,
|
||||
PiggyBank,
|
||||
TrendingUp,
|
||||
Umbrella,
|
||||
} from 'lucide-react';
|
||||
import { AccountType, accountIconByType } from '@/types/account';
|
||||
|
||||
export function AccountTypeIcon({
|
||||
type,
|
||||
|
|
@ -19,17 +8,7 @@ export function AccountTypeIcon({
|
|||
type: AccountType;
|
||||
className?: string;
|
||||
}) {
|
||||
const typeMap: Record<AccountType, LucideIcon> = {
|
||||
checking: Building2, // 🏦 - bank / institution
|
||||
credit_card: CreditCard, // 💳 - card
|
||||
investment: TrendingUp, // 📈 - growth / investment
|
||||
loan: Landmark, // 🏠 - "institution/loan", or use Home if it's a mortgage
|
||||
retirement: Umbrella, // 🏖️ - retirement / pension
|
||||
savings: PiggyBank, // 💰 - savings
|
||||
others: FolderKanban, // 📁 - miscellaneous/other
|
||||
};
|
||||
|
||||
const Icon = typeMap[type] || BadgeQuestionMarkIcon;
|
||||
const Icon = accountIconByType(type);
|
||||
|
||||
return (
|
||||
<Icon className={cn(['h-5 w-5 text-muted-foreground', className])} />
|
||||
|
|
|
|||
|
|
@ -1,15 +1,8 @@
|
|||
import { StepButton } from '@/components/onboarding/step-button';
|
||||
import { StepHeader } from '@/components/onboarding/step-header';
|
||||
import { accountIconByType } from '@/types/account';
|
||||
import { __ } from '@/utils/i18n';
|
||||
import {
|
||||
Banknote,
|
||||
Building2,
|
||||
CreditCard,
|
||||
LineChart,
|
||||
PiggyBank,
|
||||
TrendingUp,
|
||||
Wallet,
|
||||
} from 'lucide-react';
|
||||
import { Banknote } from 'lucide-react';
|
||||
|
||||
interface StepAccountTypesProps {
|
||||
onContinue: () => void;
|
||||
|
|
@ -17,44 +10,38 @@ interface StepAccountTypesProps {
|
|||
|
||||
const accountTypes = [
|
||||
{
|
||||
type: 'checking',
|
||||
type: 'checking' as const,
|
||||
nameKey: 'Checking',
|
||||
icon: Wallet,
|
||||
descriptionKey: 'Daily spending and transactions',
|
||||
hasTransactions: true,
|
||||
},
|
||||
{
|
||||
type: 'savings',
|
||||
type: 'savings' as const,
|
||||
nameKey: 'Savings',
|
||||
icon: PiggyBank,
|
||||
descriptionKey: 'Save money for goals',
|
||||
hasTransactions: true,
|
||||
},
|
||||
{
|
||||
type: 'credit_card',
|
||||
type: 'credit_card' as const,
|
||||
nameKey: 'Credit Card',
|
||||
icon: CreditCard,
|
||||
descriptionKey: 'Track credit card spending',
|
||||
hasTransactions: true,
|
||||
},
|
||||
{
|
||||
type: 'investment',
|
||||
type: 'investment' as const,
|
||||
nameKey: 'Investment',
|
||||
icon: LineChart,
|
||||
descriptionKey: 'Stocks, ETFs, and portfolios',
|
||||
hasTransactions: false,
|
||||
},
|
||||
{
|
||||
type: 'retirement',
|
||||
type: 'retirement' as const,
|
||||
nameKey: 'Retirement',
|
||||
icon: TrendingUp,
|
||||
descriptionKey: '401k, IRA, pension funds',
|
||||
hasTransactions: false,
|
||||
},
|
||||
{
|
||||
type: 'loan',
|
||||
type: 'loan' as const,
|
||||
nameKey: 'Loan',
|
||||
icon: Building2,
|
||||
descriptionKey: 'Mortgages and loans',
|
||||
hasTransactions: false,
|
||||
},
|
||||
|
|
@ -73,41 +60,45 @@ export function StepAccountTypes({ onContinue }: StepAccountTypesProps) {
|
|||
/>
|
||||
|
||||
<div className="grid w-full max-w-2xl gap-3 sm:grid-cols-2">
|
||||
{accountTypes.map((account) => (
|
||||
<div
|
||||
key={account.type}
|
||||
className="group relative flex flex-row items-center gap-2 overflow-hidden rounded-xl border bg-card p-3 transition-all hover:shadow-md sm:items-start sm:p-4"
|
||||
>
|
||||
<div className="flex w-full flex-col items-start gap-1 sm:gap-2">
|
||||
<div className="flex w-full flex-row items-center justify-between gap-2 sm:items-start">
|
||||
<div className="flex items-center gap-2">
|
||||
<account.icon
|
||||
className={`size-4 stroke-muted-foreground`}
|
||||
/>
|
||||
{accountTypes.map((account) => {
|
||||
const Icon = accountIconByType(account.type);
|
||||
|
||||
<h3 className="font-semibold">
|
||||
{__(account.nameKey)}
|
||||
</h3>
|
||||
return (
|
||||
<div
|
||||
key={account.type}
|
||||
className="group relative flex flex-row items-center gap-2 overflow-hidden rounded-xl border bg-card p-3 transition-all hover:shadow-md sm:items-start sm:p-4"
|
||||
>
|
||||
<div className="flex w-full flex-col items-start gap-1 sm:gap-2">
|
||||
<div className="flex w-full flex-row items-center justify-between gap-2 sm:items-start">
|
||||
<div className="flex items-center gap-2">
|
||||
<Icon
|
||||
className={`size-4 stroke-muted-foreground`}
|
||||
/>
|
||||
|
||||
<h3 className="font-semibold">
|
||||
{__(account.nameKey)}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<span
|
||||
className={`inline-flex items-center rounded-full px-2 py-0.5 text-[10px] font-medium ${
|
||||
account.hasTransactions
|
||||
? 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400'
|
||||
: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400'
|
||||
}`}
|
||||
>
|
||||
{account.hasTransactions
|
||||
? __('Transactions + Balance')
|
||||
: __('Balance')}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<span
|
||||
className={`inline-flex items-center rounded-full px-2 py-0.5 text-[10px] font-medium ${
|
||||
account.hasTransactions
|
||||
? 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400'
|
||||
: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400'
|
||||
}`}
|
||||
>
|
||||
{account.hasTransactions
|
||||
? __('Transactions + Balance')
|
||||
: __('Balance')}
|
||||
</span>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{__(account.descriptionKey)}
|
||||
</p>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{__(account.descriptionKey)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="mt-8 w-full sm:w-auto">
|
||||
|
|
|
|||
|
|
@ -1,4 +1,15 @@
|
|||
import { __ } from '@/utils/i18n';
|
||||
import {
|
||||
BadgeQuestionMarkIcon,
|
||||
Building2,
|
||||
CreditCard,
|
||||
FolderKanban,
|
||||
LineChart,
|
||||
LucideIcon,
|
||||
PiggyBank,
|
||||
TrendingUp,
|
||||
Wallet,
|
||||
} from 'lucide-react';
|
||||
import { UUID } from './uuid';
|
||||
|
||||
export const ACCOUNT_TYPES = [
|
||||
|
|
@ -92,6 +103,20 @@ export function supportsInvestedAmount(
|
|||
return INVESTED_AMOUNT_ACCOUNT_TYPES.includes(account.type);
|
||||
}
|
||||
|
||||
export function accountIconByType(type: AccountType): LucideIcon {
|
||||
const typeMap: Record<AccountType, LucideIcon> = {
|
||||
checking: Wallet,
|
||||
credit_card: CreditCard,
|
||||
investment: LineChart,
|
||||
loan: Building2,
|
||||
retirement: TrendingUp,
|
||||
savings: PiggyBank,
|
||||
others: FolderKanban,
|
||||
};
|
||||
|
||||
return typeMap[type] ?? BadgeQuestionMarkIcon;
|
||||
}
|
||||
|
||||
export function filterTransactionalAccounts<T extends { type: AccountType }>(
|
||||
accounts: T[],
|
||||
): T[] {
|
||||
|
|
|
|||
Loading…
Reference in New Issue