add bug fix
This commit is contained in:
parent
f92bfbcb4f
commit
4d4c6ca2a6
|
|
@ -99,6 +99,7 @@ export function CetakInstanModal() {
|
||||||
pengguna: PenggunaData
|
pengguna: PenggunaData
|
||||||
row: HasilItem
|
row: HasilItem
|
||||||
allHasil: HasilItem[]
|
allHasil: HasilItem[]
|
||||||
|
idBerkas: number
|
||||||
} | null>(null)
|
} | null>(null)
|
||||||
|
|
||||||
const templateRef = useRef<HTMLDivElement>(null)
|
const templateRef = useRef<HTMLDivElement>(null)
|
||||||
|
|
@ -176,6 +177,8 @@ export function CetakInstanModal() {
|
||||||
folderHandle = await dirHandle.getDirectoryHandle(folderName, { create: true })
|
folderHandle = await dirHandle.getDirectoryHandle(folderName, { create: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const currentIdBerkas = Date.now()
|
||||||
|
|
||||||
// 3. Generation Loop
|
// 3. Generation Loop
|
||||||
for (let i = 0; i < targets.length; i++) {
|
for (let i = 0; i < targets.length; i++) {
|
||||||
const b = targets[i] as PenggunaData
|
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 })
|
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 ---
|
// --- 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
|
// 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
|
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>
|
<p className="text-xs text-gray-500">Ibu: {progress.mama}</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="grid grid-cols-2 gap-3">
|
<div className="grid grid-cols-1 gap-3">
|
||||||
<div className="text-center px-3 py-3 bg-gray-50 border border-gray-200 rounded-xl">
|
<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-2xl font-black font-mono">{String(Math.floor(elapsed / 60)).padStart(2, '0')}:{String(elapsed % 60).padStart(2, '0')}</p>
|
<p className="text-[10px] font-bold uppercase tracking-widest text-gray-500 mb-1">Estimasi Selesai</p>
|
||||||
</div>
|
|
||||||
<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">{estRemaining !== null ? `${String(Math.floor(estRemaining / 60)).padStart(2, '0')}:${String(estRemaining % 60).padStart(2, '0')}` : '--:--'}</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>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -462,7 +469,7 @@ export function CetakInstanModal() {
|
||||||
['Nama Anak', activePrintData.pengguna.nama_anak],
|
['Nama Anak', activePrintData.pengguna.nama_anak],
|
||||||
['Alamat', activePrintData.pengguna.alamat ?? '-'],
|
['Alamat', activePrintData.pengguna.alamat ?? '-'],
|
||||||
['Jenis Kelamin', activePrintData.pengguna.jenis_kelamin ?? '-'],
|
['Jenis Kelamin', activePrintData.pengguna.jenis_kelamin ?? '-'],
|
||||||
['', ''],
|
['ID Berkas', String(activePrintData.idBerkas)],
|
||||||
['Tanggal Lahir', tanggalLahir],
|
['Tanggal Lahir', tanggalLahir],
|
||||||
].map(([label, value], i) => (
|
].map(([label, value], i) => (
|
||||||
label ? (
|
label ? (
|
||||||
|
|
@ -479,9 +486,9 @@ export function CetakInstanModal() {
|
||||||
<div style={{ marginBottom: 20 }}>
|
<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={{ 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 }}>
|
<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={{ 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}>
|
<ResponsiveContainer width="100%" height={120}>
|
||||||
<AreaChart data={chartData} margin={{ top: 4, right: 8, left: -20, bottom: 0 }}>
|
<AreaChart data={chartData} margin={{ top: 4, right: 8, left: -20, bottom: 0 }}>
|
||||||
<defs>
|
<defs>
|
||||||
|
|
@ -542,7 +549,7 @@ export function CetakInstanModal() {
|
||||||
<table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 11 }}>
|
<table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 11 }}>
|
||||||
<thead>
|
<thead>
|
||||||
<tr style={{ background: '#111', color: '#fff' }}>
|
<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>
|
<th key={h} style={{ padding: '8px 10px', fontWeight: 700, fontSize: 9, letterSpacing: 1, textTransform: 'uppercase', textAlign: 'left' }}>{h}</th>
|
||||||
))}
|
))}
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -570,17 +577,6 @@ export function CetakInstanModal() {
|
||||||
)}
|
)}
|
||||||
</div>
|
</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 ── */}
|
{/* ── Portal Access Info Box ── */}
|
||||||
<div style={{ marginTop: 16, padding: '14px', border: '2px dashed #000', borderRadius: 12, backgroundColor: '#fdfcf0' }}>
|
<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 }}>
|
<div style={{ fontSize: 10, fontWeight: 900, textTransform: 'uppercase', letterSpacing: 2, color: '#854d0e', display: 'flex', alignItems: 'center', gap: 6 }}>
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import {
|
||||||
ResponsiveContainer,
|
ResponsiveContainer,
|
||||||
} from 'recharts'
|
} from 'recharts'
|
||||||
import { showSwal } from '@/lib/swal'
|
import { showSwal } from '@/lib/swal'
|
||||||
|
import { supabase } from '@/lib/supabase'
|
||||||
|
|
||||||
interface HasilItem {
|
interface HasilItem {
|
||||||
id: number
|
id: number
|
||||||
|
|
@ -77,6 +78,7 @@ function build5MonthData(allData: HasilItem[], rowDate: Date) {
|
||||||
export function CetakPDFButton({ row, allData, pengguna }: Props) {
|
export function CetakPDFButton({ row, allData, pengguna }: Props) {
|
||||||
const templateRef = useRef<HTMLDivElement>(null)
|
const templateRef = useRef<HTMLDivElement>(null)
|
||||||
const [loading, setLoading] = useState(false)
|
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 rowDate = row.tanggal_upload ? new Date(row.tanggal_upload) : new Date()
|
||||||
const chartData = useMemo(() => build5MonthData(allData, rowDate), [allData, row.tanggal_upload])
|
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
|
if (!templateRef.current || loading) return
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
try {
|
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: html2canvas } = await import('html2canvas')
|
||||||
const { default: jsPDF } = await import('jspdf')
|
const { default: jsPDF } = await import('jspdf')
|
||||||
|
|
||||||
|
|
@ -176,7 +189,7 @@ export function CetakPDFButton({ row, allData, pengguna }: Props) {
|
||||||
['Nama Anak', pengguna.nama_anak],
|
['Nama Anak', pengguna.nama_anak],
|
||||||
['Alamat', pengguna.alamat ?? '-'],
|
['Alamat', pengguna.alamat ?? '-'],
|
||||||
['Jenis Kelamin', pengguna.jenis_kelamin ?? '-'],
|
['Jenis Kelamin', pengguna.jenis_kelamin ?? '-'],
|
||||||
['', ''],
|
['ID Berkas', idBerkas ? String(idBerkas) : '-'],
|
||||||
['Tanggal Lahir', tanggalLahir],
|
['Tanggal Lahir', tanggalLahir],
|
||||||
].map(([label, value], i) => (
|
].map(([label, value], i) => (
|
||||||
label ? (
|
label ? (
|
||||||
|
|
@ -195,9 +208,9 @@ export function CetakPDFButton({ row, allData, pengguna }: Props) {
|
||||||
Grafik Perkembangan Balita (5 Bulan Terakhir)
|
Grafik Perkembangan Balita (5 Bulan Terakhir)
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 }}>
|
<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={{ 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}>
|
<ResponsiveContainer width="100%" height={120}>
|
||||||
<AreaChart data={chartData} margin={{ top: 4, right: 8, left: -20, bottom: 0 }}>
|
<AreaChart data={chartData} margin={{ top: 4, right: 8, left: -20, bottom: 0 }}>
|
||||||
<defs>
|
<defs>
|
||||||
|
|
@ -272,7 +285,7 @@ export function CetakPDFButton({ row, allData, pengguna }: Props) {
|
||||||
<table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 11 }}>
|
<table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 11 }}>
|
||||||
<thead>
|
<thead>
|
||||||
<tr style={{ background: '#111', color: '#fff' }}>
|
<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>
|
<th key={h} style={{ padding: '8px 10px', fontWeight: 700, fontSize: 9, letterSpacing: 1, textTransform: 'uppercase', textAlign: 'left' }}>{h}</th>
|
||||||
))}
|
))}
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -313,17 +326,6 @@ export function CetakPDFButton({ row, allData, pengguna }: Props) {
|
||||||
)}
|
)}
|
||||||
</div>
|
</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 ── */}
|
{/* ── Portal Access Info Box ── */}
|
||||||
<div style={{ marginTop: 16, padding: '14px', border: '2px dashed #000', borderRadius: 12, backgroundColor: '#fdfcf0' }}>
|
<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 }}>
|
<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 */}
|
{/* 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">
|
<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 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">Berat</span>
|
||||||
<span className="text-center">Z-Score</span>
|
<span className="text-center">Z-Score</span>
|
||||||
<span className="text-center">Status</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>
|
<span className="text-xs text-gray-400 font-bold">{idx + 1}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Tinggi Badan */}
|
{/* Panjang Badan */}
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<span className="font-bold">{row.tinggi_badan ?? '-'}</span>
|
<span className="font-bold">{row.tinggi_badan ?? '-'}</span>
|
||||||
{row.tinggi_badan && <span className="text-xs text-gray-400 ml-0.5">cm</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 */}
|
{/* Charts Grid */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<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="rounded-xl border-2 border-blue-100 bg-blue-50/30 p-4">
|
||||||
<div className="flex items-center gap-2 mb-3">
|
<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">
|
<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" />
|
<Ruler className="w-4 h-4 text-blue-600" />
|
||||||
</div>
|
</div>
|
||||||
<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>
|
<p className="text-[10px] text-blue-400">Dalam satuan cm</p>
|
||||||
</div>
|
</div>
|
||||||
</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 className="flex-1 h-px bg-gradient-to-l from-transparent via-gray-200 to-gray-200" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Chart Perkembangan Tinggi & Berat */}
|
{/* Chart Perkembangan Panjang & Berat */}
|
||||||
<PerkembanganChart data={hasilData ?? []} />
|
<PerkembanganChart data={hasilData ?? []} />
|
||||||
|
|
||||||
{/* Professional Separator */}
|
{/* Professional Separator */}
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@ function build5MonthData(allData: HasilItem[], rowDate: Date) {
|
||||||
export function ExportPDFButton({ row, allData, pengguna }: Props) {
|
export function ExportPDFButton({ row, allData, pengguna }: Props) {
|
||||||
const templateRef = useRef<HTMLDivElement>(null)
|
const templateRef = useRef<HTMLDivElement>(null)
|
||||||
const [loading, setLoading] = useState(false)
|
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 rowDate = row.tanggal_upload ? new Date(row.tanggal_upload) : new Date()
|
||||||
const chartData = useMemo(() => build5MonthData(allData, rowDate), [allData, row.tanggal_upload])
|
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
|
if (!templateRef.current || loading) return
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
try {
|
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: html2canvas } = await import('html2canvas')
|
||||||
const { default: jsPDF } = await import('jspdf')
|
const { default: jsPDF } = await import('jspdf')
|
||||||
|
|
||||||
|
|
@ -174,7 +187,7 @@ export function ExportPDFButton({ row, allData, pengguna }: Props) {
|
||||||
['Nama Anak', pengguna.nama_anak],
|
['Nama Anak', pengguna.nama_anak],
|
||||||
['Alamat', pengguna.alamat ?? '-'],
|
['Alamat', pengguna.alamat ?? '-'],
|
||||||
['Jenis Kelamin', pengguna.jenis_kelamin ?? '-'],
|
['Jenis Kelamin', pengguna.jenis_kelamin ?? '-'],
|
||||||
['', ''],
|
['ID Berkas', idBerkas ? String(idBerkas) : '-'],
|
||||||
['Tanggal Lahir', tanggalLahir],
|
['Tanggal Lahir', tanggalLahir],
|
||||||
].map(([label, value], i) => (
|
].map(([label, value], i) => (
|
||||||
label ? (
|
label ? (
|
||||||
|
|
@ -193,9 +206,9 @@ export function ExportPDFButton({ row, allData, pengguna }: Props) {
|
||||||
Grafik Pertumbuhan (5 Bulan Terakhir)
|
Grafik Pertumbuhan (5 Bulan Terakhir)
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 }}>
|
<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={{ 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}>
|
<ResponsiveContainer width="100%" height={120}>
|
||||||
<AreaChart data={chartData} margin={{ top: 4, right: 8, left: -20, bottom: 0 }}>
|
<AreaChart data={chartData} margin={{ top: 4, right: 8, left: -20, bottom: 0 }}>
|
||||||
<defs>
|
<defs>
|
||||||
|
|
@ -270,7 +283,7 @@ export function ExportPDFButton({ row, allData, pengguna }: Props) {
|
||||||
<table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 11 }}>
|
<table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 11 }}>
|
||||||
<thead>
|
<thead>
|
||||||
<tr style={{ background: '#111', color: '#fff' }}>
|
<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>
|
<th key={h} style={{ padding: '8px 10px', fontWeight: 700, fontSize: 9, letterSpacing: 1, textTransform: 'uppercase', textAlign: 'left' }}>{h}</th>
|
||||||
))}
|
))}
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -311,17 +324,6 @@ export function ExportPDFButton({ row, allData, pengguna }: Props) {
|
||||||
)}
|
)}
|
||||||
</div>
|
</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 ── */}
|
{/* ── Portal Access Info Box ── */}
|
||||||
<div style={{ marginTop: 16, padding: '14px', border: '2px dashed #000', borderRadius: 12, backgroundColor: '#fdfcf0' }}>
|
<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 }}>
|
<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
|
Grafik Pertumbuhan Anak
|
||||||
</p>
|
</p>
|
||||||
<p className="text-[10px] text-gray-400 font-bold uppercase tracking-widest">
|
<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>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -120,7 +120,7 @@ export function GrowthChart({ data }: Props) {
|
||||||
<Ruler className="w-5 h-5 text-blue-600" />
|
<Ruler className="w-5 h-5 text-blue-600" />
|
||||||
</div>
|
</div>
|
||||||
<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>
|
<p className="text-[10px] text-blue-400 font-bold uppercase tracking-tighter">Satuan Centimeter (cm)</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ export function StuntingTable({ data, pengguna }: Props) {
|
||||||
<div className="min-w-[1000px]">
|
<div className="min-w-[1000px]">
|
||||||
{/* Header */}
|
{/* 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">
|
<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">Berat</span>
|
||||||
<span className="text-center">Z-Score</span>
|
<span className="text-center">Z-Score</span>
|
||||||
<span className="text-center">Status</span>
|
<span className="text-center">Status</span>
|
||||||
|
|
@ -115,7 +115,7 @@ export function StuntingTable({ data, pengguna }: Props) {
|
||||||
key={row.id}
|
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"
|
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">
|
<div className="text-center">
|
||||||
<span className="font-black text-lg text-black">{row.tinggi_badan ?? '-'}</span>
|
<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>}
|
{row.tinggi_badan && <span className="text-[10px] text-gray-400 ml-1 font-bold">cm</span>}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue