Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/house planner #392

Merged
merged 3 commits into from
Mar 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/Http/Controllers/System/DashboardController.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public function __invoke()
$teamId = $request->user()->current_team_id;
$budget = BudgetMonth::getMonthAssignmentTotal($teamId, $startDate);
$transactionsTotal = TransactionService::getExpensesTotal($teamId, $startDate, $endDate);
$netWorth = collect(TransactionService::getNetWorth($teamId, $startDate, $endDate))->reverse()->values();
$plannedMeals = $this->mealService->getMealSchedule($teamId);
$nextPayments = $this->plannedService->getPlanned($teamId);

Expand All @@ -37,6 +38,7 @@ public function __invoke()
'meals' => PlannedMealResource::collection($plannedMeals),
'budgetTotal' => $budget,
'transactionTotal' => $transactionsTotal,
'netWorth' => $netWorth,
'expenses' => ReportService::generateCurrentPreviousReport($teamId, 'month', 1),
'spendingSummary' => ReportService::generateExpensesByPeriod($teamId, $startDate),
'onboarding' => function () use ($team) {
Expand Down
2 changes: 1 addition & 1 deletion resources/js/Components/WidgetContainer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ const { isTab: isCurrentTab, selectedTab, tabs: widgetTabs } = useTabs(

<div class="w-full flex justify-end" v-if="$slots.actions || actionLabel || tabs.length">
<section
class="flex justify-end w-full space-x-2 px-4 py-2.5"
class="flex justify-end w-full space-x-2 px-4 py-2"
v-if="tabs.length"
>
<button
Expand Down
45 changes: 23 additions & 22 deletions resources/js/Pages/Dashboard/Index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,17 @@

import NextPaymentsWidget from "@/domains/transactions/components/NextPaymentsWidget.vue";
import MealWidget from "@/domains/meal/components/MealWidget.vue";
import BudgetTracker from "@/domains/budget/components/BudgetTracker.vue";
import AccountsTracker from "@/domains/transactions/components/AccountsTracker.vue";
import OccurrenceCard from '@/Components/Modules/occurrence/OccurrenceCard.vue';
import DashboardSpendings from './Partials/DashboardSpendings.vue';
import DashboardSpending from './Partials/DashboardSpendings.vue';
import BudgetFundWidget from './Partials/BudgetFundWidget.vue';
import NetWorthWidget from './Partials/NetWorthWidget.vue';
import BudgetWidget from "./Partials/BudgetWidget.vue";

import { useAppContextStore } from '@/store';
import { IOccurrenceCheck } from '@/Components/Modules/occurrence/models';
import { IAccount, ICategory } from '@/domains/transactions/models';
import { IBudgetStat } from '@/domains/budget/models';

withDefaults(defineProps<{
spendingSummary: {
Expand All @@ -40,21 +43,20 @@
user: {
name: string;
},
budgetTotal: number,
netWorth: any,
budgetTotal: IBudgetStat,
nextPayments: any[],
transactionTotal: Record<string, any>,
categories: ICategory[],
accounts: IAccount[],
onboarding: Record<string, any>,
checks: IOccurrenceCheck[]
}>(), {

});
}>(), {});
const contextStore = useAppContextStore()

const selected = ref(null);

const budgetTrackerRef = ref();;
const AccountsTrackerRef = ref();;


const areChecksLoading = ref(true);
Expand Down Expand Up @@ -89,29 +91,23 @@
<main class="px-5 mx-auto mt-5 mb-10 md:space-y-0 md:space-x-10 md:flex max-w-screen-2xl sm:px-6 lg:px-8">
<section class="mt-6 md:w-9/12 space-y-4">
<section class="flex flex-col md:flex-row md:space-x-4">
<BudgetTracker
<AccountsTracker
class="md:w-7/12 w-full order-1 mt-2 md:mt-0"
ref="budgetTrackerRef"
:budget="budgetTotal"
ref="AccountsTrackerRef"
:net-worth="netWorth"
:expenses="transactionTotal.total_amount"
:message="$t('dashboard.welcome')"
:username="user.name"
@section-click="selected=$event"
/>
<BudgetTracker
class="md:w-5/12 w-full order-1 mt-2 md:mt-0"
ref="budgetTrackerRef"
:budget="budgetTotal"
:message="$t('Net-worth trend')"
@section-click="selected=$event"
/>

<BudgetFundWidget class="md:w-5/12 w-full order-1 mt-2 md:mt-0" />
</section>

<DashboardSpendings
<DashboardSpending
:expenses="expenses"
:spending-summary="spendingSummary"
/>
<MealWidget :meals="meals?.data" />
</section>
<section class="py-6 space-y-4 md:w-3/12">
<OccurrenceCard :checks="checks" :wrap="true" />
Expand All @@ -122,8 +118,6 @@
:steps="onboarding.steps"
:percentage="onboarding.percentage"
/>

<MealWidget :meals="meals?.data" />
<WidgetContainer
:message="$t('Transactions')"
:tabs="transactionsTabs"
Expand All @@ -143,7 +137,14 @@
<DashboardDrafts v-else />
</template>
</WidgetContainer>
<BudgetFundWidget />
<BudgetWidget :budget="budgetTotal"/>
<!-- <NetWorthWidget
ref="NetWorthWidgetRef"
:budget="budgetTotal"
:message="$t('Net-worth trend')"
@section-click="selected=$event"
/> -->

</section>
</main>
</AppLayout>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { ITransaction } from '@/domains/transactions/models';
import axios from 'axios';
import { router } from '@inertiajs/vue3';

import LogerButton from '@/Components/atoms/LogerButton.vue';
import WidgetTitleCard from '@/Components/molecules/WidgetTitleCard.vue';
import TransactionsList from '@/domains/transactions/components/TransactionsList.vue';

import { ITransaction } from '@/domains/transactions/models';
import { removeTransaction, draftsDBToTransaction, useTransactionModal } from '@/domains/transactions';
import LogerButton from '@/Components/atoms/LogerButton.vue';
import { useTransactionStore } from '@/store/transactions';
import { router } from '@inertiajs/vue3';


const transactionsDraft = ref([]);
Expand Down
49 changes: 36 additions & 13 deletions resources/js/Pages/Dashboard/Partials/BudgetFundWidget.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { onMounted, ref, computed } from 'vue';
import axios from 'axios';

import WidgetContainer from '@/Components/WidgetContainer.vue';
import axios from 'axios';
import { formatMoney } from '@/utils';
import BudgetProgress from '@/domains/budget/components/BudgetProgress.vue';
import MoneyPresenter from '@/Components/molecules/MoneyPresenter.vue';

const budgetData = ref({})

Expand All @@ -13,6 +14,12 @@ import { formatMoney } from '@/utils';
});
}


const fundMetrics = computed(() => ({
target: budgetData?.value.monthlyExpense * budgetData?.value.target_times,
balance: budgetData.value?.balance ?? 0
}))

onMounted(() => {
fetchChecks()
})
Expand All @@ -23,16 +30,32 @@ import { formatMoney } from '@/utils';
:message="$t('Emergency Fund Builder')"
>
<template #content>
<section>
<p>
{{ formatMoney(budgetData.balance) }}
</p>
<p>
{{ formatMoney(budgetData.monthlyExpense) }}
</p>
<p>
{{ budgetData.total?.toFixed?.(2) }} Months
</p>
<section class="my-2">
<BudgetProgress
class="h-1.5 rounded-sm"
:goal="fundMetrics.target"
:current="budgetData.balance"
:progress-class="['bg-primary', 'bg-secondary/5']"
:show-labels="false"
>
<template #before>
<header class="mb-1 font-bold flex justify-between">
<span>
<MoneyPresenter :value="fundMetrics.target" />
</span>
<span>
{{ budgetData.target_times }} Months
</span>
</header>
</template>

<template v-slot:after="{ progress }">
<div class="flex justify-between w-full mt-1">
<span> <MoneyPresenter :value="fundMetrics.balance" />({{ progress}}%) </span>
<span>{{ budgetData.total?.toFixed?.(2) }} Months</span>
</div>
</template>
</BudgetProgress>
</section>
</template>
</WidgetContainer>
Expand Down
101 changes: 41 additions & 60 deletions resources/js/Pages/Dashboard/Partials/BudgetWidget.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,37 @@ import { ITransaction } from '@/domains/transactions/models';
import axios from 'axios';
import WidgetTitleCard from '@/Components/molecules/WidgetTitleCard.vue';
import LogerButton from '@/Components/atoms/LogerButton.vue';
import { useTransactionStore } from '@/store/transactions';
import { useI18n } from "vue-i18n";
// import VueApexCharts from "vue3-apexcharts";
import VueApexCharts from "vue3-apexcharts";
import { formatMoney } from '@/utils';
import BudgetProgress from '@/domains/budget/components/BudgetProgress.vue';
import { IBudgetStat } from '@/domains/budget/models/budget';

