refactor: enhance AnnualBudget component layout with improved dark mode support, streamline table structure, and update CSS for better visual consistency
This commit is contained in:
parent
24e8b7a3a8
commit
f073f91569
14 changed files with 1440 additions and 922 deletions
|
|
@ -2,114 +2,164 @@
|
|||
<div class="space-y-8">
|
||||
<!-- Annual Budget Overview -->
|
||||
<div class="space-y-4">
|
||||
<h2 class="text-2xl font-bold">Annual Budget Overview</h2>
|
||||
<div class="relative">
|
||||
<div class="absolute top-2 left-2 w-full h-full dither-shadow"></div>
|
||||
<div
|
||||
class="relative border border-black dark:border-neutral-600 bg-white dark:bg-neutral-950">
|
||||
<table
|
||||
class="w-full border-collapse text-sm bg-white dark:bg-neutral-950">
|
||||
<thead>
|
||||
<tr class="bg-neutral-100 dark:bg-neutral-950">
|
||||
<th
|
||||
class="border-r-1 border-black dark:border-neutral-400 px-4 py-3 text-left font-bold text-black dark:text-white">
|
||||
Category
|
||||
</th>
|
||||
<th
|
||||
class="border-r border-neutral-400 dark:border-neutral-600 px-4 py-3 text-right font-bold text-black dark:text-white">
|
||||
Planned
|
||||
</th>
|
||||
<th
|
||||
class="px-4 py-3 text-right font-bold text-black dark:text-white">
|
||||
%
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- Revenue Section -->
|
||||
<tr class="bg-black text-white dark:bg-white dark:text-black">
|
||||
<td
|
||||
class="px-4 py-2 font-bold text-white dark:text-black"
|
||||
colspan="3">
|
||||
REVENUE
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<div class="border border-black bg-white">
|
||||
<table class="w-full border-collapse text-sm">
|
||||
<thead>
|
||||
<tr class="border-b-2 border-black bg-neutral-100">
|
||||
<th class="border-r-1 border-black px-4 py-3 text-left font-bold">
|
||||
Category
|
||||
</th>
|
||||
<th
|
||||
class="border-r border-neutral-400 px-4 py-3 text-right font-bold">
|
||||
Planned
|
||||
</th>
|
||||
<th class="px-4 py-3 text-right font-bold">%</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- Revenue Section -->
|
||||
<tr class="bg-black text-white">
|
||||
<td class="px-4 py-2 font-bold" colspan="3">REVENUE</td>
|
||||
</tr>
|
||||
<!-- Revenue Categories -->
|
||||
<tr
|
||||
v-for="(category, index) in revenueCategories"
|
||||
:key="`rev-${index}`"
|
||||
class="border-t border-neutral-200 dark:border-neutral-700 text-black dark:text-white"
|
||||
v-show="category.planned > 0">
|
||||
<td
|
||||
class="border-r-1 border-black dark:border-neutral-400 px-4 py-2 text-black dark:text-white">
|
||||
{{ category.name }}
|
||||
</td>
|
||||
<td
|
||||
class="border-r border-neutral-400 dark:border-neutral-600 px-4 py-2 text-right text-black dark:text-white font-mono">
|
||||
{{ formatCurrency(category.planned) }}
|
||||
</td>
|
||||
<td
|
||||
class="px-4 py-2 text-right text-black dark:text-white font-mono">
|
||||
{{ category.percentage }}%
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Revenue Categories -->
|
||||
<tr
|
||||
v-for="(category, index) in revenueCategories"
|
||||
:key="`rev-${index}`"
|
||||
class="border-t border-neutral-200"
|
||||
v-show="category.planned > 0">
|
||||
<td class="border-r-1 border-black px-4 py-2">
|
||||
{{ category.name }}
|
||||
</td>
|
||||
<td class="border-r border-neutral-400 px-4 py-2 text-right">
|
||||
{{ formatCurrency(category.planned) }}
|
||||
</td>
|
||||
<td class="px-4 py-2 text-right">{{ category.percentage }}%</td>
|
||||
</tr>
|
||||
<!-- Total Revenue -->
|
||||
<tr
|
||||
class="border-t-2 border-black dark:border-neutral-400 font-semibold bg-neutral-50 dark:bg-neutral-800">
|
||||
<td
|
||||
class="border-r-1 border-black dark:border-neutral-400 px-4 py-2 text-black dark:text-white">
|
||||
Total Revenue
|
||||
</td>
|
||||
<td
|
||||
class="border-r border-neutral-400 dark:border-neutral-600 px-4 py-2 text-right text-black dark:text-white font-mono">
|
||||
{{ formatCurrency(totalRevenuePlanned) }}
|
||||
</td>
|
||||
<td
|
||||
class="px-4 py-2 text-right text-black dark:text-white font-mono">
|
||||
100%
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Total Revenue -->
|
||||
<tr class="border-t-2 border-black font-semibold bg-neutral-50">
|
||||
<td class="border-r-1 border-black px-4 py-2">Total Revenue</td>
|
||||
<td class="border-r border-neutral-400 px-4 py-2 text-right">
|
||||
{{ formatCurrency(totalRevenuePlanned) }}
|
||||
</td>
|
||||
<td class="px-4 py-2 text-right">100%</td>
|
||||
</tr>
|
||||
<!-- Revenue Diversification Guidance -->
|
||||
<tr class="bg-neutral-50 dark:bg-neutral-800">
|
||||
<td
|
||||
colspan="3"
|
||||
class="border-t border-neutral-300 dark:border-neutral-700 px-4 py-3 text-black dark:text-white">
|
||||
<div class="text-sm">
|
||||
<p class="font-medium mb-2 text-black dark:text-white">
|
||||
{{ diversificationGuidance }}
|
||||
</p>
|
||||
<p
|
||||
class="text-neutral-600 dark:text-neutral-100 mb-2"
|
||||
v-if="suggestedCategories.length > 0">
|
||||
Consider developing: {{ suggestedCategories.join(", ") }}
|
||||
</p>
|
||||
<p class="text-xs text-black dark:text-white">
|
||||
<NuxtLink
|
||||
to="/help#revenue-diversification"
|
||||
class="text-white dark:text-neutral-100 hover:text-white dark:hover:text-white underline">
|
||||
Learn how to develop these revenue streams →
|
||||
</NuxtLink>
|
||||
</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Revenue Diversification Guidance -->
|
||||
<tr :class="guidanceBackgroundClass">
|
||||
<td colspan="3" class="border-t border-neutral-300 px-4 py-3">
|
||||
<div class="text-sm">
|
||||
<p class="font-medium mb-2">{{ diversificationGuidance }}</p>
|
||||
<p
|
||||
class="text-neutral-600 mb-2"
|
||||
v-if="suggestedCategories.length > 0">
|
||||
Consider developing: {{ suggestedCategories.join(", ") }}
|
||||
</p>
|
||||
<p class="text-xs">
|
||||
<NuxtLink
|
||||
to="/help#revenue-diversification"
|
||||
class="text-blue-600 hover:text-blue-800 underline">
|
||||
Learn how to develop these revenue streams →
|
||||
</NuxtLink>
|
||||
</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- Expenses Section -->
|
||||
<tr class="bg-black text-white dark:bg-white dark:text-black">
|
||||
<td
|
||||
class="px-4 py-2 font-bold text-white dark:text-black"
|
||||
colspan="3">
|
||||
EXPENSES
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Expenses Section -->
|
||||
<tr class="bg-black text-white">
|
||||
<td class="px-4 py-2 font-bold" colspan="3">EXPENSES</td>
|
||||
</tr>
|
||||
<!-- Expense Categories -->
|
||||
<tr
|
||||
v-for="(category, index) in expenseCategories"
|
||||
:key="`exp-${index}`"
|
||||
class="text-black dark:text-white"
|
||||
v-show="category.planned > 0">
|
||||
<td
|
||||
class="border-r-1 border-black dark:border-neutral-400 px-4 py-2 text-black dark:text-white">
|
||||
{{ category.name }}
|
||||
</td>
|
||||
<td
|
||||
class="border-r border-neutral-400 dark:border-neutral-600 px-4 py-2 text-right text-black dark:text-white font-mono">
|
||||
{{ formatCurrency(category.planned) }}
|
||||
</td>
|
||||
<td
|
||||
class="px-4 py-2 text-right text-black dark:text-white font-mono">
|
||||
{{ category.percentage }}%
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Expense Categories -->
|
||||
<tr
|
||||
v-for="(category, index) in expenseCategories"
|
||||
:key="`exp-${index}`"
|
||||
class="border-t border-neutral-200"
|
||||
v-show="category.planned > 0">
|
||||
<td class="border-r-1 border-black px-4 py-2">
|
||||
{{ category.name }}
|
||||
</td>
|
||||
<td class="border-r border-neutral-400 px-4 py-2 text-right">
|
||||
{{ formatCurrency(category.planned) }}
|
||||
</td>
|
||||
<td class="px-4 py-2 text-right">{{ category.percentage }}%</td>
|
||||
</tr>
|
||||
<!-- Total Expenses -->
|
||||
<tr class="font-semibold bg-neutral-50 dark:bg-neutral-800">
|
||||
<td
|
||||
class="border-r-1 border-black dark:border-neutral-400 px-4 py-2 text-black dark:text-white">
|
||||
Total Expenses
|
||||
</td>
|
||||
<td
|
||||
class="border-r border-neutral-400 dark:border-neutral-600 px-4 py-2 text-right text-black dark:text-white font-mono">
|
||||
{{ formatCurrency(totalExpensesPlanned) }}
|
||||
</td>
|
||||
<td
|
||||
class="px-4 py-2 text-right text-black dark:text-white font-mono">
|
||||
100%
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Total Expenses -->
|
||||
<tr class="border-t-2 border-black font-semibold bg-neutral-50">
|
||||
<td class="border-r-1 border-black px-4 py-2">Total Expenses</td>
|
||||
<td class="border-r border-neutral-400 px-4 py-2 text-right">
|
||||
{{ formatCurrency(totalExpensesPlanned) }}
|
||||
</td>
|
||||
<td class="px-4 py-2 text-right">100%</td>
|
||||
</tr>
|
||||
|
||||
<!-- Net Total -->
|
||||
<tr
|
||||
class="border-t-2 border-black font-bold text-lg"
|
||||
:class="netTotalClass">
|
||||
<td class="border-r-1 border-black px-4 py-3">NET TOTAL</td>
|
||||
<td class="border-r border-neutral-400 px-4 py-3 text-right">
|
||||
{{ formatCurrency(netTotal) }}
|
||||
</td>
|
||||
<td class="px-4 py-3 text-right">-</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<!-- Net Total -->
|
||||
<tr
|
||||
class="border-t-2 border-black dark:border-neutral-400 font-bold text-lg"
|
||||
:class="netTotalClass">
|
||||
<td
|
||||
class="border-r-1 border-black dark:border-neutral-400 px-4 py-3 text-black dark:text-white">
|
||||
NET TOTAL
|
||||
</td>
|
||||
<td
|
||||
class="border-r border-neutral-400 dark:border-neutral-600 px-4 py-3 text-right text-black dark:text-white font-mono">
|
||||
{{ formatCurrency(netTotal) }}
|
||||
</td>
|
||||
<td class="px-4 py-3 text-right text-black dark:text-white">
|
||||
-
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -242,9 +292,9 @@ const netTotal = computed(
|
|||
);
|
||||
|
||||
const netTotalClass = computed(() => {
|
||||
if (netTotal.value > 0) return "bg-green-50";
|
||||
if (netTotal.value < 0) return "bg-red-50";
|
||||
return "bg-neutral-50";
|
||||
if (netTotal.value > 0) return "bg-green-50 dark:bg-green-950";
|
||||
if (netTotal.value < 0) return "bg-red-50 dark:bg-red-950";
|
||||
return "bg-neutral-50 dark:bg-neutral-800";
|
||||
});
|
||||
|
||||
// Diversification guidance
|
||||
|
|
@ -308,28 +358,6 @@ const diversificationGuidance = computed(() => {
|
|||
return guidance;
|
||||
});
|
||||
|
||||
const guidanceBackgroundClass = computed(() => {
|
||||
const topCategory = revenueCategories.value.reduce(
|
||||
(max, cat) => (cat.percentage > max.percentage ? cat : max),
|
||||
{ percentage: 0 }
|
||||
);
|
||||
|
||||
if (topCategory.percentage >= 70) {
|
||||
return "bg-red-50";
|
||||
} else if (topCategory.percentage >= 50) {
|
||||
return "bg-red-50";
|
||||
} else {
|
||||
const categoriesAbove20 = revenueCategories.value.filter(
|
||||
(cat) => cat.percentage >= 20
|
||||
).length;
|
||||
if (categoriesAbove20 >= 3) {
|
||||
return "bg-green-50";
|
||||
} else {
|
||||
return "bg-yellow-50";
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Suggested categories to develop
|
||||
const suggestedCategories = computed(() => {
|
||||
const categoriesWithRevenue = revenueCategories.value.filter(
|
||||
|
|
@ -394,10 +422,11 @@ function formatCurrency(amount: number): string {
|
|||
}
|
||||
|
||||
function getPercentageClass(percentage: number): string {
|
||||
if (percentage > 50) return "text-red-600 font-bold";
|
||||
if (percentage > 35) return "text-yellow-600 font-semibold";
|
||||
if (percentage > 20) return "text-black font-medium";
|
||||
return "text-neutral-500";
|
||||
if (percentage > 50) return "text-red-600 dark:text-red-400 font-bold";
|
||||
if (percentage > 35)
|
||||
return "text-yellow-600 dark:text-yellow-400 font-semibold";
|
||||
if (percentage > 20) return "text-black dark:text-white font-medium";
|
||||
return "text-neutral-500 dark:text-neutral-400";
|
||||
}
|
||||
|
||||
// Initialize
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue