From c00e5bba0da9e7df4ca0875e3f2190bdd1a03dad Mon Sep 17 00:00:00 2001 From: Jesus Guerrero Date: Thu, 31 Aug 2023 22:59:41 -0400 Subject: [PATCH 1/2] fix: set dates to budget transactions --- resources/js/Components/atoms/BalanceInput.vue | 5 +++-- resources/js/Components/atoms/FiltersPopover.vue | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/resources/js/Components/atoms/BalanceInput.vue b/resources/js/Components/atoms/BalanceInput.vue index b106a843..6ddb654a 100644 --- a/resources/js/Components/atoms/BalanceInput.vue +++ b/resources/js/Components/atoms/BalanceInput.vue @@ -75,7 +75,8 @@ import { ICategory } from "@/domains/transactions/models"; budgeted: BALANCE_STATUS.available ? data.amount : props.category.budgeted + data.amount, [field]: props.category.id, source_category_id: data.source_category_id?.value, - type: 'movement' + type: 'movement', + date: format(new Date(), 'yyyy-MM-dd') })).post(`/budgets/${props.category.id}/months/${month}`, { preserveState: true, preserveScroll: true @@ -152,7 +153,7 @@ import { ICategory } from "@/domains/transactions/models"; diff --git a/resources/js/Components/atoms/FiltersPopover.vue b/resources/js/Components/atoms/FiltersPopover.vue index 231a9811..aa6330c3 100644 --- a/resources/js/Components/atoms/FiltersPopover.vue +++ b/resources/js/Components/atoms/FiltersPopover.vue @@ -9,7 +9,7 @@
- +
@@ -88,7 +88,8 @@ ...data, budgeted: BALANCE_STATUS.available ? data.amount : props.category.budgeted + data.amount, [field]: props.category.id, - type: 'movement' + type: 'movement', + date: format(new Date(), 'yyyy-MM-dd') })).post(`/budgets/${props.category.id}/months/${month}`, { preserveState: true, preserveScroll: true From ebf4d76b483c7a3ad347a187cae3370d34334048 Mon Sep 17 00:00:00 2001 From: Jesus Guerrero Date: Thu, 31 Aug 2023 22:59:55 -0400 Subject: [PATCH 2/2] fix: set dates to budget transactions --- app/Domains/Budget/Models/BudgetMovement.php | 4 +- .../Finance/BudgetCategoryController.php | 3 +- .../Finance/FinanceAccountController.php | 5 +- .../Controllers/Finance/FinanceController.php | 5 +- .../Finance/FinanceTransactionController.php | 8 +- .../System/DashboardController.php | 8 +- .../Controllers/Traits/HasEnrichedRequest.php | 6 +- package-lock.json | 312 +++++++++++++++++- package.json | 1 + resources/js/Components/shared/BaseTable.vue | 235 +++++++++++++ resources/js/Pages/Finance/Budget.vue | 1 + resources/js/Pages/Finance/Transactions.vue | 2 +- resources/js/app.js | 5 +- resources/js/composables/useServerSearch.ts | 13 +- resources/js/domains/budget/budgetCols.ts | 3 +- .../budget/components/BudgetBalanceAssign.vue | 3 +- .../domains/budget/components/BudgetItem.vue | 5 +- 17 files changed, 577 insertions(+), 42 deletions(-) create mode 100644 resources/js/Components/shared/BaseTable.vue diff --git a/app/Domains/Budget/Models/BudgetMovement.php b/app/Domains/Budget/Models/BudgetMovement.php index d72feb89..5c678ce7 100644 --- a/app/Domains/Budget/Models/BudgetMovement.php +++ b/app/Domains/Budget/Models/BudgetMovement.php @@ -12,7 +12,7 @@ class BudgetMovement extends Model use HasFactory; protected $fillable = ['team_id', 'user_id', 'source_category_id', 'destination_category_id', 'amount', 'date']; - public static function registerMovement($monthBudget, $form) { + public static function registerMovement(BudgetMonth $monthBudget, $form) { DB::beginTransaction(); $session = [ 'team_id' => $monthBudget->team_id, @@ -38,7 +38,7 @@ public static function registerMovement($monthBudget, $form) { 'source_category_id' => $sourceId, 'destination_category_id' => $destinationId, 'amount' => $amount, - 'date' => date('Y-m-d') + 'date' => $form['date'] ]); $savedMovement = self::create($formData); diff --git a/app/Http/Controllers/Finance/BudgetCategoryController.php b/app/Http/Controllers/Finance/BudgetCategoryController.php index 4f71714a..5ee6bf71 100644 --- a/app/Http/Controllers/Finance/BudgetCategoryController.php +++ b/app/Http/Controllers/Finance/BudgetCategoryController.php @@ -8,6 +8,7 @@ use App\Domains\Transaction\Models\Transaction; use App\Domains\Transaction\Services\ReportService; use App\Http\Resources\CategoryGroupCollection; +use App\Models\Setting; use Freesgen\Atmosphere\Http\InertiaController; use Illuminate\Http\Request; use Illuminate\Support\Facades\Redirect; @@ -32,11 +33,9 @@ public function __construct(Category $category) ]; $this->sorts = ['index']; $this->includes = ['subCategories', 'subCategories.budget', 'subCategories.budgets']; - $dates = $this->getFilterDates(); $this->filters = [ 'parent_id' => '$null', 'resource_type' => 'transactions', - 'date' => "{$dates['0']}~{$dates['1']}", ]; $this->resourceName= "budgets"; } diff --git a/app/Http/Controllers/Finance/FinanceAccountController.php b/app/Http/Controllers/Finance/FinanceAccountController.php index 9f884e45..56c70ff1 100644 --- a/app/Http/Controllers/Finance/FinanceAccountController.php +++ b/app/Http/Controllers/Finance/FinanceAccountController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers\Finance; use App\Domains\Transaction\Services\ReportService; +use App\Models\Setting; use Freesgen\Atmosphere\Http\InertiaController; use Freesgen\Atmosphere\Http\Querify; use Illuminate\Support\Facades\Gate; @@ -32,13 +33,13 @@ public function __construct(Account $account, ReportService $reportService) public function show(Account $account) { $queryParams = request()->query(); $response = Gate::inspect('show', $account); - + $settings = Setting::getByTeam(auth()->user()->current_team_id); if (!$response->allowed()) { return redirect(route('finance')); } $filters = isset($queryParams['filter']) ? $queryParams['filter'] : []; - [$startDate, $endDate] = $this->getFilterDates($filters); + [$startDate, $endDate] = $this->getFilterDates($filters, $settings["team_timezone"]); return inertia($this->templates['show'], [ "sectionTitle" => $account->name, diff --git a/app/Http/Controllers/Finance/FinanceController.php b/app/Http/Controllers/Finance/FinanceController.php index a56e831f..646c3591 100644 --- a/app/Http/Controllers/Finance/FinanceController.php +++ b/app/Http/Controllers/Finance/FinanceController.php @@ -7,6 +7,7 @@ use App\Domains\Transaction\Models\Transaction; use App\Domains\Transaction\Services\PlannedTransactionService; use App\Domains\Transaction\Services\TransactionService; +use App\Models\Setting; use Carbon\Carbon; use Illuminate\Http\Request; use Laravel\Jetstream\Jetstream; @@ -26,9 +27,11 @@ public function __construct(Transaction $transaction, private TransactionService public function index(Request $request) { $teamId = $request->user()->current_team_id; + $settings = Setting::getByTeam(auth()->user()->current_team_id); + $queryParams = $request->query(); $filters = isset($queryParams['filter']) ? $queryParams['filter'] : []; - [$startDate, $endDate] = $this->getFilterDates($filters); + [$startDate, $endDate] = $this->getFilterDates($filters, $settings['team_timezone']); $lastMonthStartDate = Carbon::createFromFormat(self::DateFormat, $startDate)->subMonth()->startOfMonth()->format(self::DateFormat); $lastMonthEndDate = Carbon::createFromFormat(self::DateFormat, $startDate)->subMonth()->endOfMonth()->format(self::DateFormat); diff --git a/app/Http/Controllers/Finance/FinanceTransactionController.php b/app/Http/Controllers/Finance/FinanceTransactionController.php index b9d5ce45..3bb449f2 100644 --- a/app/Http/Controllers/Finance/FinanceTransactionController.php +++ b/app/Http/Controllers/Finance/FinanceTransactionController.php @@ -36,9 +36,7 @@ public function __construct(Transaction $transaction, private PlannedTransaction 'counterLine.account' ]; $this->appends = []; - $dates = $this->getFilterDates(); $this->filters = [ - 'date' => "{$dates['0']}~{$dates['1']}", 'status' => Transaction::STATUS_VERIFIED ]; } @@ -67,14 +65,14 @@ protected function list(Request $request) { transactions.description, date, transactions.direction, - transactions.status, + transactions.status, total, transactions.account_id, counter_account_id, payee_id, categories.name category_name, payees.name payee_name, - ca.name counter_account_name, + ca.name counter_account_name, accounts.name account_name ") ->leftJoin('categories', 'categories.id', 'transactions.category_id') @@ -178,7 +176,7 @@ private function getOptionParams() { return $queryParams; } - + public function bulkDelete(Request $request) { $items = $request->post('data'); diff --git a/app/Http/Controllers/System/DashboardController.php b/app/Http/Controllers/System/DashboardController.php index 378b27c7..b07a1a05 100644 --- a/app/Http/Controllers/System/DashboardController.php +++ b/app/Http/Controllers/System/DashboardController.php @@ -7,18 +7,20 @@ use App\Domains\Meal\Services\MealService; use App\Domains\Transaction\Services\ReportService; use App\Domains\Transaction\Services\TransactionService; +use App\Http\Controllers\Traits\HasEnrichedRequest; use App\Http\Resources\PlannedMealResource; -use Carbon\Carbon; class DashboardController { + use HasEnrichedRequest; + public function __construct(private MealService $mealService) { } + public function __invoke() { $request = request(); - $startDate = $request->query('startDate', Carbon::now()->startOfMonth()->format('Y-m-d')); - $endDate = $request->query('endDate', Carbon::now()->endOfMonth()->format('Y-m-d')); + [$startDate, $endDate] = $this->getFilterDates(); $team = $request->user()->currentTeam; $teamId = $request->user()->current_team_id; $budget = BudgetMonth::getMonthAssignmentTotal($teamId, $startDate); diff --git a/app/Http/Controllers/Traits/HasEnrichedRequest.php b/app/Http/Controllers/Traits/HasEnrichedRequest.php index 38833b87..f157240f 100644 --- a/app/Http/Controllers/Traits/HasEnrichedRequest.php +++ b/app/Http/Controllers/Traits/HasEnrichedRequest.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers\Traits; +use App\Models\Setting; use Illuminate\Support\Carbon; trait HasEnrichedRequest { @@ -27,9 +28,10 @@ protected function getPostData() { } protected function getFilterDates($filters = [], $subCount=0) { + $settings = Setting::getByTeam(auth()->user()->current_team_id); $dates = isset($filters['date']) ? explode("~", $filters['date']) : [ - Carbon::now()->subMonths($subCount)->startOfMonth()->format('Y-m-d'), - Carbon::now()->endOfMonth()->format('Y-m-d') + Carbon::now()->setTimezone($settings["team_timezone"])->subMonths($subCount)->startOfMonth()->format('Y-m-d'), + Carbon::now()->setTimezone($settings["team_timezone"])->endOfMonth()->format('Y-m-d') ]; return $dates; } diff --git a/package-lock.json b/package-lock.json index 80e25be8..3962acc7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "@formkit/auto-animate": "^1.0.0-beta.1", "@vueuse/components": "^10.3.0", "chart.js": "^4.3.3", + "element-plus": "^2.3.12", "firebase": "^10.2.0", "fuse.js": "^6.6.2", "luxon": "^3.4.0", @@ -2271,6 +2272,14 @@ "vue": "^3.0.11" } }, + "node_modules/@ctrl/tinycolor": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", + "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", + "engines": { + "node": ">=10" + } + }, "node_modules/@cypress/request": { "version": "2.88.11", "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.11.tgz", @@ -2357,6 +2366,14 @@ "ms": "^2.1.1" } }, + "node_modules/@element-plus/icons-vue": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-2.1.0.tgz", + "integrity": "sha512-PSBn3elNoanENc1vnCfh+3WA9fimRC7n+fWkf3rE5jvv+aBohNHABC/KAR5KWPecxWxDTVT1ERpRbOMRcOV/vA==", + "peerDependencies": { + "vue": "^3.2.0" + } + }, "node_modules/@emotion/hash": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", @@ -3260,6 +3277,28 @@ "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.10.1.tgz", "integrity": "sha512-Dq5rYfEpdeel0bLVN+nfD1VWmzCkK+pJbSjIawGE+RY4+NIJqhbUDDQjvV0NUK84fMfwxvtFoCtEe70HfZjFcw==" }, + "node_modules/@floating-ui/core": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.4.1.tgz", + "integrity": "sha512-jk3WqquEJRlcyu7997NtR5PibI+y5bi+LS3hPmguVClypenMsCY3CBa3LAQnozRCtCrYWSEtAdiskpamuJRFOQ==", + "dependencies": { + "@floating-ui/utils": "^0.1.1" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.1.tgz", + "integrity": "sha512-KwvVcPSXg6mQygvA1TjbN/gh///36kKtllIF8SUm0qpFj8+rvYrpvlYdL1JoA71SHpDqgSSdGOSoQ0Mp3uY5aw==", + "dependencies": { + "@floating-ui/core": "^1.4.1", + "@floating-ui/utils": "^0.1.1" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.1.tgz", + "integrity": "sha512-m0G6wlnhm/AX0H12IOWtK8gASEMffnX08RtKkCgTdHb9JpHKGloI7icFfLg9ZmQeavcvR0PKmzxClyuFPSjKWw==" + }, "node_modules/@formkit/auto-animate": { "version": "1.0.0-beta.5", "resolved": "https://registry.npmjs.org/@formkit/auto-animate/-/auto-animate-1.0.0-beta.5.tgz", @@ -3901,7 +3940,6 @@ "version": "2.11.8", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", - "dev": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/popperjs" @@ -5488,8 +5526,7 @@ "node_modules/async-validator": { "version": "4.2.5", "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz", - "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==", - "dev": true + "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==" }, "node_modules/asynckit": { "version": "0.4.0", @@ -7151,6 +7188,124 @@ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.496.tgz", "integrity": "sha512-qeXC3Zbykq44RCrBa4kr8v/dWzYJA8rAwpyh9Qd+NKWoJfjG5vvJqy9XOJ9H4P/lqulZBCgUWAYi+FeK5AuJ8g==" }, + "node_modules/element-plus": { + "version": "2.3.12", + "resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.3.12.tgz", + "integrity": "sha512-fAWpbKCyt+l1dsqSNPOs/F/dBN4Wp5CGAyxbiS5zqDwI4q3QPM+LxLU2h3GUHMIBtMGCvmsG98j5HPMkTKkvcA==", + "dependencies": { + "@ctrl/tinycolor": "^3.4.1", + "@element-plus/icons-vue": "^2.0.6", + "@floating-ui/dom": "^1.0.1", + "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7", + "@types/lodash": "^4.14.182", + "@types/lodash-es": "^4.17.6", + "@vueuse/core": "^9.1.0", + "async-validator": "^4.2.5", + "dayjs": "^1.11.3", + "escape-html": "^1.0.3", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "lodash-unified": "^1.0.2", + "memoize-one": "^6.0.0", + "normalize-wheel-es": "^1.2.0" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/element-plus/node_modules/@types/web-bluetooth": { + "version": "0.0.16", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz", + "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==" + }, + "node_modules/element-plus/node_modules/@vueuse/core": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.13.0.tgz", + "integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==", + "dependencies": { + "@types/web-bluetooth": "^0.0.16", + "@vueuse/metadata": "9.13.0", + "@vueuse/shared": "9.13.0", + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/element-plus/node_modules/@vueuse/core/node_modules/vue-demi": { + "version": "0.14.6", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz", + "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/element-plus/node_modules/@vueuse/metadata": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz", + "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/element-plus/node_modules/@vueuse/shared": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz", + "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==", + "dependencies": { + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/element-plus/node_modules/@vueuse/shared/node_modules/vue-demi": { + "version": "0.14.6", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz", + "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/element-plus/node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -7398,8 +7553,7 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "peer": true + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "node_modules/escape-latex": { "version": "1.2.0", @@ -9870,14 +10024,23 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "node_modules/lodash-es": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" }, + "node_modules/lodash-unified": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/lodash-unified/-/lodash-unified-1.0.3.tgz", + "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==", + "peerDependencies": { + "@types/lodash-es": "*", + "lodash": "*", + "lodash-es": "*" + } + }, "node_modules/lodash._reinterpolate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", @@ -11393,6 +11556,11 @@ "node": ">=0.10.0" } }, + "node_modules/normalize-wheel-es": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz", + "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==" + }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -16832,6 +17000,11 @@ "dev": true, "requires": {} }, + "@ctrl/tinycolor": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", + "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==" + }, "@cypress/request": { "version": "2.88.11", "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.11.tgz", @@ -16907,6 +17080,12 @@ } } }, + "@element-plus/icons-vue": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-2.1.0.tgz", + "integrity": "sha512-PSBn3elNoanENc1vnCfh+3WA9fimRC7n+fWkf3rE5jvv+aBohNHABC/KAR5KWPecxWxDTVT1ERpRbOMRcOV/vA==", + "requires": {} + }, "@emotion/hash": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", @@ -17524,6 +17703,28 @@ "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.10.1.tgz", "integrity": "sha512-Dq5rYfEpdeel0bLVN+nfD1VWmzCkK+pJbSjIawGE+RY4+NIJqhbUDDQjvV0NUK84fMfwxvtFoCtEe70HfZjFcw==" }, + "@floating-ui/core": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.4.1.tgz", + "integrity": "sha512-jk3WqquEJRlcyu7997NtR5PibI+y5bi+LS3hPmguVClypenMsCY3CBa3LAQnozRCtCrYWSEtAdiskpamuJRFOQ==", + "requires": { + "@floating-ui/utils": "^0.1.1" + } + }, + "@floating-ui/dom": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.1.tgz", + "integrity": "sha512-KwvVcPSXg6mQygvA1TjbN/gh///36kKtllIF8SUm0qpFj8+rvYrpvlYdL1JoA71SHpDqgSSdGOSoQ0Mp3uY5aw==", + "requires": { + "@floating-ui/core": "^1.4.1", + "@floating-ui/utils": "^0.1.1" + } + }, + "@floating-ui/utils": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.1.tgz", + "integrity": "sha512-m0G6wlnhm/AX0H12IOWtK8gASEMffnX08RtKkCgTdHb9JpHKGloI7icFfLg9ZmQeavcvR0PKmzxClyuFPSjKWw==" + }, "@formkit/auto-animate": { "version": "1.0.0-beta.5", "resolved": "https://registry.npmjs.org/@formkit/auto-animate/-/auto-animate-1.0.0-beta.5.tgz", @@ -18034,8 +18235,7 @@ "@popperjs/core": { "version": "2.11.8", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", - "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", - "dev": true + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==" }, "@protobufjs/aspromise": { "version": "1.1.2", @@ -19306,8 +19506,7 @@ "async-validator": { "version": "4.2.5", "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz", - "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==", - "dev": true + "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==" }, "asynckit": { "version": "0.4.0", @@ -20525,6 +20724,80 @@ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.496.tgz", "integrity": "sha512-qeXC3Zbykq44RCrBa4kr8v/dWzYJA8rAwpyh9Qd+NKWoJfjG5vvJqy9XOJ9H4P/lqulZBCgUWAYi+FeK5AuJ8g==" }, + "element-plus": { + "version": "2.3.12", + "resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.3.12.tgz", + "integrity": "sha512-fAWpbKCyt+l1dsqSNPOs/F/dBN4Wp5CGAyxbiS5zqDwI4q3QPM+LxLU2h3GUHMIBtMGCvmsG98j5HPMkTKkvcA==", + "requires": { + "@ctrl/tinycolor": "^3.4.1", + "@element-plus/icons-vue": "^2.0.6", + "@floating-ui/dom": "^1.0.1", + "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7", + "@types/lodash": "^4.14.182", + "@types/lodash-es": "^4.17.6", + "@vueuse/core": "^9.1.0", + "async-validator": "^4.2.5", + "dayjs": "^1.11.3", + "escape-html": "^1.0.3", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "lodash-unified": "^1.0.2", + "memoize-one": "^6.0.0", + "normalize-wheel-es": "^1.2.0" + }, + "dependencies": { + "@types/web-bluetooth": { + "version": "0.0.16", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz", + "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==" + }, + "@vueuse/core": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.13.0.tgz", + "integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==", + "requires": { + "@types/web-bluetooth": "^0.0.16", + "@vueuse/metadata": "9.13.0", + "@vueuse/shared": "9.13.0", + "vue-demi": "*" + }, + "dependencies": { + "vue-demi": { + "version": "0.14.6", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz", + "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==", + "requires": {} + } + } + }, + "@vueuse/metadata": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz", + "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==" + }, + "@vueuse/shared": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz", + "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==", + "requires": { + "vue-demi": "*" + }, + "dependencies": { + "vue-demi": { + "version": "0.14.6", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz", + "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==", + "requires": {} + } + } + }, + "memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + } + } + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -20720,8 +20993,7 @@ "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "peer": true + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "escape-latex": { "version": "1.2.0", @@ -22539,14 +22811,19 @@ "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "lodash-es": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" }, + "lodash-unified": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/lodash-unified/-/lodash-unified-1.0.3.tgz", + "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==", + "requires": {} + }, "lodash._reinterpolate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", @@ -23759,6 +24036,11 @@ "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", "dev": true }, + "normalize-wheel-es": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz", + "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==" + }, "npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", diff --git a/package.json b/package.json index 5596510d..82626fe1 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,7 @@ "@formkit/auto-animate": "^1.0.0-beta.1", "@vueuse/components": "^10.3.0", "chart.js": "^4.3.3", + "element-plus": "^2.3.12", "firebase": "^10.2.0", "fuse.js": "^6.6.2", "luxon": "^3.4.0", diff --git a/resources/js/Components/shared/BaseTable.vue b/resources/js/Components/shared/BaseTable.vue new file mode 100644 index 00000000..859bbb00 --- /dev/null +++ b/resources/js/Components/shared/BaseTable.vue @@ -0,0 +1,235 @@ + + + + + diff --git a/resources/js/Pages/Finance/Budget.vue b/resources/js/Pages/Finance/Budget.vue index 7c7644bf..50834311 100644 --- a/resources/js/Pages/Finance/Budget.vue +++ b/resources/js/Pages/Finance/Budget.vue @@ -55,6 +55,7 @@ const { state: pageState, executeSearchWithDelay } = useServerSearch( serverSearchOptions, { manual: true, + defaultDates: true, } ); diff --git a/resources/js/Pages/Finance/Transactions.vue b/resources/js/Pages/Finance/Transactions.vue index c096eafc..12924072 100644 --- a/resources/js/Pages/Finance/Transactions.vue +++ b/resources/js/Pages/Finance/Transactions.vue @@ -64,7 +64,7 @@ const { state: pageState, executeSearch, reset, -} = useServerSearch(serverSearchOptions, { manual: false }, async (urlParams) => { +} = useServerSearch(serverSearchOptions, { manual: false, defaultDates: true }, async (urlParams) => { if (isLoading.value) return; const url = `/api/finance/transactions?${urlParams}`; isLoading.value = true diff --git a/resources/js/app.js b/resources/js/app.js index 5e8df985..f1dce721 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -12,6 +12,8 @@ import VueMultiselect from 'vue-multiselect' import { autoAnimatePlugin } from '@formkit/auto-animate/vue' import { createPinia } from 'pinia'; import { vRipple } from './utils/vRipple'; +import ElementPlus from 'element-plus' +import 'element-plus/dist/index.css' const localesMessages = Object.fromEntries( Object.entries( @@ -52,6 +54,7 @@ createInertiaApp({ .use(pinia) .use(ZiggyVue, Ziggy) .use(autoAnimatePlugin) + .use(ElementPlus) .component('Multiselect', VueMultiselect) .directive('ripple', vRipple) .provide("router", router) @@ -68,4 +71,4 @@ createInertiaApp({ }) .mount(el); } -}); \ No newline at end of file +}); diff --git a/resources/js/composables/useServerSearch.ts b/resources/js/composables/useServerSearch.ts index c6cdcf6d..c01615a5 100644 --- a/resources/js/composables/useServerSearch.ts +++ b/resources/js/composables/useServerSearch.ts @@ -1,5 +1,5 @@ import { router } from '@inertiajs/vue3'; -import { format, parseISO } from "date-fns"; +import { endOfMonth, format, parseISO, startOfMonth } from "date-fns"; import { reactive, Ref, watch, nextTick, computed, ref } from "vue" import debounce from 'lodash/debounce'; @@ -16,6 +16,7 @@ export interface IServerSearchData { interface IServerSearchOptions { manual?: Boolean, mainDateField?: string, + defaultDates?: boolean } interface IDateSpan { startDate: Date|null; @@ -85,8 +86,12 @@ export const parseParams = (state: ISearchState) => { return params.filter(value => typeof value == 'string' && value?.trim() || value).join("&"); } -function parseDateFilters(options: Ref>) { - const dates = options?.value.filters?.date ? options.value.filters.date.split('~') : [null, null] +function parseDateFilters(options: Ref>, setDefaultDate: boolean) { + const dates = options?.value.filters?.date ? options.value.filters.date.split('~') : [ + setDefaultDate ? format(startOfMonth(new Date()), 'yyyy-MM-dd') : null, + setDefaultDate ? format(endOfMonth(new Date()), 'yyyy-MM-dd') : null + ]; + return { startDate: dates[0] && parseISO(dates[0]), endDate: dates.length == 2 && dates[1] && dates[1] !== "" ? parseISO(dates[1]) : null @@ -110,7 +115,7 @@ export const defaultSearchInertia = async (urlParams: string) => { } export const useServerSearch = (serverSearchData: Ref>, options: IServerSearchOptions = {}, onUrlChange = defaultSearchInertia) => { - const dates = parseDateFilters(serverSearchData) + const dates = parseDateFilters(serverSearchData, options.defaultDates) const isLoaded = ref(false) const state = reactive({ diff --git a/resources/js/domains/budget/budgetCols.ts b/resources/js/domains/budget/budgetCols.ts index 6b6cb97e..4bde3970 100644 --- a/resources/js/domains/budget/budgetCols.ts +++ b/resources/js/domains/budget/budgetCols.ts @@ -67,7 +67,8 @@ export const budgetCols = (state) => { const month = format(startOfMonth(new Date()), 'yyyy-MM-dd'); router.post(`/budgets/${row.id}/months/${month}`, { id: row.id, - budgeted: row.budgeted + budgeted: row.budgeted, + date: format(new Date(), 'yyyy-MM-dd') }, { preserveState: true, preserveScroll: true diff --git a/resources/js/domains/budget/components/BudgetBalanceAssign.vue b/resources/js/domains/budget/components/BudgetBalanceAssign.vue index 9ea7faa6..ba389d2b 100644 --- a/resources/js/domains/budget/components/BudgetBalanceAssign.vue +++ b/resources/js/domains/budget/components/BudgetBalanceAssign.vue @@ -102,7 +102,8 @@ budgeted: Math.abs(props.value), [field]: props.category.id, source_category_id: data.source_category_id?.value, - 'type': 'movement' + 'type': 'movement', + date: format(new Date(), 'yyyy-MM-dd') })).post(`/budgets/${props.category.id}/months/${month}`, { onSuccess() { router.reload({ diff --git a/resources/js/domains/budget/components/BudgetItem.vue b/resources/js/domains/budget/components/BudgetItem.vue index f3069003..88980b7e 100644 --- a/resources/js/domains/budget/components/BudgetItem.vue +++ b/resources/js/domains/budget/components/BudgetItem.vue @@ -34,7 +34,7 @@ const budgetTarget = computed(() => { }) const lastMonthAmount = computed(() => { - // @ts-ignore: + // @ts-ignore: return props.item.budgets?.at?.(2)?.budgeted ?? 0 }) @@ -87,7 +87,8 @@ const onAssignBudget = () => { router.post(`/budgets/${props.item.id}/months/${month}`, { id: props.item.id, - budgeted: Number(budgeted.value) + budgeted: Number(budgeted.value), + date: format(new Date(), 'yyyy-MM-dd') }, { preserveState: true, preserveScroll: true