interface Stat {
label: string;
value: string|number;
}

const props = defineProps<{
budget: IBudgetStat
}>();


const stats = ref<{
budgeted: Stat;
spending: Stat;
budgetedSpending: Stat;
}>({
budgeted: {
value: 2000,
value: props.budget.spending,
label: 'Budgeted'
},
spending: {
value: 1000,
label: 'spending'
value: props.budget.savings,
label: 'Savings'
},
budgetedSpending: {
value: 1500,
value: 0,
label: 'Budgeted spending'
},
});
Expand Down Expand Up @@ -81,66 +87,29 @@ const chartConfig = {
series: Object.values(stats.value).map(item => item.value),
};
const legend = computed(() => {
return chartConfig.options.labels.map((label, index) => {
return {
label: label,
value: chartConfig.series[index],
color: "",
};
});
return chartConfig.options.labels.map((label, index) => {
return {
label: label,
value: chartConfig.series[index],
color: "",
};
});
});

const transactionsDraft = ref([]);
const isLoadingDrafts = ref(false);
const fetchTransactions = async () => {
const url = `/api/finance/transactions?filter[status]=draft&limit=10`;
return axios.get(url).then<ITransaction[]>(({ data }) => {
transactionsDraft.value = data;
isLoadingDrafts.value = false
})
}

onMounted(() => {
fetchTransactions()
})

const isLoading = ref(false);
const updateTransactions = () => {
isLoading.value = true;
fetchTransactions().finally(() => {
isLoading.value = false;
})
}

const transactionStore = useTransactionStore();
const unsubscribe = transactionStore.$onAction(({
name,
store,
args,
after
}) => {
after((result) => {
const [savedValue, action, originalData] = args;
if (originalData && originalData.status == 'draft' && savedValue.status == 'verified') {
fetchTransactions();
}
})
})
</script>

<template>
<WidgetTitleCard title="Budget balance" class="hidden md:block bg-primary text-white" :hide-divider="true">
<section class="w-full">
<section class="w-full py-3 relative h-[155px]">
<article style="width: 100%; height: 300px" class="relative py-1 mb-10">
<!-- <VueApexCharts
<VueApexCharts
ref="chartRef"
width="100%"
height="100%"
type="donut"
:options="chartConfig.options"
:series="chartConfig.series.map((value) => Number(value))"
/> -->
/>
</article>
</section>
<header class="mt-4 border-t py-4 flex items-start justify-between pb-2">
Expand All @@ -149,7 +118,7 @@ const unsubscribe = transactionStore.$onAction(({
>
<IMdiBankTransfer />
</section>
Budget total
Total
</h1>
<section class="space-x-2 w-full">
<h2 class="text-lg flex items-center font-bold">
Expand All @@ -168,30 +137,42 @@ const unsubscribe = transactionStore.$onAction(({
<article class="space-y-2 mt-4">
<BudgetProgress
class="h-2 rounded-sm"
:goal="2000"
:current="1500"
:goal="budget.total"
:current="budget.spending"
:progress-class="['bg-white', 'bg-primaryDark/60']"
:show-labels="false"
>
<template v-slot:before="{ progress }">
<header class="mb-1 font-bold text-xs flex justify-between w-full ">
<section>
Class a
For spending
</section>
<section >
{{ formatMoney(totals?.paid) }} / {{ formatMoney(totals?.total) }}
{{ formatMoney(budget.spending) }} / {{ formatMoney(budget?.total) }}
({{ progress }}%)
</section>
</header>
</template>
</BudgetProgress>
<BudgetProgress
class="h-2 rounded-sm"
:goal="1200"
:current="700"
:goal="budget.total"
:current="budget.savings"
:progress-class="['bg-white', 'bg-primaryDark/60']"
:show-labels="false"
/>
>
<template v-slot:before="{ progress }">
<header class="mb-1 font-bold text-xs flex justify-between w-full ">
<section>
For savings
</section>
<section >
{{ formatMoney(budget.savings) }} / {{ formatMoney(budget?.total) }}
({{ progress }}%)
</section>
</header>
</template>
</BudgetProgress>
</article>
</section>

Expand Down
Loading
Loading