refactor: update app.vue and various components to enhance UI consistency, replace color classes for improved accessibility, and refine layout for better user experience
This commit is contained in:
parent
7b4fb6c2fd
commit
24e8b7a3a8
41 changed files with 2395 additions and 1603 deletions
128
pages/budget.vue
128
pages/budget.vue
|
|
@ -11,7 +11,7 @@
|
|||
'px-4 py-2 font-medium transition-none',
|
||||
activeView === 'monthly'
|
||||
? 'bg-black text-white'
|
||||
: 'bg-white text-black hover:bg-zinc-100',
|
||||
: 'bg-white text-black hover:bg-neutral-100',
|
||||
]">
|
||||
Monthly
|
||||
</button>
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
'px-4 py-2 font-medium border-l-2 border-black transition-none',
|
||||
activeView === 'annual'
|
||||
? 'bg-black text-white'
|
||||
: 'bg-white text-black hover:bg-zinc-100',
|
||||
: 'bg-white text-black hover:bg-neutral-100',
|
||||
]">
|
||||
Annual
|
||||
</button>
|
||||
|
|
@ -48,14 +48,14 @@
|
|||
<div class="max-w-md mx-auto space-y-6">
|
||||
<div class="text-6xl">📊</div>
|
||||
<h3 class="text-xl font-bold text-black">No budget data found</h3>
|
||||
<p class="text-gray-600">
|
||||
<p class="text-neutral-600">
|
||||
Your budget is empty. Complete the setup wizard to add your revenue
|
||||
streams, team members, and expenses.
|
||||
</p>
|
||||
<div class="flex justify-center">
|
||||
<NuxtLink
|
||||
to="/coop-builder"
|
||||
class="inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-black hover:bg-zinc-800 border-2 border-black transition-colors">
|
||||
class="inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-black hover:bg-neutral-800 border-2 border-black transition-colors">
|
||||
Complete Setup Wizard
|
||||
</NuxtLink>
|
||||
</div>
|
||||
|
|
@ -79,7 +79,7 @@
|
|||
<th
|
||||
v-for="month in monthlyHeaders"
|
||||
:key="month.key"
|
||||
class="border-r border-gray-400 px-2 py-3 text-center font-medium min-w-[80px] last:border-r-0">
|
||||
class="border-r border-neutral-400 px-2 py-3 text-center font-medium min-w-[80px] last:border-r-0">
|
||||
{{ month.label }}
|
||||
</th>
|
||||
</tr>
|
||||
|
|
@ -94,7 +94,7 @@
|
|||
@click="showAddRevenueModal = true"
|
||||
size="xs"
|
||||
:ui="{
|
||||
base: 'bg-white text-black hover:bg-zinc-200 transition-none',
|
||||
base: 'bg-white text-black hover:bg-neutral-200 transition-none',
|
||||
}">
|
||||
+ Add
|
||||
</UButton>
|
||||
|
|
@ -107,9 +107,9 @@
|
|||
<template
|
||||
v-for="(items, categoryName) in groupedRevenue"
|
||||
:key="`revenue-${categoryName}`">
|
||||
<tr v-if="items.length > 0" class="border-t border-gray-300">
|
||||
<tr v-if="items.length > 0" class="border-t border-neutral-300">
|
||||
<td
|
||||
class="px-4 py-1 font-semibold sticky left-0 bg-zinc-100 z-10 border-black"
|
||||
class="px-4 py-1 font-semibold sticky left-0 bg-neutral-100 z-10 border-black"
|
||||
:colspan="monthlyHeaders.length + 1">
|
||||
{{ categoryName }}
|
||||
</td>
|
||||
|
|
@ -118,17 +118,17 @@
|
|||
v-for="item in items"
|
||||
:key="item.id"
|
||||
:class="[
|
||||
'border-t border-gray-200 hover:bg-zinc-50 transition-all duration-300',
|
||||
'border-t border-neutral-200 hover:bg-neutral-50 transition-all duration-300',
|
||||
highlightedItemId === item.id &&
|
||||
'bg-yellow-100 animate-pulse',
|
||||
]">
|
||||
<td
|
||||
class="border-r-1 border-zinc-200 px-4 py-2 sticky left-0 bg-white z-10">
|
||||
class="border-r-1 border-neutral-200 px-4 py-2 sticky left-0 bg-white z-10">
|
||||
<div class="flex items-center justify-between group">
|
||||
<div class="flex-1">
|
||||
<div class="text-left w-full">
|
||||
<div class="font-medium">{{ item.name }}</div>
|
||||
<div class="text-xs text-gray-600">
|
||||
<div class="text-xs text-neutral-600">
|
||||
{{ item.subcategory }}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -147,7 +147,7 @@
|
|||
<td
|
||||
v-for="month in monthlyHeaders"
|
||||
:key="month.key"
|
||||
class="border-r border-gray-200 px-1 py-1 last:border-r-0">
|
||||
class="border-r border-neutral-200 px-1 py-1 last:border-r-0">
|
||||
<input
|
||||
type="text"
|
||||
:value="formatValue(item.monthlyValues?.[month.key] || 0)"
|
||||
|
|
@ -157,9 +157,9 @@
|
|||
"
|
||||
@blur="handleBlur($event, 'revenue', item.id, month.key)"
|
||||
@keydown.enter="handleEnter($event)"
|
||||
class="w-full text-right px-1 py-0.5 border border-transparent hover:border-gray-400 focus:border-black focus:outline-none transition-none"
|
||||
class="w-full text-right px-1 py-0.5 border border-transparent hover:border-neutral-400 focus:border-black focus:outline-none transition-none"
|
||||
:class="{
|
||||
'bg-zinc-50': !item.monthlyValues?.[month.key],
|
||||
'bg-neutral-50': !item.monthlyValues?.[month.key],
|
||||
}" />
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -167,9 +167,9 @@
|
|||
|
||||
<!-- Total Revenue Row -->
|
||||
<tr
|
||||
class="border-t-1 border-black border-b-1 font-bold bg-zinc-100">
|
||||
class="border-t-1 border-black border-b-1 font-bold bg-neutral-100">
|
||||
<td
|
||||
class="border-r-1 border-black px-4 py-2 sticky left-0 bg-zinc-100 z-10">
|
||||
class="border-r-1 border-black px-4 py-2 sticky left-0 bg-neutral-100 z-10">
|
||||
TOTAL REVENUE
|
||||
</td>
|
||||
<td
|
||||
|
|
@ -189,7 +189,7 @@
|
|||
@click="showAddExpenseModal = true"
|
||||
size="xs"
|
||||
:ui="{
|
||||
base: 'bg-white text-black hover:bg-zinc-200 transition-none',
|
||||
base: 'bg-white text-black hover:bg-neutral-200 transition-none',
|
||||
}">
|
||||
+ Add
|
||||
</UButton>
|
||||
|
|
@ -202,9 +202,9 @@
|
|||
<template
|
||||
v-for="(items, categoryName) in groupedExpenses"
|
||||
:key="`expense-${categoryName}`">
|
||||
<tr v-if="items.length > 0" class="border-t border-gray-300">
|
||||
<tr v-if="items.length > 0" class="border-t border-neutral-300">
|
||||
<td
|
||||
class="px-4 py-1 font-semibold sticky left-0 bg-zinc-100 z-10"
|
||||
class="px-4 py-1 font-semibold sticky left-0 bg-neutral-100 z-10"
|
||||
:colspan="monthlyHeaders.length + 1">
|
||||
{{ categoryName }}
|
||||
</td>
|
||||
|
|
@ -213,12 +213,12 @@
|
|||
v-for="item in items"
|
||||
:key="item.id"
|
||||
:class="[
|
||||
'border-t border-gray-200 hover:bg-zinc-50 transition-all duration-300',
|
||||
'border-t border-neutral-200 hover:bg-neutral-50 transition-all duration-300',
|
||||
highlightedItemId === item.id &&
|
||||
'bg-yellow-100 animate-pulse',
|
||||
]">
|
||||
<td
|
||||
class="border-r-1 border-zinc-200 px-4 py-2 sticky left-0 bg-white z-10">
|
||||
class="border-r-1 border-neutral-200 px-4 py-2 sticky left-0 bg-white z-10">
|
||||
<div class="flex items-center justify-between group">
|
||||
<div class="flex-1">
|
||||
<div class="text-left w-full">
|
||||
|
|
@ -236,7 +236,7 @@
|
|||
Auto
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-xs text-gray-600" v-if="!isPayrollItem(item.id)">
|
||||
<div class="text-xs text-neutral-600" v-if="!isPayrollItem(item.id)">
|
||||
{{ item.subcategory }}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -258,7 +258,7 @@
|
|||
<td
|
||||
v-for="month in monthlyHeaders"
|
||||
:key="month.key"
|
||||
class="border-r border-gray-200 px-1 py-1 last:border-r-0">
|
||||
class="border-r border-neutral-200 px-1 py-1 last:border-r-0">
|
||||
<input
|
||||
type="text"
|
||||
:value="formatValue(item.monthlyValues?.[month.key] || 0)"
|
||||
|
|
@ -271,12 +271,12 @@
|
|||
@keydown.enter="handleEnter($event)"
|
||||
class="w-full text-right px-1 py-0.5 border-2 transition-none"
|
||||
:class="{
|
||||
'bg-zinc-50':
|
||||
'bg-neutral-50':
|
||||
!item.monthlyValues?.[month.key] &&
|
||||
!isPayrollItem(item.id),
|
||||
'bg-zinc-50 border-none cursor-not-allowed text-zinc-500':
|
||||
'bg-neutral-50 border-none cursor-not-allowed text-neutral-500':
|
||||
isPayrollItem(item.id),
|
||||
'border-transparent hover:border-zinc-400 focus:border-black focus:outline-none':
|
||||
'border-transparent hover:border-neutral-400 focus:border-black focus:outline-none':
|
||||
!isPayrollItem(item.id),
|
||||
}"
|
||||
:title="
|
||||
|
|
@ -289,15 +289,15 @@
|
|||
</template>
|
||||
|
||||
<!-- Total Expenses Row -->
|
||||
<tr class="border-t-1 border-black font-bold bg-zinc-100">
|
||||
<tr class="border-t-1 border-black font-bold bg-neutral-100">
|
||||
<td
|
||||
class="border-r-1 border-black px-4 py-2 sticky left-0 bg-zinc-100 z-10">
|
||||
class="border-r-1 border-black px-4 py-2 sticky left-0 bg-neutral-100 z-10">
|
||||
TOTAL EXPENSES
|
||||
</td>
|
||||
<td
|
||||
v-for="month in monthlyHeaders"
|
||||
:key="month.key"
|
||||
class="border-r border-gray-400 px-2 py-2 text-right last:border-r-0">
|
||||
class="border-r border-neutral-400 px-2 py-2 text-right last:border-r-0">
|
||||
{{ formatCurrency(monthlyTotals[month.key]?.expenses || 0) }}
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -311,7 +311,7 @@
|
|||
<td
|
||||
v-for="month in monthlyHeaders"
|
||||
:key="month.key"
|
||||
class="border-r border-gray-400 px-2 py-3 text-right last:border-r-0"
|
||||
class="border-r border-neutral-400 px-2 py-3 text-right last:border-r-0"
|
||||
:class="
|
||||
getNetIncomeClass(monthlyTotals[month.key]?.net || 0)
|
||||
">
|
||||
|
|
@ -320,7 +320,7 @@
|
|||
</tr>
|
||||
|
||||
<!-- Cumulative Balance Row -->
|
||||
<tr class="border-t-1 border-gray-400 font-bold text-lg bg-blue-50">
|
||||
<tr class="border-t-1 border-neutral-400 font-bold text-lg bg-blue-50">
|
||||
<td
|
||||
class="border-r-1 border-black px-4 py-3 sticky left-0 bg-blue-50 z-10">
|
||||
CUMULATIVE BALANCE
|
||||
|
|
@ -328,7 +328,7 @@
|
|||
<td
|
||||
v-for="month in monthlyHeaders"
|
||||
:key="month.key"
|
||||
class="border-r border-gray-400 px-2 py-3 text-right last:border-r-0"
|
||||
class="border-r border-neutral-400 px-2 py-3 text-right last:border-r-0"
|
||||
:class="
|
||||
getCumulativeBalanceClass(cumulativeBalances[month.key] || 0)
|
||||
">
|
||||
|
|
@ -403,19 +403,19 @@
|
|||
placeholder="Enter annual amount (e.g., 12000)"
|
||||
size="lg">
|
||||
<template #leading>
|
||||
<span class="text-gray-500 font-medium">$</span>
|
||||
<span class="text-neutral-500 font-medium">$</span>
|
||||
</template>
|
||||
</UInput>
|
||||
</UFormField>
|
||||
<div class="bg-white rounded-lg p-4 border border-gray-200">
|
||||
<div class="bg-white rounded-lg p-4 border border-neutral-200">
|
||||
<div class="mb-2">
|
||||
<span class="text-sm font-medium text-gray-700"
|
||||
<span class="text-sm font-medium text-neutral-700"
|
||||
>Distribution Preview</span
|
||||
>
|
||||
</div>
|
||||
<p class="text-sm text-gray-600">
|
||||
<p class="text-sm text-neutral-600">
|
||||
This will divide
|
||||
<span class="font-semibold text-gray-900"
|
||||
<span class="font-semibold text-neutral-900"
|
||||
>${{ newRevenue.annualAmount || 0 }}</span
|
||||
>
|
||||
equally across all 12 months (<span
|
||||
|
|
@ -440,17 +440,17 @@
|
|||
placeholder="Enter monthly amount (e.g., 1000)"
|
||||
size="lg">
|
||||
<template #leading>
|
||||
<span class="text-gray-500 font-medium">$</span>
|
||||
<span class="text-neutral-500 font-medium">$</span>
|
||||
</template>
|
||||
</UInput>
|
||||
</UFormField>
|
||||
<div class="bg-white rounded-lg p-4 border border-gray-200">
|
||||
<div class="bg-white rounded-lg p-4 border border-neutral-200">
|
||||
<div class="mb-2">
|
||||
<span class="text-sm font-medium text-gray-700"
|
||||
<span class="text-sm font-medium text-neutral-700"
|
||||
>Monthly Preview</span
|
||||
>
|
||||
</div>
|
||||
<p class="text-sm text-gray-600">
|
||||
<p class="text-sm text-neutral-600">
|
||||
This will set
|
||||
<span class="font-semibold text-green-600"
|
||||
>${{ newRevenue.monthlyAmount || 0 }}</span
|
||||
|
|
@ -463,8 +463,8 @@
|
|||
<!-- Start Empty -->
|
||||
<div v-else>
|
||||
<div
|
||||
class="bg-white rounded-lg p-6 border border-gray-200 text-center">
|
||||
<p class="text-sm text-gray-600">
|
||||
class="bg-white rounded-lg p-6 border border-neutral-200 text-center">
|
||||
<p class="text-sm text-neutral-600">
|
||||
The revenue item will be created with no initial values. You
|
||||
can fill them in later directly in the budget table.
|
||||
</p>
|
||||
|
|
@ -545,19 +545,19 @@
|
|||
size="lg"
|
||||
class="text-sm font-medium w-full">
|
||||
<template #leading>
|
||||
<span class="text-gray-500 font-medium">$</span>
|
||||
<span class="text-neutral-500 font-medium">$</span>
|
||||
</template>
|
||||
</UInput>
|
||||
</UFormField>
|
||||
<div class="bg-white rounded-lg p-4 border border-gray-200">
|
||||
<div class="bg-white rounded-lg p-4 border border-neutral-200">
|
||||
<div class="mb-2">
|
||||
<span class="text-sm font-medium text-gray-700"
|
||||
<span class="text-sm font-medium text-neutral-700"
|
||||
>Distribution Preview</span
|
||||
>
|
||||
</div>
|
||||
<p class="text-sm text-gray-600">
|
||||
<p class="text-sm text-neutral-600">
|
||||
This will divide
|
||||
<span class="font-semibold text-gray-900"
|
||||
<span class="font-semibold text-neutral-900"
|
||||
>${{ newExpense.annualAmount || 0 }}</span
|
||||
>
|
||||
equally across all 12 months (<span
|
||||
|
|
@ -583,17 +583,17 @@
|
|||
size="lg"
|
||||
class="text-sm font-medium w-full">
|
||||
<template #leading>
|
||||
<span class="text-gray-500 font-medium">$</span>
|
||||
<span class="text-neutral-500 font-medium">$</span>
|
||||
</template>
|
||||
</UInput>
|
||||
</UFormField>
|
||||
<div class="bg-white rounded-lg p-4 border border-gray-200">
|
||||
<div class="bg-white rounded-lg p-4 border border-neutral-200">
|
||||
<div class="mb-2">
|
||||
<span class="text-sm font-medium text-gray-700"
|
||||
<span class="text-sm font-medium text-neutral-700"
|
||||
>Monthly Preview</span
|
||||
>
|
||||
</div>
|
||||
<p class="text-sm text-gray-600">
|
||||
<p class="text-sm text-neutral-600">
|
||||
This will set
|
||||
<span class="font-semibold text-red-600"
|
||||
>${{ newExpense.monthlyAmount || 0 }}</span
|
||||
|
|
@ -606,8 +606,8 @@
|
|||
<!-- Start Empty -->
|
||||
<div v-else>
|
||||
<div
|
||||
class="bg-white rounded-lg p-6 border border-gray-200 text-center">
|
||||
<p class="text-sm text-gray-600">
|
||||
class="bg-white rounded-lg p-6 border border-neutral-200 text-center">
|
||||
<p class="text-sm text-neutral-600">
|
||||
The expense item will be created with no initial values. You
|
||||
can fill them in later directly in the budget table.
|
||||
</p>
|
||||
|
|
@ -650,8 +650,8 @@
|
|||
<!-- Revenue Section -->
|
||||
<div>
|
||||
<h4 class="font-semibold text-green-600 mb-2">📈 Revenue Calculation</h4>
|
||||
<p class="text-sm text-gray-600 mb-2">Revenue comes from your setup wizard streams and any manual additions:</p>
|
||||
<ul class="text-sm text-gray-600 space-y-1 ml-4">
|
||||
<p class="text-sm text-neutral-600 mb-2">Revenue comes from your setup wizard streams and any manual additions:</p>
|
||||
<ul class="text-sm text-neutral-600 space-y-1 ml-4">
|
||||
<li>• Monthly amounts you entered for each revenue stream</li>
|
||||
<li>• Varies by month based on your specific projections</li>
|
||||
</ul>
|
||||
|
|
@ -660,7 +660,7 @@
|
|||
<!-- Payroll Section -->
|
||||
<div>
|
||||
<h4 class="font-semibold text-blue-600 mb-2">👥 Smart Payroll Calculation</h4>
|
||||
<p class="text-sm text-gray-600 mb-2">Payroll uses a <strong>cumulative balance approach</strong> to ensure sustainability:</p>
|
||||
<p class="text-sm text-neutral-600 mb-2">Payroll uses a <strong>cumulative balance approach</strong> to ensure sustainability:</p>
|
||||
<div class="bg-blue-50 border border-blue-200 rounded p-3 text-sm">
|
||||
<p class="font-medium mb-2">Step-by-step process:</p>
|
||||
<ol class="space-y-1 ml-4">
|
||||
|
|
@ -671,7 +671,7 @@
|
|||
<li>5. Ensure cumulative balance doesn't fall below threshold</li>
|
||||
</ol>
|
||||
</div>
|
||||
<p class="text-sm text-gray-600 mt-2">
|
||||
<p class="text-sm text-neutral-600 mt-2">
|
||||
This means payroll varies by month - higher in good cash flow months, lower when cash is tight.
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -679,8 +679,8 @@
|
|||
<!-- Cumulative Balance Section -->
|
||||
<div>
|
||||
<h4 class="font-semibold text-purple-600 mb-2">💰 Cumulative Balance</h4>
|
||||
<p class="text-sm text-gray-600 mb-2">Shows your running cash position over time:</p>
|
||||
<ul class="text-sm text-gray-600 space-y-1 ml-4">
|
||||
<p class="text-sm text-neutral-600 mb-2">Shows your running cash position over time:</p>
|
||||
<ul class="text-sm text-neutral-600 space-y-1 ml-4">
|
||||
<li>• Starts at $0 (current cash position)</li>
|
||||
<li>• Adds each month's net income (Revenue - All Expenses)</li>
|
||||
<li>• Helps you see when cash might run low</li>
|
||||
|
|
@ -691,7 +691,7 @@
|
|||
<!-- Policy Explanation -->
|
||||
<div>
|
||||
<h4 class="font-semibold text-orange-600 mb-2">⚖️ Pay Policy: {{ getPolicyName() }}</h4>
|
||||
<div class="text-sm text-gray-600">
|
||||
<div class="text-sm text-neutral-600">
|
||||
<p v-if="coopBuilderStore.policy?.relationship === 'equal-pay'">
|
||||
Everyone gets equal hourly wage (${{ coopBuilderStore.equalHourlyWage || 0 }}/hour) based on their monthly hours.
|
||||
</p>
|
||||
|
|
@ -704,8 +704,8 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-gray-50 border border-gray-200 rounded p-3">
|
||||
<p class="text-sm text-gray-700">
|
||||
<div class="bg-neutral-50 border border-neutral-200 rounded p-3">
|
||||
<p class="text-sm text-neutral-700">
|
||||
<strong>Key insight:</strong> This system prioritizes sustainability over theoretical maximums.
|
||||
You might not always get full theoretical wages, but you'll never run out of cash.
|
||||
</p>
|
||||
|
|
@ -1231,7 +1231,7 @@ function formatCurrency(amount: number): string {
|
|||
function getNetIncomeClass(amount: number): string {
|
||||
if (amount > 0) return "text-green-600 font-bold";
|
||||
if (amount < 0) return "text-red-600 font-bold";
|
||||
return "text-gray-600";
|
||||
return "text-neutral-600";
|
||||
}
|
||||
|
||||
function getCumulativeBalanceClass(amount: number): string {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue