update tgl 8 mei

This commit is contained in:
whywdd 2025-05-07 23:34:26 +07:00
parent 0be2b98301
commit 514596bce8
10 changed files with 933 additions and 312 deletions

View File

@ -173,17 +173,21 @@ public function index(Request $request)
} }
} }
// Get monthly totals for chart // Get daily totals for chart
$monthlyTotals = DB::table('laporan_transaksis') $monthlyTotals = DB::table('laporan_transaksis')
->select( ->select(
DB::raw('DATE_FORMAT(Tanggal, "%Y-%m") as periode'), DB::raw('DATE_FORMAT(Tanggal, "%Y-%m-%d") as periode'),
DB::raw('SUM(CASE WHEN LEFT(kategori, 3) IN ("241", "242") THEN uang_masuk ELSE 0 END) as total_debit'), DB::raw('SUM(uang_masuk) as total_debit'),
DB::raw('SUM(CASE WHEN LEFT(kategori, 3) IN ("251", "252") THEN uang_keluar ELSE 0 END) as total_kredit') DB::raw('SUM(uang_keluar) as total_kredit')
) )
->whereBetween('Tanggal', [$startDate, $endDate])
->groupBy('periode') ->groupBy('periode')
->orderBy('periode') ->orderBy('periode')
->get(); ->get();
// Debug untuk memastikan data terisi
Log::info('Daily Totals:', ['data' => $monthlyTotals->toArray()]);
// Get category totals for distribution chart // Get category totals for distribution chart
$categoryTotals = DB::table('laporan_transaksis') $categoryTotals = DB::table('laporan_transaksis')
->select( ->select(
@ -242,6 +246,63 @@ public function index(Request $request)
(($currentMonthLabaRugi - $lastMonthLabaRugi) / abs($lastMonthLabaRugi)) * 100 : (($currentMonthLabaRugi - $lastMonthLabaRugi) / abs($lastMonthLabaRugi)) * 100 :
100; 100;
// Ambil data neraca saldo untuk pie chart
$rawTransaksis = DB::table('laporan_transaksis')
->whereBetween('Tanggal', [$startDate, $endDate])
->orderBy('kode', 'asc')
->get();
$totalsPerAkun = [];
foreach ($rawTransaksis as $transaksi) {
$processAkun = function($kode, $kategori, $debit, $kredit) use (&$totalsPerAkun) {
if (!empty($kode) && !empty($kategori)) {
if (!isset($totalsPerAkun[$kategori])) {
$totalsPerAkun[$kategori] = [
'kode' => $kode,
'kategori' => $kategori,
'debit' => 0,
'kredit' => 0
];
}
$totalsPerAkun[$kategori]['debit'] += floatval($debit ?? 0);
$totalsPerAkun[$kategori]['kredit'] += floatval($kredit ?? 0);
}
};
$processAkun($transaksi->kode, $transaksi->kategori, $transaksi->uang_masuk, $transaksi->uang_keluar);
$processAkun($transaksi->kode2, $transaksi->kategori2, $transaksi->uang_masuk2, $transaksi->uang_keluar2);
$processAkun($transaksi->kode3, $transaksi->kategori3, $transaksi->uang_masuk3, $transaksi->uang_keluar3);
$processAkun($transaksi->kode4, $transaksi->kategori4, $transaksi->uang_masuk4, $transaksi->uang_keluar4);
$processAkun($transaksi->kode5, $transaksi->kategori5, $transaksi->uang_masuk5, $transaksi->uang_keluar5);
}
$finalTransaksis = [];
foreach ($totalsPerAkun as $kategori => $data) {
$kodeAwal = substr($data['kode'], 0, 3);
$saldo = $data['debit'] - $data['kredit'];
if (in_array($kodeAwal, ['111', '112']) || in_array($kodeAwal, ['251', '252'])) {
if ($saldo != 0) {
$finalTransaksis[] = [
'kode' => $data['kode'],
'kategori' => $kategori,
'debit' => $saldo,
'kredit' => 0
];
}
} else {
if ($saldo != 0) {
$finalTransaksis[] = [
'kode' => $data['kode'],
'kategori' => $kategori,
'debit' => 0,
'kredit' => -$saldo
];
}
}
}
$neracaTransaksis = collect($finalTransaksis);
$pieLabels = $neracaTransaksis->pluck('kategori')->toArray();
$pieData = $neracaTransaksis->map(function($item) {
return abs($item['debit']) + abs($item['kredit']);
})->toArray();
return view('home', compact( return view('home', compact(
'startDate', 'startDate',
'endDate', 'endDate',
@ -254,7 +315,9 @@ public function index(Request $request)
'categoryTotals', 'categoryTotals',
'recentTransactions', 'recentTransactions',
'pendapatan', 'pendapatan',
'beban' 'beban',
'pieLabels',
'pieData'
)); ));
} catch (\Exception $e) { } catch (\Exception $e) {

View File

@ -134,4 +134,202 @@ public function filter(Request $request)
{ {
return $this->index($request); return $this->index($request);
} }
public function exportExcel(Request $request)
{
try {
$startDate = $request->input('start_date', Carbon::now()->startOfMonth()->format('Y-m-d'));
$endDate = $request->input('end_date', Carbon::now()->endOfMonth()->format('Y-m-d'));
// Inisialisasi array untuk menyimpan data
$pendapatan = [];
$beban = [];
// Ambil semua transaksi dalam periode
$transaksis = DB::table('laporan_transaksis')
->whereBetween('Tanggal', [$startDate, $endDate])
->get();
foreach ($transaksis as $transaksi) {
// Proses kategori1
if (!empty($transaksi->kategori)) {
$this->prosesKategori(
$transaksi->kategori,
$transaksi->uang_masuk ?? 0,
$transaksi->uang_keluar ?? 0,
$pendapatan,
$beban
);
}
// Proses kategori2-5
for ($i = 2; $i <= 5; $i++) {
$kategori = $transaksi->{"kategori$i"};
if (!empty($kategori)) {
$this->prosesKategori(
$kategori,
$transaksi->{"uang_masuk$i"} ?? 0,
$transaksi->{"uang_keluar$i"} ?? 0,
$pendapatan,
$beban
);
}
}
}
// Hitung total
$total_pendapatan = array_sum(array_column($pendapatan, 'nominal'));
$total_beban = abs(array_sum(array_column($beban, 'nominal')));
$laba_rugi = $total_pendapatan - $total_beban;
// Siapkan data untuk Excel
$rows = [];
// Header
$rows[] = ['Laporan Laba Rugi'];
$rows[] = ['Periode: ' . date('F Y', strtotime($startDate))];
$rows[] = []; // Baris kosong
// Pendapatan
$rows[] = ['Pendapatan'];
foreach ($pendapatan as $item) {
$rows[] = [
ucwords($item['kategori']),
number_format(abs($item['nominal']), 0, ',', '.')
];
}
$rows[] = ['Total Pendapatan', number_format(abs($total_pendapatan), 0, ',', '.')];
$rows[] = []; // Baris kosong
// Beban
$rows[] = ['Beban'];
foreach ($beban as $item) {
$rows[] = [
ucwords($item['kategori']),
number_format(abs($item['nominal']), 0, ',', '.')
];
}
$rows[] = ['Total Beban', number_format($total_beban, 0, ',', '.')];
$rows[] = []; // Baris kosong
// Laba/Rugi
$rows[] = ['Laba/Rugi Bersih', number_format($laba_rugi, 0, ',', '.')];
$export = new class($rows) implements \Maatwebsite\Excel\Concerns\FromArray {
protected $rows;
public function __construct($rows) { $this->rows = $rows; }
public function array(): array { return $this->rows; }
};
return \Maatwebsite\Excel\Facades\Excel::download($export, 'laporan-laba-rugi-'.date('Y-m-d').'.xlsx');
} catch (\Exception $e) {
return redirect()->back()->with('error', 'Gagal mengekspor Excel: ' . $e->getMessage());
}
}
public function exportPDF(Request $request)
{
try {
$startDate = $request->input('start_date', Carbon::now()->startOfMonth()->format('Y-m-d'));
$endDate = $request->input('end_date', Carbon::now()->endOfMonth()->format('Y-m-d'));
// Inisialisasi array untuk menyimpan data
$pendapatan = [];
$beban = [];
// Ambil semua transaksi dalam periode
$transaksis = DB::table('laporan_transaksis')
->whereBetween('Tanggal', [$startDate, $endDate])
->get();
foreach ($transaksis as $transaksi) {
// Proses kategori1
if (!empty($transaksi->kategori)) {
$this->prosesKategori(
$transaksi->kategori,
$transaksi->uang_masuk ?? 0,
$transaksi->uang_keluar ?? 0,
$pendapatan,
$beban
);
}
// Proses kategori2-5
for ($i = 2; $i <= 5; $i++) {
$kategori = $transaksi->{"kategori$i"};
if (!empty($kategori)) {
$this->prosesKategori(
$kategori,
$transaksi->{"uang_masuk$i"} ?? 0,
$transaksi->{"uang_keluar$i"} ?? 0,
$pendapatan,
$beban
);
}
}
}
// Hitung total
$total_pendapatan = array_sum(array_column($pendapatan, 'nominal'));
$total_beban = abs(array_sum(array_column($beban, 'nominal')));
$laba_rugi = $total_pendapatan - $total_beban;
$html = '<!DOCTYPE html><html><head><title>Laporan Laba Rugi</title><style>
body{font-family:Arial,sans-serif;font-size:12px;}
table{width:100%;border-collapse:collapse;margin-bottom:20px;}
table,th,td{border:1px solid #ddd;}
th,td{padding:8px;text-align:left;}
th{background-color:#6b46c1;color:white;}
.bg-gray-100{background-color:#f3f4f6;}
.bg-purple-100{background-color:#f3e8ff;}
.text-right{text-align:right;}
.font-bold{font-weight:bold;}
.pl-8{padding-left:2rem;}
</style></head><body>';
$html .= '<h2 style="text-align:center">Laporan Laba Rugi</h2>';
$html .= '<p style="text-align:center">Periode: ' . date('F Y', strtotime($startDate)) . '</p>';
$html .= '<table>';
// Header
$html .= '<tr><th>Keterangan</th><th style="text-align:right">Nominal</th></tr>';
// Pendapatan
$html .= '<tr class="bg-gray-100"><td colspan="2" class="font-bold">Pendapatan</td></tr>';
foreach ($pendapatan as $item) {
$html .= '<tr>';
$html .= '<td class="pl-8">' . ucwords($item['kategori']) . '</td>';
$html .= '<td class="text-right">' . number_format(abs($item['nominal']), 0, ',', '.') . '</td>';
$html .= '</tr>';
}
$html .= '<tr class="font-bold"><td>Total Pendapatan</td><td class="text-right">' . number_format(abs($total_pendapatan), 0, ',', '.') . '</td></tr>';
// Beban
$html .= '<tr class="bg-gray-100"><td colspan="2" class="font-bold">Beban</td></tr>';
foreach ($beban as $item) {
$html .= '<tr>';
$html .= '<td class="pl-8">' . ucwords($item['kategori']) . '</td>';
$html .= '<td class="text-right">' . number_format(abs($item['nominal']), 0, ',', '.') . '</td>';
$html .= '</tr>';
}
$html .= '<tr class="font-bold"><td>Total Beban</td><td class="text-right">' . number_format($total_beban, 0, ',', '.') . '</td></tr>';
// Laba/Rugi
$html .= '<tr class="bg-purple-100"><td class="font-bold">Laba/Rugi Bersih</td><td class="text-right font-bold">';
if ($laba_rugi < 0) {
$html .= '-Rp ' . number_format(abs($laba_rugi), 0, ',', '.');
} else {
$html .= 'Rp ' . number_format($laba_rugi, 0, ',', '.');
}
$html .= '</td></tr>';
$html .= '</table></body></html>';
$pdf = \Barryvdh\DomPDF\Facade\Pdf::loadHTML($html);
return $pdf->download('laporan-laba-rugi-'.date('Y-m-d').'.pdf');
} catch (\Exception $e) {
return redirect()->back()->with('error', 'Gagal mengekspor PDF: ' . $e->getMessage());
}
}
} }

View File

@ -52,54 +52,117 @@ public function filter(Request $request)
return $this->index($request); return $this->index($request);
} }
public function exportExcel() public function exportExcel(Request $request)
{ {
try { try {
// Buat class export inline $startDate = $request->input('start_date', Carbon::now()->startOfMonth()->format('Y-m-d'));
$export = new class implements FromCollection, WithHeadings, WithMapping { $endDate = $request->input('end_date', Carbon::now()->endOfMonth()->format('Y-m-d'));
public function collection() $laporan = LaporanModel::whereBetween('Tanggal', [$startDate, $endDate])
{ ->orderBy('Tanggal', 'desc')
return LaporanModel::orderBy('Tanggal', 'desc')->get(); ->get();
$rows = [];
$no = 1;
$totalDebit = 0;
$totalKredit = 0;
foreach ($laporan as $item) {
// Cek apakah semua nilai adalah debit
$allDebit = true;
$debitValues = [
$item->uang_masuk,
$item->uang_masuk2,
$item->uang_masuk3,
$item->uang_masuk4,
$item->uang_masuk5
];
$validDebitValues = array_filter($debitValues, function($value) {
return $value !== null && $value > 0;
});
if ($item->uang_keluar > 0 ||
($item->uang_keluar2 ?? 0) > 0 ||
($item->uang_keluar3 ?? 0) > 0 ||
($item->uang_keluar4 ?? 0) > 0 ||
($item->uang_keluar5 ?? 0) > 0) {
$allDebit = false;
} }
public function headings(): array // Proses data untuk setiap baris
{ $rowDebit = 0;
return [ $rowKredit = 0;
'ID',
'Tanggal', if ($allDebit) {
'Kode', $lastDebitValue = end($validDebitValues);
'Kategori', $firstDebitValue = reset($validDebitValues);
'Keterangan',
'Uang Masuk', if (count($validDebitValues) > 1) {
'Uang Keluar' $rowDebit = $firstDebitValue;
]; $rowKredit = $lastDebitValue;
} else {
$rowDebit = $firstDebitValue;
$rowKredit = $firstDebitValue;
}
} else {
$rowDebit = $item->uang_masuk +
($item->uang_masuk2 ?? 0) +
($item->uang_masuk3 ?? 0) +
($item->uang_masuk4 ?? 0) +
($item->uang_masuk5 ?? 0);
$rowKredit = $item->uang_keluar +
($item->uang_keluar2 ?? 0) +
($item->uang_keluar3 ?? 0) +
($item->uang_keluar4 ?? 0) +
($item->uang_keluar5 ?? 0);
} }
public function map($laporan): array $totalDebit += $rowDebit;
{ $totalKredit += $rowKredit;
// Hitung total uang masuk untuk baris ini
$totalUangMasuk = $laporan->uang_masuk +
($laporan->uang_masuk2 ?? 0) +
($laporan->uang_masuk3 ?? 0) +
($laporan->uang_masuk4 ?? 0) +
($laporan->uang_masuk5 ?? 0);
// Hitung total uang keluar untuk baris ini // Gabungkan semua kode akun
$totalUangKeluar = $laporan->uang_keluar + $kodeAkun = $item->kode;
($laporan->uang_keluar2 ?? 0) + if (!empty($item->kode2)) $kodeAkun .= "\n" . $item->kode2;
($laporan->uang_keluar3 ?? 0) + if (!empty($item->kode3)) $kodeAkun .= "\n" . $item->kode3;
($laporan->uang_keluar4 ?? 0) + if (!empty($item->kode4)) $kodeAkun .= "\n" . $item->kode4;
($laporan->uang_keluar5 ?? 0); if (!empty($item->kode5)) $kodeAkun .= "\n" . $item->kode5;
return [ // Gabungkan semua nama akun
$laporan->id, $namaAkun = $item->kategori;
$laporan->Tanggal, if (!empty($item->kategori2)) $namaAkun .= "\n" . $item->kategori2;
$laporan->kode, if (!empty($item->kategori3)) $namaAkun .= "\n" . $item->kategori3;
$laporan->kategori, if (!empty($item->kategori4)) $namaAkun .= "\n" . $item->kategori4;
$laporan->keterangan, if (!empty($item->kategori5)) $namaAkun .= "\n" . $item->kategori5;
$totalUangMasuk,
$totalUangKeluar $rows[] = [
]; 'No' => $no++,
'Tanggal' => date('d/m/Y', strtotime($item->Tanggal)),
'Kode Akun' => $kodeAkun,
'Nama Akun' => $namaAkun,
'Keterangan' => $item->keterangan . ' ' . $item->nama_karyawan,
'Debit' => $rowDebit > 0 ? number_format($rowDebit, 0, ',', '.') : '-',
'Kredit' => $rowKredit > 0 ? number_format($rowKredit, 0, ',', '.') : '-'
];
}
// Tambahkan baris total
$rows[] = [
'No' => '',
'Tanggal' => '',
'Kode Akun' => '',
'Nama Akun' => '',
'Keterangan' => 'Total',
'Debit' => number_format($totalDebit, 0, ',', '.'),
'Kredit' => number_format($totalKredit, 0, ',', '.')
];
$export = new class($rows) implements FromCollection, WithHeadings {
protected $rows;
public function __construct($rows) { $this->rows = $rows; }
public function collection() { return collect($this->rows); }
public function headings(): array {
return ['No', 'Tanggal', 'Kode Akun', 'Nama Akun', 'Keterangan', 'Debit', 'Kredit'];
} }
}; };
@ -109,131 +172,131 @@ public function map($laporan): array
} }
} }
public function exportPDF() public function exportPDF(Request $request)
{ {
try { try {
$laporan = LaporanModel::orderBy('Tanggal', 'desc')->get(); $startDate = $request->input('start_date', Carbon::now()->startOfMonth()->format('Y-m-d'));
$endDate = $request->input('end_date', Carbon::now()->endOfMonth()->format('Y-m-d'));
$laporan = LaporanModel::whereBetween('Tanggal', [$startDate, $endDate])
->orderBy('Tanggal', 'desc')
->get();
// Hitung total uang masuk $rows = '';
$totalUangMasuk = LaporanModel::selectRaw('SUM(uang_masuk) + $no = 1;
COALESCE(SUM(uang_masuk2), 0) + $totalDebit = 0;
COALESCE(SUM(uang_masuk3), 0) + $totalKredit = 0;
COALESCE(SUM(uang_masuk4), 0) +
COALESCE(SUM(uang_masuk5), 0) as total')
->value('total') ?? 0;
// Hitung total uang keluar foreach ($laporan as $item) {
$totalKredit = LaporanModel::selectRaw('SUM(uang_keluar) + // Cek apakah semua nilai adalah debit
COALESCE(SUM(uang_keluar2), 0) + $allDebit = true;
COALESCE(SUM(uang_keluar3), 0) + $debitValues = [
COALESCE(SUM(uang_keluar4), 0) + $item->uang_masuk,
COALESCE(SUM(uang_keluar5), 0) as total') $item->uang_masuk2,
->value('total') ?? 0; $item->uang_masuk3,
$item->uang_masuk4,
$item->uang_masuk5
];
$saldo = $totalUangMasuk - $totalKredit; $validDebitValues = array_filter($debitValues, function($value) {
return $value !== null && $value > 0;
});
// Generate PDF if ($item->uang_keluar > 0 ||
$html = ' ($item->uang_keluar2 ?? 0) > 0 ||
<!DOCTYPE html> ($item->uang_keluar3 ?? 0) > 0 ||
<html> ($item->uang_keluar4 ?? 0) > 0 ||
<head> ($item->uang_keluar5 ?? 0) > 0) {
<title>Laporan Keuangan</title> $allDebit = false;
<style> }
body {
font-family: Arial, sans-serif; // Proses data untuk setiap baris
font-size: 12px; $rowDebit = 0;
$rowKredit = 0;
if ($allDebit) {
$lastDebitValue = end($validDebitValues);
$firstDebitValue = reset($validDebitValues);
if (count($validDebitValues) > 1) {
$rowDebit = $firstDebitValue;
$rowKredit = $lastDebitValue;
} else {
$rowDebit = $firstDebitValue;
$rowKredit = $firstDebitValue;
} }
table { } else {
width: 100%; $rowDebit = $item->uang_masuk +
border-collapse: collapse; ($item->uang_masuk2 ?? 0) +
margin-bottom: 20px; ($item->uang_masuk3 ?? 0) +
} ($item->uang_masuk4 ?? 0) +
table, th, td { ($item->uang_masuk5 ?? 0);
border: 1px solid #ddd;
}
th, td {
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
.summary {
margin-top: 20px;
}
.summary table {
width: 300px;
}
</style>
</head>
<body>
<h2>Laporan Keuangan</h2>
<p>Tanggal: '.date('d-m-Y').'</p>
<table> $rowKredit = $item->uang_keluar +
<thead> ($item->uang_keluar2 ?? 0) +
<tr> ($item->uang_keluar3 ?? 0) +
<th>No</th> ($item->uang_keluar4 ?? 0) +
<th>Tanggal</th> ($item->uang_keluar5 ?? 0);
<th>Kode</th> }
<th>Kategori</th>
<th>Keterangan</th>
<th>Uang Masuk</th>
<th>Uang Keluar</th>
</tr>
</thead>
<tbody>';
foreach($laporan as $index => $item) { $totalDebit += $rowDebit;
// Hitung total uang masuk untuk baris ini $totalKredit += $rowKredit;
$rowUangMasuk = $item->uang_masuk +
($item->uang_masuk2 ?? 0) +
($item->uang_masuk3 ?? 0) +
($item->uang_masuk4 ?? 0) +
($item->uang_masuk5 ?? 0);
// Hitung total uang keluar untuk baris ini // Gabungkan semua kode akun
$rowUangKeluar = $item->uang_keluar + $kodeAkun = $item->kode;
($item->uang_keluar2 ?? 0) + if (!empty($item->kode2)) $kodeAkun .= "<br>" . $item->kode2;
($item->uang_keluar3 ?? 0) + if (!empty($item->kode3)) $kodeAkun .= "<br>" . $item->kode3;
($item->uang_keluar4 ?? 0) + if (!empty($item->kode4)) $kodeAkun .= "<br>" . $item->kode4;
($item->uang_keluar5 ?? 0); if (!empty($item->kode5)) $kodeAkun .= "<br>" . $item->kode5;
$html .= ' // Gabungkan semua nama akun
<tr> $namaAkun = $item->kategori;
<td>'.($index + 1).'</td> if (!empty($item->kategori2)) $namaAkun .= "<br>" . $item->kategori2;
<td>'.$item->Tanggal.'</td> if (!empty($item->kategori3)) $namaAkun .= "<br>" . $item->kategori3;
<td>'.$item->kode.'</td> if (!empty($item->kategori4)) $namaAkun .= "<br>" . $item->kategori4;
<td>'.$item->kategori.'</td> if (!empty($item->kategori5)) $namaAkun .= "<br>" . $item->kategori5;
<td>'.$item->keterangan.'</td>
<td>Rp '.number_format($rowUangMasuk, 0, ',', '.').'</td>
<td>Rp '.number_format($rowUangKeluar, 0, ',', '.').'</td>
</tr>';
}
$html .= ' $rows .= '<tr>';
</tbody> $rows .= '<td style="text-align:center">'.$no++.'</td>';
</table> $rows .= '<td>'.date('d/m/Y', strtotime($item->Tanggal)).'</td>';
$rows .= '<td>'.$kodeAkun.'</td>';
$rows .= '<td>'.$namaAkun.'</td>';
$rows .= '<td>'.$item->keterangan.' '.$item->nama_karyawan.'</td>';
$rows .= '<td style="text-align:right">'.($rowDebit > 0 ? number_format($rowDebit, 0, ',', '.') : '-').'</td>';
$rows .= '<td style="text-align:right">'.($rowKredit > 0 ? number_format($rowKredit, 0, ',', '.') : '-').'</td>';
$rows .= '</tr>';
}
<div class="summary"> // Tambahkan baris total
<h3>Ringkasan</h3> $rows .= '<tr style="font-weight:bold;background-color:#f9f9f9;">';
<table> $rows .= '<td colspan="5" style="text-align:right">Total</td>';
<tr> $rows .= '<td style="text-align:right">'.number_format($totalDebit, 0, ',', '.').'</td>';
<td><strong>Total Uang Masuk</strong></td> $rows .= '<td style="text-align:right">'.number_format($totalKredit, 0, ',', '.').'</td>';
<td>Rp '.number_format($totalUangMasuk, 0, ',', '.').'</td> $rows .= '</tr>';
</tr>
<tr> $html = '<!DOCTYPE html><html><head><title>Laporan Keuangan</title><style>
<td><strong>Total Uang Keluar</strong></td> body{font-family:Arial,sans-serif;font-size:12px;}
<td>Rp '.number_format($totalKredit, 0, ',', '.').'</td> table{width:100%;border-collapse:collapse;margin-bottom:20px;}
</tr> table,th,td{border:1px solid #ddd;}
<tr> th,td{padding:8px;text-align:left;}
<td><strong>Saldo</strong></td> th{background-color:#f2f2f2;}
<td>Rp '.number_format($saldo, 0, ',', '.').'</td> tfoot td{font-weight:bold;background-color:#f9f9f9;}
</tr> .text-right{text-align:right;}
</table> .text-center{text-align:center;}
</div> td{vertical-align:top;}
</body> </style></head><body>';
</html>'; $html .= '<h2 style="text-align:center">Laporan Keuangan</h2>';
$html .= '<p style="text-align:center">Periode: '.date('d/m/Y', strtotime($startDate)).' - '.date('d/m/Y', strtotime($endDate)).'</p>';
$html .= '<table><thead><tr>
<th style="text-align:center">No</th>
<th>Tanggal</th>
<th>Kode Akun</th>
<th>Nama Akun</th>
<th>Keterangan</th>
<th style="text-align:right">Debit</th>
<th style="text-align:right">Kredit</th>
</tr></thead><tbody>';
$html .= $rows;
$html .= '</tbody></table></body></html>';
$pdf = PDF::loadHTML($html); $pdf = PDF::loadHTML($html);
return $pdf->download('laporan-keuangan-'.date('Y-m-d').'.pdf'); return $pdf->download('laporan-keuangan-'.date('Y-m-d').'.pdf');

View File

@ -62,10 +62,9 @@ public function store(Request $request)
]); ]);
if ($validator->fails()) { if ($validator->fails()) {
return response()->json([ return redirect()->back()
'success' => false, ->with('error', $validator->errors()->first())
'message' => $validator->errors()->first() ->withInput();
], 422);
} }
try { try {
@ -76,22 +75,24 @@ public function store(Request $request)
'tipe_pengguna' => $request->tipe_pengguna 'tipe_pengguna' => $request->tipe_pengguna
]); ]);
return response()->json([ return redirect()->route('User.index')
'success' => true, ->with('success', 'User berhasil ditambahkan!');
'message' => 'User berhasil ditambahkan'
]);
} catch (\Exception $e) { } catch (\Exception $e) {
return response()->json([ return redirect()->back()
'success' => false, ->with('error', 'Gagal menambahkan user: ' . $e->getMessage())
'message' => 'Gagal menambahkan user: ' . $e->getMessage() ->withInput();
], 500);
} }
} }
public function edit($id) public function edit($id)
{ {
$user = User::findOrFail($id); try {
return view('EditAkun', compact('user')); $user = User::findOrFail($id);
return view('EditAkun', compact('user'));
} catch (\Exception $e) {
return redirect()->route('User.index')
->with('error', 'User tidak ditemukan');
}
} }
public function update(Request $request, $id) public function update(Request $request, $id)
@ -104,10 +105,9 @@ public function update(Request $request, $id)
]); ]);
if ($validator->fails()) { if ($validator->fails()) {
return response()->json([ return redirect()->back()
'success' => false, ->with('error', $validator->errors()->first())
'message' => $validator->errors()->first() ->withInput();
], 422);
} }
try { try {
@ -125,15 +125,12 @@ public function update(Request $request, $id)
$user->update($data); $user->update($data);
return response()->json([ return redirect()->route('User.index')
'success' => true, ->with('success', 'Data user berhasil diperbarui!');
'message' => 'User berhasil diperbarui'
]);
} catch (\Exception $e) { } catch (\Exception $e) {
return response()->json([ return redirect()->back()
'success' => false, ->with('error', 'Gagal memperbarui user: ' . $e->getMessage())
'message' => 'Gagal memperbarui user: ' . $e->getMessage() ->withInput();
], 500);
} }
} }
@ -145,7 +142,7 @@ public function destroy($id)
return response()->json([ return response()->json([
'success' => true, 'success' => true,
'message' => 'User berhasil dihapus' 'message' => 'User berhasil dihapus!'
]); ]);
} catch (\Exception $e) { } catch (\Exception $e) {
return response()->json([ return response()->json([

View File

@ -1,6 +1,10 @@
@extends('Core.Sidebar') @extends('Core.Sidebar')
@section('content') @section('content')
<!-- Chart.js -->
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.9.1/dist/chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.2.0"></script>
<style> <style>
.chart-container { .chart-container {
position: relative; position: relative;
@ -192,18 +196,128 @@
<!-- Charts Section --> <!-- Charts Section -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6"> <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
<!-- Bar Chart --> <!-- Bar Chart -->
<div class="bg-white p-6 rounded-xl shadow-sm"> <div class="max-w-sm w-full bg-white rounded-lg shadow-sm dark:bg-gray-800 p-4 md:p-6">
<h4 class="text-lg font-semibold text-gray-700 mb-4">Tren Pendapatan & Beban</h4> <div class="flex justify-between">
<div>
<h5 class="leading-none text-3xl font-bold text-gray-900 dark:text-white pb-2">
@if($labaRugiTotal < 0)
-Rp {{ number_format(abs($labaRugiTotal), 0, ',', '.') }}
@else
Rp {{ number_format($labaRugiTotal, 0, ',', '.') }}
@endif
</h5>
<p class="text-base font-normal text-gray-500 dark:text-gray-400">Laba/Rugi Total</p>
</div>
<div class="flex items-center px-2.5 py-0.5 text-base font-semibold {{ $growthPercentage >= 0 ? 'text-green-500' : 'text-red-500' }} dark:text-green-500 text-center">
{{ number_format($growthPercentage, 1) }}%
<svg class="w-3 h-3 ms-1" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 14">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13V1m0 0L1 5m4-4 4 4"/>
</svg>
</div>
</div>
<div class="chart-container"> <div class="chart-container">
<canvas id="financial-trend-chart"></canvas> <canvas id="financial-trend-chart"></canvas>
</div> </div>
<div class="grid grid-cols-1 items-center border-gray-200 border-t dark:border-gray-700 justify-between">
<div class="flex justify-between items-center pt-5">
<!-- Button -->
<button
id="dropdownDefaultButton"
data-dropdown-toggle="lastDaysdropdown"
data-dropdown-placement="bottom"
class="text-sm font-medium text-gray-500 dark:text-gray-400 hover:text-gray-900 text-center inline-flex items-center dark:hover:text-white"
type="button">
{{ date('d/m/Y', strtotime($startDate)) }} - {{ date('d/m/Y', strtotime($endDate)) }}
<svg class="w-2.5 m-2.5 ms-1.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 4 4 4-4"/>
</svg>
</button>
<!-- Dropdown menu -->
<div id="lastDaysdropdown" class="z-10 hidden bg-white divide-y divide-gray-100 rounded-lg shadow-sm w-44 dark:bg-gray-700">
<ul class="py-2 text-sm text-gray-700 dark:text-gray-200" aria-labelledby="dropdownDefaultButton">
<li>
<a href="{{ route('home.filter', ['start_date' => Carbon\Carbon::yesterday()->format('Y-m-d'), 'end_date' => Carbon\Carbon::yesterday()->format('Y-m-d')]) }}" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Kemarin</a>
</li>
<li>
<a href="{{ route('home.filter', ['start_date' => Carbon\Carbon::today()->format('Y-m-d'), 'end_date' => Carbon\Carbon::today()->format('Y-m-d')]) }}" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Hari Ini</a>
</li>
<li>
<a href="{{ route('home.filter', ['start_date' => Carbon\Carbon::now()->subDays(7)->format('Y-m-d'), 'end_date' => Carbon\Carbon::now()->format('Y-m-d')]) }}" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">7 Hari Terakhir</a>
</li>
<li>
<a href="{{ route('home.filter', ['start_date' => Carbon\Carbon::now()->subDays(30)->format('Y-m-d'), 'end_date' => Carbon\Carbon::now()->format('Y-m-d')]) }}" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">30 Hari Terakhir</a>
</li>
<li>
<a href="{{ route('home.filter', ['start_date' => Carbon\Carbon::now()->subDays(90)->format('Y-m-d'), 'end_date' => Carbon\Carbon::now()->format('Y-m-d')]) }}" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">90 Hari Terakhir</a>
</li>
</ul>
</div>
<div class="flex items-center space-x-2">
<button onclick="updateChartType('line')" class="text-sm font-medium text-gray-500 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white px-3 py-1 rounded-lg bg-gray-100 dark:bg-gray-700">Garis</button>
<button onclick="updateChartType('bar')" class="text-sm font-medium text-gray-500 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white px-3 py-1 rounded-lg">Bar</button>
</div>
</div>
</div>
</div> </div>
<!-- Category Chart --> <!-- Category Chart -->
<div class="bg-white p-6 rounded-xl shadow-sm"> <div class="max-w-sm w-full bg-white rounded-lg shadow-sm dark:bg-gray-800 p-4 md:p-6">
<h4 class="text-lg font-semibold text-gray-700 mb-4">Distribusi per Kategori</h4> <div class="flex flex-col w-full">
<div class="chart-container"> <div class="flex items-center justify-between mb-2">
<canvas id="category-distribution-chart"></canvas> <div class="flex items-center">
<h5 class="text-xl font-bold leading-none text-gray-900 dark:text-white">Distribusi Neraca Saldo</h5>
<svg data-popover-target="chart-info" data-popover-placement="bottom" class="w-3.5 h-3.5 text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white cursor-pointer ms-2" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
<path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5Zm0 16a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3Zm1-5.034V12a1 1 0 0 1-2 0v-1.418a1 1 0 0 1 1.038-.999 1.436 1.436 0 0 0 1.488-1.441 1.501 1.501 0 1 0-3-.116.986.986 0 0 1-1.037.961 1 1 0 0 1-.96-1.037A3.5 3.5 0 1 1 11 11.466Z"/>
</svg>
</div>
<button id="dateRangeButton" data-dropdown-toggle="dateRangeDropdown" data-dropdown-ignore-click-outside-class="datepicker" type="button" class="inline-flex items-center text-blue-700 dark:text-blue-600 font-medium hover:underline">
{{ date('d M', strtotime($startDate)) }} - {{ date('d M', strtotime($endDate)) }}
<svg class="w-3 h-3 ms-2" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 4 4 4-4"/>
</svg>
</button>
</div>
<div class="flex flex-col items-center justify-center py-4">
<div class="chart-container" style="height: 260px; width: 260px;">
<canvas id="category-distribution-chart"></canvas>
</div>
</div>
<div class="flex flex-wrap justify-center gap-4 mt-4">
@php
$pieColors = ['#FF5733','#33FF57','#3357FF','#FF33A1','#FFBD33','#10b981','#f472b6','#6366f1','#f59e42','#e11d48'];
@endphp
@foreach($pieLabels as $i => $label)
<div class="flex items-center space-x-2">
<span class="w-3 h-3 rounded-full" style="background: {{ $pieColors[$i % count($pieColors)] }}"></span>
<span class="text-sm">{{ $label }}</span>
</div>
@endforeach
</div>
<div class="flex justify-between items-center border-t border-gray-200 dark:border-gray-700 mt-6 pt-4">
<div class="flex items-center">
<button id="dropdownDefaultButton" data-dropdown-toggle="lastDaysdropdown" data-dropdown-placement="bottom" class="text-sm font-medium text-gray-500 dark:text-gray-400 hover:text-gray-900 text-center inline-flex items-center dark:hover:text-white" type="button">
Last 7 days
<svg class="w-2.5 m-2.5 ms-1.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 4 4 4-4"/>
</svg>
</button>
<div id="lastDaysdropdown" class="z-10 hidden bg-white divide-y divide-gray-100 rounded-lg shadow-sm w-44 dark:bg-gray-700">
<ul class="py-2 text-sm text-gray-700 dark:text-gray-200" aria-labelledby="dropdownDefaultButton">
<li><a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Kemarin</a></li>
<li><a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Hari Ini</a></li>
<li><a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">7 Hari Terakhir</a></li>
<li><a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">30 Hari Terakhir</a></li>
<li><a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">90 Hari Terakhir</a></li>
</ul>
</div>
</div>
<a href="#" class="uppercase text-sm font-semibold inline-flex items-center rounded-lg text-blue-600 hover:text-blue-700 dark:hover:text-blue-500 hover:bg-gray-100 dark:hover:bg-gray-700 dark:focus:ring-gray-700 dark:border-gray-700 px-3 py-2">
LAPORAN KATEGORI
<svg class="w-2.5 h-2.5 ms-1.5 rtl:rotate-180" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 6 10">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 9 4-4-4-4"/>
</svg>
</a>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -254,11 +368,13 @@
</div> </div>
</div> </div>
@push('scripts')
<!-- Chart.js -->
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.9.1/dist/chart.min.js"></script>
<script> <script>
// Debugging untuk memastikan script berjalan
console.log('Script started');
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
console.log('DOM Content Loaded');
// Format number to Rupiah // Format number to Rupiah
function formatRupiah(number) { function formatRupiah(number) {
return 'Rp ' + number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, "."); return 'Rp ' + number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
@ -270,39 +386,36 @@ function formatRupiah(number) {
if (trendCtx) { if (trendCtx) {
const monthlyData = @json($monthlyTotals); const monthlyData = @json($monthlyTotals);
const labels = monthlyData.map(item => { const labels = monthlyData.map(item => {
const [year, month] = item.periode.split('-'); const date = new Date(item.periode);
const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Ags', 'Sep', 'Okt', 'Nov', 'Des']; return date.toLocaleDateString('id-ID', { day: 'numeric', month: 'short' });
return `${monthNames[parseInt(month)-1]} ${year}`;
}); });
const pendapatanData = monthlyData.map(item => parseFloat(item.total_debit) || 0); const pendapatanData = monthlyData.map(item => parseFloat(item.total_debit) || 0);
const bebanData = monthlyData.map(item => parseFloat(item.total_kredit) || 0); const bebanData = monthlyData.map(item => parseFloat(item.total_kredit) || 0);
new Chart(trendCtx, { // Create gradient for area fill
type: 'bar', const gradientFill = trendCtx.getContext('2d').createLinearGradient(0, 0, 0, 400);
gradientFill.addColorStop(0, 'rgba(34, 197, 94, 0.2)');
gradientFill.addColorStop(1, 'rgba(34, 197, 94, 0)');
window.trendChart = new Chart(trendCtx, {
type: 'line',
data: { data: {
labels: labels, labels: labels,
datasets: [{ datasets: [{
label: 'Pendapatan', label: 'Pendapatan',
data: pendapatanData, data: pendapatanData,
backgroundColor: 'rgba(34, 197, 94, 0.5)',
borderColor: 'rgb(34, 197, 94)', borderColor: 'rgb(34, 197, 94)',
borderWidth: 1, backgroundColor: gradientFill,
order: 2 fill: true,
}, { tension: 0.4,
label: 'Beban',
data: bebanData,
backgroundColor: 'rgba(239, 68, 68, 0.5)',
borderColor: 'rgb(239, 68, 68)',
borderWidth: 1,
order: 2
}, {
label: 'Laba/Rugi',
data: pendapatanData.map((pendapatan, index) => pendapatan - bebanData[index]),
type: 'line',
borderColor: 'rgb(59, 130, 246)',
borderWidth: 2, borderWidth: 2,
fill: false, pointRadius: 0,
order: 1 pointHoverRadius: 5,
pointHoverBackgroundColor: 'rgb(34, 197, 94)',
pointHoverBorderColor: '#fff',
pointHoverBorderWidth: 2,
cubicInterpolationMode: 'monotone',
stepped: false
}] }]
}, },
options: { options: {
@ -312,89 +425,127 @@ function formatRupiah(number) {
intersect: false, intersect: false,
mode: 'index' mode: 'index'
}, },
scales: {
y: {
beginAtZero: true,
ticks: {
callback: function(value) {
return formatRupiah(value);
}
}
}
},
plugins: {
tooltip: {
callbacks: {
label: function(context) {
return context.dataset.label + ': ' + formatRupiah(context.parsed.y);
}
}
}
}
}
});
}
// Category Distribution Chart
const categoryCtx = document.getElementById('category-distribution-chart');
if (categoryCtx) {
const categoryData = @json($categoryTotals);
const categories = categoryData.map(item => item.kategori);
const pendapatanPerKategori = categoryData.map(item => parseFloat(item.total_debit) || 0);
const bebanPerKategori = categoryData.map(item => parseFloat(item.total_kredit) || 0);
new Chart(categoryCtx, {
type: 'bar',
data: {
labels: categories,
datasets: [{
label: 'Pendapatan',
data: pendapatanPerKategori,
backgroundColor: 'rgba(34, 197, 94, 0.5)',
borderColor: 'rgb(34, 197, 94)',
borderWidth: 1
}, {
label: 'Beban',
data: bebanPerKategori,
backgroundColor: 'rgba(239, 68, 68, 0.5)',
borderColor: 'rgb(239, 68, 68)',
borderWidth: 1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
indexAxis: 'y',
scales: {
x: {
beginAtZero: true,
ticks: {
callback: function(value) {
return formatRupiah(value);
}
}
}
},
plugins: { plugins: {
legend: { legend: {
position: 'bottom' display: false
}, },
tooltip: { tooltip: {
callbacks: { callbacks: {
label: function(context) { label: function(context) {
return context.dataset.label + ': ' + formatRupiah(context.parsed.x); const value = context.parsed.y;
return formatRupiah(value);
},
title: function(context) {
return `Tanggal: ${context[0].label}`;
} }
},
backgroundColor: 'rgba(0, 0, 0, 0.8)',
padding: 12,
titleFont: {
size: 14,
weight: 'bold'
},
bodyFont: {
size: 13
} }
} }
},
scales: {
y: {
beginAtZero: true,
grid: {
display: false
},
ticks: {
display: false
}
},
x: {
grid: {
display: false
},
ticks: {
font: {
size: 11
},
maxRotation: 0,
autoSkip: true,
maxTicksLimit: 7
}
}
},
elements: {
line: {
tension: 0.4
}
} }
} }
}); });
// Debug untuk memastikan data terisi
console.log('Chart Data:', {
labels: labels,
data: pendapatanData
});
} }
// Pie Chart Neraca Saldo
var ctx = document.getElementById('category-distribution-chart').getContext('2d');
var pieLabels = @json($pieLabels);
var pieData = @json($pieData);
var pieColors = [
'#FF5733','#33FF57','#3357FF','#FF33A1','#FFBD33','#10b981','#f472b6','#6366f1','#f59e42','#e11d48'
];
var total = pieData.reduce((a, b) => a + b, 0);
var myPieChart = new Chart(ctx, {
type: 'pie',
data: {
labels: pieLabels,
datasets: [{
data: pieData,
backgroundColor: pieColors,
borderColor: '#fff',
borderWidth: 2
}]
},
options: {
responsive: true,
plugins: {
legend: { display: false },
datalabels: {
color: '#fff',
font: { weight: 'bold', size: 16 },
formatter: function(value) {
var percent = total ? (value / total * 100) : 0;
return percent.toFixed(1) + '%';
}
},
tooltip: {
callbacks: {
label: function(context) {
var label = context.label || '';
var value = context.parsed || 0;
var percent = total ? (value / total * 100) : 0;
return label + ': ' + value.toLocaleString('id-ID', {style:'currency', currency:'IDR'}) + ' (' + percent.toFixed(1) + '%)';
}
}
}
}
},
plugins: [ChartDataLabels]
});
} catch (error) { } catch (error) {
console.error('Error creating charts:', error); console.error('Error creating charts:', error);
} }
}); });
// Function to update chart type
function updateChartType(type) {
if (window.trendChart) {
window.trendChart.config.type = type;
window.trendChart.update();
}
}
</script> </script>
@endpush
@endsection @endsection

View File

@ -60,7 +60,7 @@
</tr> </tr>
@foreach($pendapatan as $item) @foreach($pendapatan as $item)
<tr class="border-b border-gray-300"> <tr class="border-b border-gray-300">
<td class="p-2 border border-gray-300 pl-8">{{ ucwords($item['kategori']) }} ({{ $item['kode_akun'] }})</td> <td class="p-2 border border-gray-300 pl-8">{{ ucwords($item['kategori']) }}</td>
<td class="text-right p-2 border border-gray-300"> <td class="text-right p-2 border border-gray-300">
{{ number_format(abs($item['nominal']), 0, ',', '.') }} {{ number_format(abs($item['nominal']), 0, ',', '.') }}
</td> </td>
@ -77,7 +77,7 @@
</tr> </tr>
@foreach($beban as $item) @foreach($beban as $item)
<tr class="border-b border-gray-300"> <tr class="border-b border-gray-300">
<td class="p-2 border border-gray-300 pl-8">{{ ucwords($item['kategori']) }} ({{ $item['kode_akun'] }})</td> <td class="p-2 border border-gray-300 pl-8">{{ ucwords($item['kategori']) }}</td>
<td class="text-right p-2 border border-gray-300"> <td class="text-right p-2 border border-gray-300">
{{ number_format(abs($item['nominal']), 0, ',', '.') }} {{ number_format(abs($item['nominal']), 0, ',', '.') }}
</td> </td>
@ -104,6 +104,84 @@
</tr> </tr>
</table> </table>
</div> </div>
<!-- Action Buttons -->
<div class="flex justify-between items-center mt-4 mb-4">
<div class="flex space-x-2">
<a href="{{ route('labarugi.export-excel', ['start_date' => $startDate, 'end_date' => $endDate]) }}" class="btn bg-green-500 text-white hover:bg-green-600 px-4 py-2 rounded">
<i class="fas fa-file-excel mr-2"></i>Export Excel
</a>
<a href="{{ route('labarugi.export-pdf', ['start_date' => $startDate, 'end_date' => $endDate]) }}" class="btn bg-red-500 text-white hover:bg-red-600 px-4 py-2 rounded">
<i class="fas fa-file-pdf mr-2"></i>Export PDF
</a>
<button onclick="window.print()" class="btn bg-gray-500 text-white hover:bg-gray-600 px-4 py-2 rounded">
<i class="fas fa-print mr-2"></i>Print
</button>
</div>
</div>
<!-- Style untuk print -->
<style>
@media print {
.btn, header, footer, .no-print, nav, .aside {
display: none !important;
}
body {
padding: 20px;
font-size: 12px;
background-color: white !important;
}
.box, .p-4, .intro-y {
padding: 0 !important;
margin: 0 !important;
background-color: white !important;
}
.bg-gray-100 {
background-color: white !important;
}
h1.text-2xl {
text-align: center;
font-size: 20px;
margin: 10px 0 5px 0;
font-weight: bold;
}
p.text-sm {
text-align: center;
margin: 5px 0 20px 0;
font-size: 12px;
}
table {
width: 100%;
border-collapse: collapse !important;
margin-bottom: 20px;
}
table, th, td {
border: 1px solid #000 !important;
}
th {
background-color: #6b46c1 !important;
color: white !important;
-webkit-print-color-adjust: exact;
color-adjust: exact;
print-color-adjust: exact;
}
.text-right {
text-align: right !important;
}
.bg-purple-100 {
background-color: #f3e8ff !important;
-webkit-print-color-adjust: exact;
color-adjust: exact;
print-color-adjust: exact;
}
.bg-gray-100 {
background-color: #f3f4f6 !important;
-webkit-print-color-adjust: exact;
color-adjust: exact;
print-color-adjust: exact;
}
}
</style>
</div> </div>
</div> </div>
@endsection @endsection

View File

@ -121,7 +121,7 @@
<th class="py-3 px-4 text-left">Keterangan</th> <th class="py-3 px-4 text-left">Keterangan</th>
<th class="py-3 px-4 text-right">Debit</th> <th class="py-3 px-4 text-right">Debit</th>
<th class="py-3 px-4 text-right">Kredit</th> <th class="py-3 px-4 text-right">Kredit</th>
<th class="py-3 px-4 text-center">Aksi</th> <th class="py-3 px-4 text-center aksi-col">Aksi</th>
</tr> </tr>
</thead> </thead>
<tbody id="tableBody"> <tbody id="tableBody">
@ -310,7 +310,7 @@
@endif @endif
</div> </div>
</td> </td>
<td class="py-3 px-4 text-center"> <td class="py-3 px-4 text-center aksi-col">
<div class="flex justify-center space-x-2"> <div class="flex justify-center space-x-2">
<!-- <button class="text-blue-600 hover:text-blue-800" title="Edit"> <!-- <button class="text-blue-600 hover:text-blue-800" title="Edit">
<i class="fas fa-edit"></i> --> <i class="fas fa-edit"></i> -->
@ -453,6 +453,9 @@
.ml-8 { .ml-8 {
margin-left: 8px !important; margin-left: 8px !important;
} }
.aksi-col, .aksi-col * {
display: none !important;
}
} }
</style> </style>

View File

@ -5,6 +5,10 @@
<title>Login Page</title> <title>Login Page</title>
<script src="https://cdn.tailwindcss.com"></script> <script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<!-- SweetAlert2 CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css">
<!-- SweetAlert2 JS -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<style> <style>
body { body {
background: linear-gradient(to bottom, #00c6ff, #0072ff, #ff00ff, #ff00ff); background: linear-gradient(to bottom, #00c6ff, #0072ff, #ff00ff, #ff00ff);
@ -14,21 +18,17 @@
<body class="flex items-center justify-center min-h-screen"> <body class="flex items-center justify-center min-h-screen">
<div class="bg-white p-8 rounded-lg shadow-lg w-80"> <div class="bg-white p-8 rounded-lg shadow-lg w-80">
<h2 class="text-2xl font-bold text-center mb-6">Login</h2> <h2 class="text-2xl font-bold text-center mb-6">Login</h2>
@if(session('error')) <form method="POST" action="{{ route('login.authenticate') }}" id="loginForm">
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative mb-4" role="alert">
{{ session('error') }}
</div>
@endif
<form method="POST" action="{{ route('login.authenticate') }}">
@csrf @csrf
<div class="mb-4"> <div class="mb-4">
<label class="block mb-2 text-sm font-medium text-gray-600" for="email"> <label class="block mb-2 text-sm font-medium text-gray-600" for="email">
<i class="fas fa-user"></i> Email <i class="fas fa-user"></i> Email
</label> </label>
<input class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500" <input class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 @error('email') border-red-500 @enderror"
type="email" type="email"
id="email" id="email"
name="email" name="email"
value="{{ old('email') }}"
placeholder="Type your email" placeholder="Type your email"
required> required>
</div> </div>
@ -36,7 +36,7 @@
<label class="block mb-2 text-sm font-medium text-gray-600" for="password"> <label class="block mb-2 text-sm font-medium text-gray-600" for="password">
<i class="fas fa-lock"></i> Password <i class="fas fa-lock"></i> Password
</label> </label>
<input class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500" <input class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 @error('password') border-red-500 @enderror"
type="password" type="password"
id="password" id="password"
name="password" name="password"
@ -64,5 +64,33 @@
</a> </a>
</div> --> </div> -->
</div> </div>
@if($errors->any())
<script>
document.addEventListener('DOMContentLoaded', function() {
Swal.fire({
icon: 'error',
title: 'Oops...',
text: '{{ $errors->first() }}',
confirmButtonColor: '#3085d6',
confirmButtonText: 'OK'
});
});
</script>
@endif
@if(session('error'))
<script>
document.addEventListener('DOMContentLoaded', function() {
Swal.fire({
icon: 'error',
title: 'Oops...',
text: '{{ session("error") }}',
confirmButtonColor: '#3085d6',
confirmButtonText: 'OK'
});
});
</script>
@endif
</body> </body>
</html> </html>

View File

@ -163,6 +163,25 @@
</div> </div>
<script> <script>
// Notifikasi SweetAlert2
@if(session('success'))
Swal.fire({
icon: 'success',
title: 'Berhasil!',
text: '{{ session("success") }}',
confirmButtonText: 'OK'
});
@endif
@if(session('error'))
Swal.fire({
icon: 'error',
title: 'Gagal!',
text: '{{ session("error") }}',
confirmButtonText: 'OK'
});
@endif
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
const userType = document.getElementById('userType'); const userType = document.getElementById('userType');
const searchUser = document.getElementById('searchUser'); const searchUser = document.getElementById('searchUser');
@ -208,41 +227,60 @@ function loadUsers(typeFilter = '', searchFilter = '') {
}) })
.catch(error => { .catch(error => {
console.error('Error loading users:', error); console.error('Error loading users:', error);
Swal.fire('Error!', 'Gagal memuat data user', 'error'); Swal.fire({
icon: 'error',
title: 'Error!',
text: 'Gagal memuat data user',
confirmButtonText: 'OK'
});
}); });
} }
function deleteUser(id) { function deleteUser(id) {
Swal.fire({ Swal.fire({
title: 'Hapus User', title: 'Apakah Anda yakin?',
text: 'Apakah Anda yakin ingin menghapus user ini?', text: "Data yang dihapus tidak dapat dikembalikan!",
icon: 'warning', icon: 'warning',
showCancelButton: true, showCancelButton: true,
confirmButtonText: 'Ya, Hapus', confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Ya, hapus!',
cancelButtonText: 'Batal' cancelButtonText: 'Batal'
}).then((result) => { }).then((result) => {
if (result.isConfirmed) { if (result.isConfirmed) {
fetch(`/User/${id}`, { fetch(`/User/${id}`, {
method: 'DELETE', method: 'DELETE',
headers: { headers: {
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
'Content-Type': 'application/json'
} }
}) })
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
if (data.success) { if (data.success) {
loadUsers( Swal.fire({
document.getElementById('userType').value, icon: 'success',
document.getElementById('searchUser').value title: 'Berhasil!',
); text: 'Data user berhasil dihapus',
Swal.fire('Berhasil!', 'User telah dihapus', 'success'); confirmButtonText: 'OK'
}).then(() => {
loadUsers(
document.getElementById('userType').value,
document.getElementById('searchUser').value
);
});
} else { } else {
throw new Error(data.message || 'Gagal menghapus user'); throw new Error(data.message || 'Gagal menghapus user');
} }
}) })
.catch(error => { .catch(error => {
console.error('Error deleting user:', error); console.error('Error:', error);
Swal.fire('Error!', 'Gagal menghapus user', 'error'); Swal.fire({
icon: 'error',
title: 'Gagal!',
text: error.message || 'Terjadi kesalahan saat menghapus data',
confirmButtonText: 'OK'
});
}); });
} }
}); });

View File

@ -84,4 +84,6 @@
// Routes untuk Laba Rugi // Routes untuk Laba Rugi
Route::get('/labarugi', [LabarugiController::class, 'index'])->name('labarugi.index'); Route::get('/labarugi', [LabarugiController::class, 'index'])->name('labarugi.index');
Route::get('/labarugi/filter', [LabarugiController::class, 'filter'])->name('labarugi.filter'); Route::get('/labarugi/filter', [LabarugiController::class, 'filter'])->name('labarugi.filter');
Route::get('/labarugi/export-excel', [LabarugiController::class, 'exportExcel'])->name('labarugi.export-excel');
Route::get('/labarugi/export-pdf', [LabarugiController::class, 'exportPDF'])->name('labarugi.export-pdf');
}); });