add bug fix
This commit is contained in:
parent
f92bfbcb4f
commit
4d4c6ca2a6
|
|
@ -99,6 +99,7 @@ export function CetakInstanModal() {
|
|||
pengguna: PenggunaData
|
||||
row: HasilItem
|
||||
allHasil: HasilItem[]
|
||||
idBerkas: number
|
||||
} | null>(null)
|
||||
|
||||
const templateRef = useRef<HTMLDivElement>(null)
|
||||
|
|
@ -176,6 +177,8 @@ export function CetakInstanModal() {
|
|||
folderHandle = await dirHandle.getDirectoryHandle(folderName, { create: true })
|
||||
}
|
||||
|
||||
const currentIdBerkas = Date.now()
|
||||
|
||||
// 3. Generation Loop
|
||||
for (let i = 0; i < targets.length; i++) {
|
||||
const b = targets[i] as PenggunaData
|
||||
|
|
@ -190,8 +193,14 @@ export function CetakInstanModal() {
|
|||
|
||||
setProgress({ current: i + 1, total: targets.length, name: b.nama_anak, mama: b.nama_orang_tua })
|
||||
|
||||
// --- Save to cetak_balita ---
|
||||
await supabase.from('cetak_balita').insert({
|
||||
id_berkas: currentIdBerkas,
|
||||
nama_balita: b.nama_anak,
|
||||
})
|
||||
|
||||
// --- Update template and wait for render ---
|
||||
setActivePrintData({ pengguna: b, row: rowForMonth, allHasil: balitaHasil })
|
||||
setActivePrintData({ pengguna: b, row: rowForMonth, allHasil: balitaHasil, idBerkas: currentIdBerkas })
|
||||
// Give React and Recharts some time to finish rendering the hidden template
|
||||
await new Promise(r => setTimeout(r, 1000)) // 1s buffer for stable DOM & Recharts
|
||||
|
||||
|
|
@ -395,11 +404,9 @@ export function CetakInstanModal() {
|
|||
<p className="text-xs text-gray-500">Ibu: {progress.mama}</p>
|
||||
</div>
|
||||
)}
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div className="text-center px-3 py-3 bg-gray-50 border border-gray-200 rounded-xl">
|
||||
<p className="text-2xl font-black font-mono">{String(Math.floor(elapsed / 60)).padStart(2, '0')}:{String(elapsed % 60).padStart(2, '0')}</p>
|
||||
</div>
|
||||
<div className="text-center px-3 py-3 bg-gray-50 border border-gray-200 rounded-xl">
|
||||
<div className="grid grid-cols-1 gap-3">
|
||||
<div className="flex flex-col items-center justify-center px-3 py-3 bg-gray-50 border border-gray-200 rounded-xl">
|
||||
<p className="text-[10px] font-bold uppercase tracking-widest text-gray-500 mb-1">Estimasi Selesai</p>
|
||||
<p className="text-2xl font-black font-mono">{estRemaining !== null ? `${String(Math.floor(estRemaining / 60)).padStart(2, '0')}:${String(estRemaining % 60).padStart(2, '0')}` : '--:--'}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -462,7 +469,7 @@ export function CetakInstanModal() {
|
|||
['Nama Anak', activePrintData.pengguna.nama_anak],
|
||||
['Alamat', activePrintData.pengguna.alamat ?? '-'],
|
||||
['Jenis Kelamin', activePrintData.pengguna.jenis_kelamin ?? '-'],
|
||||
['', ''],
|
||||
['ID Berkas', String(activePrintData.idBerkas)],
|
||||
['Tanggal Lahir', tanggalLahir],
|
||||
].map(([label, value], i) => (
|
||||
label ? (
|
||||
|
|
@ -479,9 +486,9 @@ export function CetakInstanModal() {
|
|||
<div style={{ marginBottom: 20 }}>
|
||||
<div style={{ fontSize: 10, fontWeight: 700, letterSpacing: 2, textTransform: 'uppercase', color: '#888', marginBottom: 6 }}>Grafik Perkembangan Balita (5 Bulan Terakhir)</div>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 }}>
|
||||
{/* Tinggi */}
|
||||
{/* Panjang */}
|
||||
<div style={{ border: '1.5px solid #dbeafe', borderRadius: 10, padding: '12px 12px 2px', background: '#eff6ff' }}>
|
||||
<div style={{ fontSize: 10, fontWeight: 700, color: '#1d4ed8', marginBottom: 6 }}>📏 Tinggi Badan (cm)</div>
|
||||
<div style={{ fontSize: 10, fontWeight: 700, color: '#1d4ed8', marginBottom: 6 }}>📏 Panjang Badan (cm)</div>
|
||||
<ResponsiveContainer width="100%" height={120}>
|
||||
<AreaChart data={chartData} margin={{ top: 4, right: 8, left: -20, bottom: 0 }}>
|
||||
<defs>
|
||||
|
|
@ -542,7 +549,7 @@ export function CetakInstanModal() {
|
|||
<table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 11 }}>
|
||||
<thead>
|
||||
<tr style={{ background: '#111', color: '#fff' }}>
|
||||
{['Tinggi', 'Berat', 'Z-Score', 'Status Stunting', 'Posyandu', 'Tgl Pemeriksaan'].map(h => (
|
||||
{['Panjang', 'Berat', 'Z-Score', 'Status Stunting', 'Posyandu', 'Tgl Pemeriksaan'].map(h => (
|
||||
<th key={h} style={{ padding: '8px 10px', fontWeight: 700, fontSize: 9, letterSpacing: 1, textTransform: 'uppercase', textAlign: 'left' }}>{h}</th>
|
||||
))}
|
||||
</tr>
|
||||
|
|
@ -570,17 +577,6 @@ export function CetakInstanModal() {
|
|||
)}
|
||||
</div>
|
||||
|
||||
{/* ── WhatsApp Info Box ── */}
|
||||
<div style={{ marginTop: 16, padding: '10px 14px', borderRadius: 10, backgroundColor: '#f0fdf4', border: '1px solid #bbf7d0', display: 'flex', alignItems: 'flex-start', gap: 10 }}>
|
||||
<div style={{ fontSize: 16 }}>📱</div>
|
||||
<div>
|
||||
<div style={{ fontSize: 9, fontWeight: 800, color: '#166534', textTransform: 'uppercase', letterSpacing: 1, marginBottom: 2 }}>Layanan Informasi WhatsApp</div>
|
||||
<div style={{ fontSize: 10, lineHeight: 1.5, color: '#14532d' }}>
|
||||
Untuk orang tua yang tidak memiliki akun WhatsApp, yuk segera buat akun karena kami melayani layanan penyampaian informasi hasil stunting dengan menggunakan WhatsApp agar mendapatkan informasi lebih cepat.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* ── Portal Access Info Box ── */}
|
||||
<div style={{ marginTop: 16, padding: '14px', border: '2px dashed #000', borderRadius: 12, backgroundColor: '#fdfcf0' }}>
|
||||
<div style={{ fontSize: 10, fontWeight: 900, textTransform: 'uppercase', letterSpacing: 2, color: '#854d0e', display: 'flex', alignItems: 'center', gap: 6 }}>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import {
|
|||
ResponsiveContainer,
|
||||
} from 'recharts'
|
||||
import { showSwal } from '@/lib/swal'
|
||||
import { supabase } from '@/lib/supabase'
|
||||
|
||||
interface HasilItem {
|
||||
id: number
|
||||
|
|
@ -77,6 +78,7 @@ function build5MonthData(allData: HasilItem[], rowDate: Date) {
|
|||
export function CetakPDFButton({ row, allData, pengguna }: Props) {
|
||||
const templateRef = useRef<HTMLDivElement>(null)
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [idBerkas, setIdBerkas] = useState<number | null>(null)
|
||||
|
||||
const rowDate = row.tanggal_upload ? new Date(row.tanggal_upload) : new Date()
|
||||
const chartData = useMemo(() => build5MonthData(allData, rowDate), [allData, row.tanggal_upload])
|
||||
|
|
@ -90,6 +92,17 @@ export function CetakPDFButton({ row, allData, pengguna }: Props) {
|
|||
if (!templateRef.current || loading) return
|
||||
setLoading(true)
|
||||
try {
|
||||
const currentIdBerkas = Date.now()
|
||||
setIdBerkas(currentIdBerkas)
|
||||
|
||||
await supabase.from('cetak_balita').insert({
|
||||
id_berkas: currentIdBerkas,
|
||||
nama_balita: pengguna.nama_anak,
|
||||
})
|
||||
|
||||
// Tunggu render React selesai (untuk menampilkan ID Berkas)
|
||||
await new Promise(r => setTimeout(r, 500))
|
||||
|
||||
const { default: html2canvas } = await import('html2canvas')
|
||||
const { default: jsPDF } = await import('jspdf')
|
||||
|
||||
|
|
@ -176,7 +189,7 @@ export function CetakPDFButton({ row, allData, pengguna }: Props) {
|
|||
['Nama Anak', pengguna.nama_anak],
|
||||
['Alamat', pengguna.alamat ?? '-'],
|
||||
['Jenis Kelamin', pengguna.jenis_kelamin ?? '-'],
|
||||
['', ''],
|
||||
['ID Berkas', idBerkas ? String(idBerkas) : '-'],
|
||||
['Tanggal Lahir', tanggalLahir],
|
||||
].map(([label, value], i) => (
|
||||
label ? (
|
||||
|
|
@ -195,9 +208,9 @@ export function CetakPDFButton({ row, allData, pengguna }: Props) {
|
|||
Grafik Perkembangan Balita (5 Bulan Terakhir)
|
||||
</div>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 }}>
|
||||
{/* Tinggi */}
|
||||
{/* Panjang */}
|
||||
<div style={{ border: '1.5px solid #dbeafe', borderRadius: 10, padding: '12px 12px 2px', background: '#eff6ff' }}>
|
||||
<div style={{ fontSize: 10, fontWeight: 700, color: '#1d4ed8', marginBottom: 6 }}>📏 Tinggi Badan (cm)</div>
|
||||
<div style={{ fontSize: 10, fontWeight: 700, color: '#1d4ed8', marginBottom: 6 }}>📏 Panjang Badan (cm)</div>
|
||||
<ResponsiveContainer width="100%" height={120}>
|
||||
<AreaChart data={chartData} margin={{ top: 4, right: 8, left: -20, bottom: 0 }}>
|
||||
<defs>
|
||||
|
|
@ -272,7 +285,7 @@ export function CetakPDFButton({ row, allData, pengguna }: Props) {
|
|||
<table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 11 }}>
|
||||
<thead>
|
||||
<tr style={{ background: '#111', color: '#fff' }}>
|
||||
{['Tinggi', 'Berat', 'Z-Score', 'Status Stunting', 'Posyandu', 'Tgl Pemeriksaan'].map(h => (
|
||||
{['Panjang', 'Berat', 'Z-Score', 'Status Stunting', 'Posyandu', 'Tgl Pemeriksaan'].map(h => (
|
||||
<th key={h} style={{ padding: '8px 10px', fontWeight: 700, fontSize: 9, letterSpacing: 1, textTransform: 'uppercase', textAlign: 'left' }}>{h}</th>
|
||||
))}
|
||||
</tr>
|
||||
|
|
@ -313,17 +326,6 @@ export function CetakPDFButton({ row, allData, pengguna }: Props) {
|
|||
)}
|
||||
</div>
|
||||
|
||||
{/* ── WhatsApp Info Box ── */}
|
||||
<div style={{ marginTop: 16, padding: '10px 14px', borderRadius: 10, backgroundColor: '#f0fdf4', border: '1px solid #bbf7d0', display: 'flex', alignItems: 'flex-start', gap: 10 }}>
|
||||
<div style={{ fontSize: 16 }}>📱</div>
|
||||
<div>
|
||||
<div style={{ fontSize: 9, fontWeight: 800, color: '#166534', textTransform: 'uppercase', letterSpacing: 1, marginBottom: 2 }}>Layanan Informasi WhatsApp</div>
|
||||
<div style={{ fontSize: 10, lineHeight: 1.5, color: '#14532d' }}>
|
||||
Untuk orang tua yang tidak memiliki akun WhatsApp, yuk segera buat akun karena kami melayani layanan penyampaian informasi hasil stunting dengan menggunakan WhatsApp agar mendapatkan informasi lebih cepat.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* ── Portal Access Info Box ── */}
|
||||
<div style={{ marginTop: 16, padding: '14px', border: '2px dashed #000', borderRadius: 12, backgroundColor: '#fdfcf0' }}>
|
||||
<div style={{ fontSize: 10, fontWeight: 900, textTransform: 'uppercase', letterSpacing: 2, color: '#854d0e', display: 'flex', alignItems: 'center', gap: 6 }}>
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ export function HasilStuntingTable({ data, pengguna }: Props) {
|
|||
{/* Header */}
|
||||
<div className="grid grid-cols-[36px_88px_88px_88px_100px_1fr_108px_110px_90px] bg-black text-white px-4 py-3 text-[10px] font-bold uppercase tracking-widest">
|
||||
<span className="text-center text-gray-500">#</span>
|
||||
<span className="text-center">Tinggi</span>
|
||||
<span className="text-center">Panjang</span>
|
||||
<span className="text-center">Berat</span>
|
||||
<span className="text-center">Z-Score</span>
|
||||
<span className="text-center">Status</span>
|
||||
|
|
@ -121,7 +121,7 @@ export function HasilStuntingTable({ data, pengguna }: Props) {
|
|||
<span className="text-xs text-gray-400 font-bold">{idx + 1}</span>
|
||||
</div>
|
||||
|
||||
{/* Tinggi Badan */}
|
||||
{/* Panjang Badan */}
|
||||
<div className="text-center">
|
||||
<span className="font-bold">{row.tinggi_badan ?? '-'}</span>
|
||||
{row.tinggi_badan && <span className="text-xs text-gray-400 ml-0.5">cm</span>}
|
||||
|
|
|
|||
|
|
@ -107,14 +107,14 @@ export function PerkembanganChart({ data }: Props) {
|
|||
{/* Charts Grid */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
|
||||
{/* Tinggi Badan */}
|
||||
{/* Panjang Badan */}
|
||||
<div className="rounded-xl border-2 border-blue-100 bg-blue-50/30 p-4">
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<div className="w-8 h-8 rounded-lg bg-blue-100 border border-blue-200 flex items-center justify-center">
|
||||
<Ruler className="w-4 h-4 text-blue-600" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-bold text-blue-800">Tinggi Badan</p>
|
||||
<p className="text-sm font-bold text-blue-800">Panjang Badan</p>
|
||||
<p className="text-[10px] text-blue-400">Dalam satuan cm</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ export default async function DetailPenggunaKelolaPage({ params }: Props) {
|
|||
<div className="flex-1 h-px bg-gradient-to-l from-transparent via-gray-200 to-gray-200" />
|
||||
</div>
|
||||
|
||||
{/* Chart Perkembangan Tinggi & Berat */}
|
||||
{/* Chart Perkembangan Panjang & Berat */}
|
||||
<PerkembanganChart data={hasilData ?? []} />
|
||||
|
||||
{/* Professional Separator */}
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ function build5MonthData(allData: HasilItem[], rowDate: Date) {
|
|||
export function ExportPDFButton({ row, allData, pengguna }: Props) {
|
||||
const templateRef = useRef<HTMLDivElement>(null)
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [idBerkas, setIdBerkas] = useState<number | null>(null)
|
||||
|
||||
const rowDate = row.tanggal_upload ? new Date(row.tanggal_upload) : new Date()
|
||||
const chartData = useMemo(() => build5MonthData(allData, rowDate), [allData, row.tanggal_upload])
|
||||
|
|
@ -89,6 +90,18 @@ export function ExportPDFButton({ row, allData, pengguna }: Props) {
|
|||
if (!templateRef.current || loading) return
|
||||
setLoading(true)
|
||||
try {
|
||||
const currentIdBerkas = Date.now()
|
||||
setIdBerkas(currentIdBerkas)
|
||||
|
||||
const { supabase } = await import('@/lib/supabase')
|
||||
await supabase.from('cetak_balita').insert({
|
||||
id_berkas: currentIdBerkas,
|
||||
nama_balita: pengguna.nama_anak,
|
||||
})
|
||||
|
||||
// Tunggu render React selesai (untuk menampilkan ID Berkas)
|
||||
await new Promise(r => setTimeout(r, 500))
|
||||
|
||||
const { default: html2canvas } = await import('html2canvas')
|
||||
const { default: jsPDF } = await import('jspdf')
|
||||
|
||||
|
|
@ -174,7 +187,7 @@ export function ExportPDFButton({ row, allData, pengguna }: Props) {
|
|||
['Nama Anak', pengguna.nama_anak],
|
||||
['Alamat', pengguna.alamat ?? '-'],
|
||||
['Jenis Kelamin', pengguna.jenis_kelamin ?? '-'],
|
||||
['', ''],
|
||||
['ID Berkas', idBerkas ? String(idBerkas) : '-'],
|
||||
['Tanggal Lahir', tanggalLahir],
|
||||
].map(([label, value], i) => (
|
||||
label ? (
|
||||
|
|
@ -193,9 +206,9 @@ export function ExportPDFButton({ row, allData, pengguna }: Props) {
|
|||
Grafik Pertumbuhan (5 Bulan Terakhir)
|
||||
</div>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 }}>
|
||||
{/* Tinggi */}
|
||||
{/* Panjang */}
|
||||
<div style={{ border: '1.5 solid #dbeafe', borderRadius: 10, padding: '12px 12px 2px', background: '#eff6ff', borderStyle: 'solid', borderWidth: '1.5px', borderColor: '#dbeafe' }}>
|
||||
<div style={{ fontSize: 10, fontWeight: 700, color: '#1d4ed8', marginBottom: 6 }}>📏 Tinggi Badan (cm)</div>
|
||||
<div style={{ fontSize: 10, fontWeight: 700, color: '#1d4ed8', marginBottom: 6 }}>📏 Panjang Badan (cm)</div>
|
||||
<ResponsiveContainer width="100%" height={120}>
|
||||
<AreaChart data={chartData} margin={{ top: 4, right: 8, left: -20, bottom: 0 }}>
|
||||
<defs>
|
||||
|
|
@ -270,7 +283,7 @@ export function ExportPDFButton({ row, allData, pengguna }: Props) {
|
|||
<table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 11 }}>
|
||||
<thead>
|
||||
<tr style={{ background: '#111', color: '#fff' }}>
|
||||
{['Tinggi', 'Berat', 'Z-Score', 'Status Stunting', 'Posyandu', 'Tgl Pemeriksaan'].map(h => (
|
||||
{['Panjang', 'Berat', 'Z-Score', 'Status Stunting', 'Posyandu', 'Tgl Pemeriksaan'].map(h => (
|
||||
<th key={h} style={{ padding: '8px 10px', fontWeight: 700, fontSize: 9, letterSpacing: 1, textTransform: 'uppercase', textAlign: 'left' }}>{h}</th>
|
||||
))}
|
||||
</tr>
|
||||
|
|
@ -311,17 +324,6 @@ export function ExportPDFButton({ row, allData, pengguna }: Props) {
|
|||
)}
|
||||
</div>
|
||||
|
||||
{/* ── WhatsApp Info Box ── */}
|
||||
<div style={{ marginTop: 16, padding: '10px 14px', borderRadius: 10, backgroundColor: '#f0fdf4', border: '1px solid #bbf7d0', display: 'flex', alignItems: 'flex-start', gap: 10 }}>
|
||||
<div style={{ fontSize: 16 }}>📱</div>
|
||||
<div>
|
||||
<div style={{ fontSize: 9, fontWeight: 800, color: '#166534', textTransform: 'uppercase', letterSpacing: 1, marginBottom: 2 }}>Layanan Informasi WhatsApp</div>
|
||||
<div style={{ fontSize: 10, lineHeight: 1.5, color: '#14532d' }}>
|
||||
Untuk orang tua yang tidak memiliki akun WhatsApp, yuk segera buat akun karena kami melayani layanan penyampaian informasi hasil stunting dengan menggunakan WhatsApp agar mendapatkan informasi lebih cepat.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* ── Portal Access Info Box ── */}
|
||||
<div style={{ marginTop: 16, padding: '14px', border: '2px dashed #000', borderRadius: 12, backgroundColor: '#fdfcf0' }}>
|
||||
<div style={{ fontSize: 10, fontWeight: 900, textTransform: 'uppercase', letterSpacing: 2, color: '#854d0e', display: 'flex', alignItems: 'center', gap: 6 }}>
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ export function GrowthChart({ data }: Props) {
|
|||
Grafik Pertumbuhan Anak
|
||||
</p>
|
||||
<p className="text-[10px] text-gray-400 font-bold uppercase tracking-widest">
|
||||
Statistik Tinggi, Berat & Z-Score {selectedYear}
|
||||
Statistik Panjang, Berat & Z-Score {selectedYear}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -120,7 +120,7 @@ export function GrowthChart({ data }: Props) {
|
|||
<Ruler className="w-5 h-5 text-blue-600" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-xs font-black text-blue-800 uppercase tracking-widest">Tinggi Badan</p>
|
||||
<p className="text-xs font-black text-blue-800 uppercase tracking-widest">Panjang Badan</p>
|
||||
<p className="text-[10px] text-blue-400 font-bold uppercase tracking-tighter">Satuan Centimeter (cm)</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ export function StuntingTable({ data, pengguna }: Props) {
|
|||
<div className="min-w-[1000px]">
|
||||
{/* Header */}
|
||||
<div className="grid grid-cols-[100px_100px_100px_140px_1fr_160px_160px_120px] bg-black text-white px-6 py-4 text-[10px] font-black uppercase tracking-widest">
|
||||
<span className="text-center">Tinggi</span>
|
||||
<span className="text-center">Panjang</span>
|
||||
<span className="text-center">Berat</span>
|
||||
<span className="text-center">Z-Score</span>
|
||||
<span className="text-center">Status</span>
|
||||
|
|
@ -115,7 +115,7 @@ export function StuntingTable({ data, pengguna }: Props) {
|
|||
key={row.id}
|
||||
className="grid grid-cols-[100px_100px_100px_140px_1fr_160px_160px_120px] items-center px-6 py-6 transition-colors hover:bg-gray-50/50"
|
||||
>
|
||||
{/* Tinggi Badan */}
|
||||
{/* Panjang Badan */}
|
||||
<div className="text-center">
|
||||
<span className="font-black text-lg text-black">{row.tinggi_badan ?? '-'}</span>
|
||||
{row.tinggi_badan && <span className="text-[10px] text-gray-400 ml-1 font-bold">cm</span>}
|
||||
|
|
|
|||
Loading…
Reference in New Issue