feat: remove summary calculation and related component from Transaction management
This commit is contained in:
parent
bdfb75f2f7
commit
86cc8637bd
@ -37,7 +37,6 @@ public function index(PaginatedRequest $request): Response
|
|||||||
filters: $filters,
|
filters: $filters,
|
||||||
user: $user,
|
user: $user,
|
||||||
),
|
),
|
||||||
'summary' => $this->service->getSummary($filters, $user),
|
|
||||||
'filters' => $filters,
|
'filters' => $filters,
|
||||||
'filterOptions' => $this->service->getFilterOptions(),
|
'filterOptions' => $this->service->getFilterOptions(),
|
||||||
'highlight' => $request->input('highlight'),
|
'highlight' => $request->input('highlight'),
|
||||||
|
|||||||
@ -154,34 +154,6 @@ public function getItems(Order $order): \Illuminate\Support\Collection
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSummary(array $filters = [], ?User $user = null): array
|
|
||||||
{
|
|
||||||
$query = Order::query()
|
|
||||||
->selectRaw('COUNT(*) as total_orders')
|
|
||||||
->selectRaw('COALESCE(SUM(total_amount), 0) as total_amount')
|
|
||||||
->selectRaw('COALESCE(SUM(discount), 0) as total_discount')
|
|
||||||
->selectRaw('COALESCE(SUM(nego_price), 0) as total_deduction')
|
|
||||||
->selectRaw('COALESCE(SUM(cogs), 0) as total_cogs')
|
|
||||||
->when($user && $this->isMarketingUser($user), fn ($q) => $q->where('marketing_id', $user->id))
|
|
||||||
->when($filters['status'] ?? null, fn ($q, $status) => $q->where('status', $status))
|
|
||||||
->when($filters['channel'] ?? null, fn ($q, $channel) => $q->where('channel', $channel))
|
|
||||||
->when($filters['payment_type'] ?? null, fn ($q, $paymentType) => $q->where('payment_type', $paymentType))
|
|
||||||
->when($filters['customer_id'] ?? null, fn ($q, $customerId) => $q->where('customer_id', $customerId))
|
|
||||||
->when($filters['marketing_id'] ?? null, fn ($q, $marketingId) => $q->where('marketing_id', $marketingId))
|
|
||||||
->when($filters['created_by_id'] ?? null, fn ($q, $createdById) => $q->where('created_by_id', $createdById))
|
|
||||||
->when($filters['date_from'] ?? null, fn ($q, $dateFrom) => $q->whereDate('created_at', '>=', $dateFrom))
|
|
||||||
->when($filters['date_to'] ?? null, fn ($q, $dateTo) => $q->whereDate('created_at', '<=', $dateTo))
|
|
||||||
->first();
|
|
||||||
|
|
||||||
return [
|
|
||||||
'total_orders' => $query->total_orders,
|
|
||||||
'total_amount' => $query->total_amount,
|
|
||||||
'total_discount' => $query->total_discount,
|
|
||||||
'total_deduction' => $query->total_deduction,
|
|
||||||
'net_total' => $query->total_amount - $query->total_cogs,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getFilterOptions(): array
|
public function getFilterOptions(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
|||||||
@ -1,13 +1,7 @@
|
|||||||
import { Head, Link, router, usePage } from '@inertiajs/react';
|
import { CardTable, FilterPopover } from '@/components/data-display';
|
||||||
import { format } from 'date-fns';
|
|
||||||
import { Bluetooth, Cable, Plus, Printer, Unplug } from 'lucide-react';
|
|
||||||
import { useCallback, useMemo, useState } from 'react';
|
|
||||||
import { toast } from 'sonner';
|
|
||||||
import { CardTable } from '@/components/data-display';
|
|
||||||
import { DatePicker } from '@/components/inputs';
|
|
||||||
import { DeleteConfirmDialog } from '@/components/dialogs';
|
import { DeleteConfirmDialog } from '@/components/dialogs';
|
||||||
import { FilterPopover } from '@/components/data-display';
|
|
||||||
import { useCardTableExpand } from '@/components/hooks/use-card-table-expand';
|
import { useCardTableExpand } from '@/components/hooks/use-card-table-expand';
|
||||||
|
import { DatePicker } from '@/components/inputs';
|
||||||
import { PageHeader } from '@/components/layout';
|
import { PageHeader } from '@/components/layout';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import {
|
import {
|
||||||
@ -34,19 +28,23 @@ import {
|
|||||||
} from '@/components/ui/select';
|
} from '@/components/ui/select';
|
||||||
import { useCan } from '@/hooks/use-can';
|
import { useCan } from '@/hooks/use-can';
|
||||||
import { useServerTable } from '@/hooks/use-server-table';
|
import { useServerTable } from '@/hooks/use-server-table';
|
||||||
import { useThermalPrinter, encodeOrderReceipt } from '@/hooks/use-thermal-printer';
|
import { encodeOrderReceipt, useThermalPrinter } from '@/hooks/use-thermal-printer';
|
||||||
import {
|
import {
|
||||||
destroy,
|
destroy,
|
||||||
create as transactionCreate,
|
create as transactionCreate,
|
||||||
index as transactionIndex,
|
|
||||||
edit as transactionEdit,
|
edit as transactionEdit,
|
||||||
updateStatus as transactionUpdateStatus,
|
index as transactionIndex,
|
||||||
items as transactionItems,
|
items as transactionItems,
|
||||||
|
updateStatus as transactionUpdateStatus,
|
||||||
} from '@/routes/admin/manage/transactions';
|
} from '@/routes/admin/manage/transactions';
|
||||||
|
import { Head, Link, router, usePage } from '@inertiajs/react';
|
||||||
|
import { format } from 'date-fns';
|
||||||
|
import { Bluetooth, Cable, Plus, Printer, Unplug } from 'lucide-react';
|
||||||
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
|
import { toast } from 'sonner';
|
||||||
import type { Transaction, TransactionItem } from './columns';
|
import type { Transaction, TransactionItem } from './columns';
|
||||||
import { TransactionCardRow } from './transaction-card';
|
import { TransactionCardRow } from './transaction-card';
|
||||||
import { TransactionItemSubRow } from './transaction-sub-row';
|
import { TransactionItemSubRow } from './transaction-sub-row';
|
||||||
import { TransactionSummaryCard } from './transaction-summary-card';
|
|
||||||
|
|
||||||
type FilterOption = {
|
type FilterOption = {
|
||||||
id: number;
|
id: number;
|
||||||
@ -66,13 +64,6 @@ type Props = {
|
|||||||
per_page: number;
|
per_page: number;
|
||||||
total: number;
|
total: number;
|
||||||
};
|
};
|
||||||
summary: {
|
|
||||||
total_orders: number;
|
|
||||||
total_amount: number;
|
|
||||||
total_discount: number;
|
|
||||||
total_deduction: number;
|
|
||||||
net_total: number;
|
|
||||||
};
|
|
||||||
filters: {
|
filters: {
|
||||||
status?: string;
|
status?: string;
|
||||||
channel?: string;
|
channel?: string;
|
||||||
@ -557,8 +548,6 @@ export default function TransactionIndex({
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TransactionSummaryCard summary={summary} />
|
|
||||||
|
|
||||||
<CardTable
|
<CardTable
|
||||||
data={transactions.data}
|
data={transactions.data}
|
||||||
getItemKey={(t) => t.id}
|
getItemKey={(t) => t.id}
|
||||||
@ -588,7 +577,7 @@ export default function TransactionIndex({
|
|||||||
transaction={item}
|
transaction={item}
|
||||||
index={
|
index={
|
||||||
(pagination.current_page - 1) *
|
(pagination.current_page - 1) *
|
||||||
pagination.per_page +
|
pagination.per_page +
|
||||||
index +
|
index +
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,91 +0,0 @@
|
|||||||
import {
|
|
||||||
Banknote,
|
|
||||||
CircleDollarSign,
|
|
||||||
FileText,
|
|
||||||
Minus,
|
|
||||||
Percent,
|
|
||||||
TrendingUp,
|
|
||||||
} from 'lucide-react';
|
|
||||||
import { Card, CardContent } from '@/components/ui/card';
|
|
||||||
import { formatCurrency } from '@/lib/utils';
|
|
||||||
|
|
||||||
type Summary = {
|
|
||||||
total_orders: number;
|
|
||||||
total_amount: number;
|
|
||||||
total_discount: number;
|
|
||||||
total_deduction: number;
|
|
||||||
net_total: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
type TransactionSummaryCardProps = {
|
|
||||||
summary: Summary;
|
|
||||||
};
|
|
||||||
|
|
||||||
const summaryItems = [
|
|
||||||
{
|
|
||||||
key: 'total_orders',
|
|
||||||
label: 'Total Pesanan',
|
|
||||||
icon: FileText,
|
|
||||||
color: 'bg-blue-100',
|
|
||||||
iconColor: 'text-blue-600',
|
|
||||||
format: (value: number) => value.toLocaleString('id-ID'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'total_amount',
|
|
||||||
label: 'Total',
|
|
||||||
icon: Banknote,
|
|
||||||
color: 'bg-emerald-100',
|
|
||||||
iconColor: 'text-emerald-600',
|
|
||||||
format: formatCurrency,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'total_discount',
|
|
||||||
label: 'Diskon',
|
|
||||||
icon: Percent,
|
|
||||||
color: 'bg-amber-100',
|
|
||||||
iconColor: 'text-amber-600',
|
|
||||||
format: formatCurrency,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'total_deduction',
|
|
||||||
label: 'Potongan',
|
|
||||||
icon: Minus,
|
|
||||||
color: 'bg-orange-100',
|
|
||||||
iconColor: 'text-orange-600',
|
|
||||||
format: formatCurrency,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'net_total',
|
|
||||||
label: 'Total Bersih',
|
|
||||||
icon: TrendingUp,
|
|
||||||
color: 'bg-sky-100',
|
|
||||||
iconColor: 'text-sky-600',
|
|
||||||
format: formatCurrency,
|
|
||||||
},
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
export function TransactionSummaryCard({ summary }: TransactionSummaryCardProps) {
|
|
||||||
return (
|
|
||||||
<div className="grid grid-cols-1 gap-3 sm:grid-cols-3 lg:grid-cols-5">
|
|
||||||
{summaryItems.map((item) => (
|
|
||||||
<Card key={item.key}>
|
|
||||||
<CardContent className="flex items-center gap-3 py-3">
|
|
||||||
<div
|
|
||||||
className={`flex h-10 w-10 shrink-0 items-center justify-center rounded-lg ${item.color}`}
|
|
||||||
>
|
|
||||||
<item.icon className={`h-5 w-5 ${item.iconColor}`} />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="text-xs text-muted-foreground">
|
|
||||||
{item.label}
|
|
||||||
</p>
|
|
||||||
<p className="text-lg font-bold">
|
|
||||||
{item.format(summary[item.key] as number)}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user