diff --git a/app/Http/Controllers/AnalysisController.php b/app/Http/Controllers/AnalysisController.php
index 082ba05..7f31d93 100644
--- a/app/Http/Controllers/AnalysisController.php
+++ b/app/Http/Controllers/AnalysisController.php
@@ -10,23 +10,41 @@
use App\Models\OrderItem;
use App\Models\Payroll;
use App\Models\Purchase;
+use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Inertia\Inertia;
class AnalysisController extends Controller
{
- public function __invoke()
+ public function __invoke(Request $request)
{
+ $period = $request->input('period', 'all');
+ $startDate = $request->input('start_date');
+ $endDate = $request->input('end_date');
+
+ $applyFilter = function ($query, $column = 'created_at') use ($period, $startDate, $endDate) {
+ if ($startDate && $endDate) {
+ return $query->whereBetween($column, [$startDate.' 00:00:00', $endDate.' 23:59:59']);
+ }
+
+ return match ($period) {
+ 'week' => $query->whereBetween($column, [now()->startOfWeek(), now()->endOfWeek()]),
+ 'month' => $query->whereMonth($column, now()->month)->whereYear($column, now()->year),
+ 'year' => $query->whereYear($column, now()->year),
+ default => $query,
+ };
+ };
+
$stats = [
- 'total_sales' => $this->getStats(fn () => Order::count()),
- 'total_revenue' => $this->getStats(fn () => Order::sum('total')),
- 'total_expenses' => $this->getStats(fn () => Expense::sum('amount')),
- 'total_payrolls' => $this->getStats(fn () => Payroll::sum('total_salary')),
- 'cogs' => $this->getStats(fn () => Order::sum('hpp')),
- 'total_discount' => $this->getStats(fn () => Order::sum('discount')),
- 'total_purchases' => $this->getStats(fn () => Purchase::sum('total')),
- 'products_sold' => $this->getStats(fn () => OrderItem::sum('qty')),
- 'total_customers' => $this->getStats(fn () => Order::distinct('customer_name')->count('customer_name')),
+ 'total_sales' => $this->getStats(fn () => $applyFilter(Order::query())->count()),
+ 'total_revenue' => $this->getStats(fn () => $applyFilter(Order::query())->sum('total')),
+ 'total_expenses' => $this->getStats(fn () => $applyFilter(Expense::query())->sum('amount')),
+ 'total_payrolls' => $this->getStats(fn () => $applyFilter(Payroll::query(), 'period_month')->sum('total_salary')),
+ 'cogs' => $this->getStats(fn () => $applyFilter(Order::query())->sum('hpp')),
+ 'total_discount' => $this->getStats(fn () => $applyFilter(Order::query())->sum('discount')),
+ 'total_purchases' => $this->getStats(fn () => $applyFilter(Purchase::query())->sum('total')),
+ 'products_sold' => $this->getStats(fn () => $applyFilter(OrderItem::query())->sum('qty')),
+ 'total_customers' => $this->getStats(fn () => $applyFilter(Order::query())->distinct('customer_name')->count('customer_name')),
];
$stats['aov'] = $this->calculateAov($stats['total_revenue'], $stats['total_sales']);
@@ -38,8 +56,8 @@ public function __invoke()
];
$stats['profit_margin'] = $this->calculateMargin($stats['net_profit'], $stats['total_revenue']);
- // Revenue vs Purchases per month (this year)
- $revenueByMonth = DB::table('orders')
+ // Revenue vs Purchases per month
+ $revenueByMonth = $applyFilter(DB::table('orders'))
->select(
DB::raw('MONTH(created_at) as month'),
DB::raw('SUM(total) as total')
@@ -47,7 +65,7 @@ public function __invoke()
->groupBy(DB::raw('MONTH(created_at)'))
->get();
- $purchasesByMonth = DB::table('purchases')
+ $purchasesByMonth = $applyFilter(DB::table('purchases'))
->select(
DB::raw('MONTH(created_at) as month'),
DB::raw('SUM(total) as total')
@@ -68,7 +86,7 @@ public function __invoke()
];
});
- $paymentMethods = DB::table('orders')
+ $paymentMethods = $applyFilter(DB::table('orders'))
->select('payment_method as name', DB::raw('COUNT(*) as total'))
->groupBy('payment_method')
->get()
@@ -80,7 +98,7 @@ public function __invoke()
return $item;
});
- $orderStatuses = DB::table('orders')
+ $orderStatuses = $applyFilter(DB::table('orders'))
->select('order_status as name', DB::raw('COUNT(*) as total'))
->groupBy('order_status')
->get()
@@ -92,7 +110,7 @@ public function __invoke()
return $item;
});
- $orderChannels = DB::table('orders')
+ $orderChannels = $applyFilter(DB::table('orders'))
->select('order_channel as name', DB::raw('COUNT(*) as total'))
->groupBy('order_channel')
->get()
@@ -104,7 +122,7 @@ public function __invoke()
return $item;
});
- $topProducts = DB::table('order_items')
+ $topProducts = $applyFilter(DB::table('order_items'), 'order_items.created_at')
->join('products', 'order_items.product_id', '=', 'products.id')
->select('products.name as name', DB::raw('SUM(order_items.qty) as total'))
->groupBy('products.name')
@@ -112,7 +130,7 @@ public function __invoke()
->limit(5)
->get();
- $topCustomers = DB::table('orders')
+ $topCustomers = $applyFilter(DB::table('orders'), 'orders.created_at')
->select('customer_name as name', DB::raw('SUM(total) as total'))
->whereNotNull('customer_name')
->groupBy('customer_name')
@@ -120,7 +138,7 @@ public function __invoke()
->limit(5)
->get();
- $salesByHourRaw = DB::table('orders')
+ $salesByHourRaw = $applyFilter(DB::table('orders'))
->select(
DB::raw('HOUR(created_at) as hour'),
DB::raw('COUNT(*) as total')
@@ -138,7 +156,7 @@ public function __invoke()
});
// Revenue & Profit & Volume per month
- $ordersByMonth = DB::table('orders')
+ $ordersByMonth = $applyFilter(DB::table('orders'))
->select(
DB::raw('MONTH(created_at) as month'),
DB::raw('SUM(total) as revenue'),
@@ -148,7 +166,7 @@ public function __invoke()
->groupBy(DB::raw('MONTH(created_at)'))
->get();
- $expensesByMonth = DB::table('expenses')
+ $expensesByMonth = $applyFilter(DB::table('expenses'))
->select(
DB::raw('MONTH(created_at) as month'),
DB::raw('SUM(amount) as total')
@@ -156,7 +174,7 @@ public function __invoke()
->groupBy(DB::raw('MONTH(created_at)'))
->get();
- $payrollsByMonth = DB::table('payrolls')
+ $payrollsByMonth = $applyFilter(DB::table('payrolls'), 'period_month')
->select(
DB::raw('MONTH(period_month) as month'),
DB::raw('SUM(total_salary) as total')
@@ -196,7 +214,7 @@ public function __invoke()
];
});
- $topCategories = DB::table('order_items')
+ $topCategories = $applyFilter(DB::table('order_items'), 'order_items.created_at')
->join('products', 'order_items.product_id', '=', 'products.id')
->join('category_product', 'products.id', '=', 'category_product.product_id')
->join('categories', 'category_product.category_id', '=', 'categories.id')
@@ -219,6 +237,11 @@ public function __invoke()
'topProducts' => $topProducts,
'topCustomers' => $topCustomers,
'topCategories' => $topCategories,
+ 'filters' => [
+ 'period' => $period,
+ 'start_date' => $startDate,
+ 'end_date' => $endDate,
+ ],
]);
}
diff --git a/resources/js/pages/analysis.tsx b/resources/js/pages/analysis.tsx
index 0cf9aeb..fd7fd4c 100644
--- a/resources/js/pages/analysis.tsx
+++ b/resources/js/pages/analysis.tsx
@@ -1,27 +1,193 @@
import { StatCard } from '@/components/cards/stat-card';
+import { Button } from '@/components/ui/button';
+import { Calendar } from '@/components/ui/calendar';
+import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
+import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { analysis } from '@/routes';
import type { AnalysisPageProps } from '@/types';
-import { Head, usePage } from '@inertiajs/react';
+import { Head, router, usePage } from '@inertiajs/react';
+import { CalendarIcon, Filter, FilterX } from 'lucide-react';
+import { useState } from 'react';
+import { AovTrendChart } from '../components/charts/aov-trend-chart';
import { CustomBarChart } from '../components/charts/bar-chart';
import { CustomPieChart } from '../components/charts/pie-chart';
import { RevenueVsProfitChart } from '../components/charts/revenue-vs-profit-chart';
-import { TransactionVolumeChart } from '../components/charts/transaction-volume-chart';
-import { AovTrendChart } from '../components/charts/aov-trend-chart';
import { RevenueVsPurchasesChart } from '../components/charts/revenue-vs-purchases-chart';
import { SalesByHourChart } from '../components/charts/sales-by-hour-chart';
+import { TransactionVolumeChart } from '../components/charts/transaction-volume-chart';
export default function Analisa() {
- const { stats, salesByMonth, revenueVsProfit, transactionVolume, salesByHour, paymentMethods, orderStatuses, orderChannels, topProducts, topCustomers, topCategories } =
+ const { stats, salesByMonth, revenueVsProfit, transactionVolume, salesByHour, paymentMethods, orderStatuses, orderChannels, topProducts, topCustomers, topCategories, filters } =
usePage
Lihat performa bisnis Anda secara mendalam.
+