fix: production build CSS dan responsive layout untuk staging

- Tambah scripts/build.ts untuk build CSS via PostCSS/Tailwind
- Update package.json build script untuk gunakan build script baru
- Fix responsive grid di sosial-page (lg -> md breakpoint)
- Tambah padding responsive untuk mobile display
- Convert inline styles ke Tailwind classes untuk konsistensi
- Update tailwind.config.js content paths
- Tambah CSS variables di index.css untuk color palette
- Update Dockerfile untuk gunakan build script baru

Fixes: tampilan berantakan di staging karena CSS tidak ter-build dengan benar

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
2026-03-12 12:16:57 +08:00
parent 66d207c081
commit 947adc1537
12 changed files with 693 additions and 224 deletions

View File

@@ -115,62 +115,55 @@ const SosialPage = () => {
},
];
const cardStyle = {
backgroundColor: dark ? "#1E293B" : "white",
border: `1px solid ${dark ? "#1E293B" : "white"}`,
};
const textStyle = {
color: dark ? "white" : "#1F2937",
};
const subtitleStyle = {
color: dark ? "#9CA3AF" : "#6B7280",
};
return (
<div
className="min-h-screen"
style={{ backgroundColor: dark ? "#0F172A" : "#F3F4F6" }}
className={`min-h-screen py-6 px-4 sm:px-6 lg:px-8 ${
dark ? "bg-slate-900" : "bg-gray-100"
}`}
>
<div className="max-w-7xl mx-auto">
<div className="max-w-7xl mx-auto w-full">
{/* Row 1: Top 4 Metrics Cards */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-6">
{healthStats.map((stat, index) => (
<div
key={index}
className="rounded-xl shadow-sm p-6"
style={cardStyle}
className={`rounded-xl shadow-sm p-6 ${
dark ? "bg-slate-800 border border-slate-800" : "bg-white border border-white"
}`}
>
<div className="flex items-center justify-between">
<div className="flex-1">
<h3
className="text-sm font-medium mb-1"
style={subtitleStyle}
className={`text-sm font-medium mb-1 ${
dark ? "text-gray-400" : "text-gray-500"
}`}
>
{stat.title}
</h3>
<p
className="text-3xl font-bold mb-1"
style={
stat.alert ? { color: "#EF4444" } : textStyle
}
className={`text-3xl font-bold mb-1 ${
stat.alert
? "text-red-500"
: dark
? "text-white"
: "text-gray-800"
}`}
>
{stat.value}
</p>
<p
className="text-xs"
style={subtitleStyle}
className={`text-xs ${
dark ? "text-gray-400" : "text-gray-500"
}`}
>
{stat.subtitle}
</p>
</div>
<div className="flex-shrink-0 ml-4">
<div
className="w-12 h-12 rounded-full flex items-center justify-center text-white"
style={{
backgroundColor: stat.alert ? "#EF4444" : "#1F3A5F",
}}
className={`w-12 h-12 rounded-full flex items-center justify-center text-white ${
stat.alert ? "bg-red-500" : "bg-blue-900"
}`}
>
<stat.icon size={24} />
</div>
@@ -182,12 +175,14 @@ const SosialPage = () => {
{/* Row 2: Statistik Kesehatan */}
<div
className="rounded-xl shadow-sm p-6 mb-6"
style={cardStyle}
className={`rounded-xl shadow-sm p-6 mb-6 ${
dark ? "bg-slate-800 border border-slate-800" : "bg-white border border-white"
}`}
>
<h3
className="text-lg font-semibold mb-6"
style={textStyle}
className={`text-lg font-semibold mb-6 ${
dark ? "text-white" : "text-gray-800"
}`}
>
Statistik Kesehatan
</h3>
@@ -196,34 +191,34 @@ const SosialPage = () => {
<div key={index}>
<div className="flex items-center justify-between mb-2">
<span
className="text-sm font-medium"
style={textStyle}
className={`text-sm font-medium ${
dark ? "text-white" : "text-gray-800"
}`}
>
{item.label}
</span>
<span
className="text-sm font-semibold"
style={
className={`text-sm font-semibold ${
item.isAlert
? { color: "#EF4444" }
: textStyle
}
? "text-red-500"
: dark
? "text-white"
: "text-gray-800"
}`}
>
{item.value}%
</span>
</div>
<div
className="w-full rounded-full h-2"
style={{ backgroundColor: dark ? "#334155" : "#E5E7EB" }}
className={`w-full rounded-full h-2 ${
dark ? "bg-slate-700" : "bg-gray-200"
}`}
>
<div
className="h-2 rounded-full transition-all"
style={{
width: `${item.value}%`,
backgroundColor: item.isAlert
? "#EF4444"
: "#1F3A5F",
}}
className={`h-2 rounded-full transition-all ${
item.isAlert ? "bg-red-500" : "bg-blue-900"
}`}
style={{ width: `${item.value}%` }}
/>
</div>
</div>
@@ -232,15 +227,17 @@ const SosialPage = () => {
</div>
{/* Row 3: Jadwal Posyandu & Pendidikan */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
{/* Jadwal Posyandu */}
<div
className="rounded-xl shadow-sm p-6"
style={cardStyle}
className={`rounded-xl shadow-sm p-6 ${
dark ? "bg-slate-800 border border-slate-800" : "bg-white border border-white"
}`}
>
<h3
className="text-lg font-semibold mb-4"
style={textStyle}
className={`text-lg font-semibold mb-4 ${
dark ? "text-white" : "text-gray-800"
}`}
>
Jadwal Posyandu
</h3>
@@ -248,32 +245,29 @@ const SosialPage = () => {
{posyanduSchedule.map((item, index) => (
<div
key={index}
className="p-4 rounded-lg"
style={{
backgroundColor: dark ? "#334155" : "#F9FAFB",
}}
className={`p-4 rounded-lg ${
dark ? "bg-slate-700" : "bg-gray-50"
}`}
>
<div className="flex items-center justify-between">
<div>
<p
className="text-sm font-medium"
style={textStyle}
className={`text-sm font-medium ${
dark ? "text-white" : "text-gray-800"
}`}
>
{item.nama}
</p>
<p
className="text-xs mt-1"
style={subtitleStyle}
className={`text-xs mt-1 ${
dark ? "text-gray-400" : "text-gray-500"
}`}
>
{item.tanggal}
</p>
</div>
<span
className="inline-flex items-center px-3 py-1 rounded-full text-xs font-medium"
style={{
backgroundColor: "#DBEAFE",
color: "#1E3A5F",
}}
className="inline-flex items-center px-3 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-900"
>
{item.jam}
</span>
@@ -285,12 +279,14 @@ const SosialPage = () => {
{/* Pendidikan Section */}
<div
className="rounded-xl shadow-sm p-6"
style={cardStyle}
className={`rounded-xl shadow-sm p-6 ${
dark ? "bg-slate-800 border border-slate-800" : "bg-white border border-white"
}`}
>
<h3
className="text-lg font-semibold mb-4"
style={textStyle}
className={`text-lg font-semibold mb-4 ${
dark ? "text-white" : "text-gray-800"
}`}
>
Pendidikan
</h3>
@@ -298,17 +294,17 @@ const SosialPage = () => {
{educationStats.map((item, index) => (
<div
key={index}
className="flex items-center justify-between py-2"
style={{
borderBottom: `1px solid ${dark ? "#334155" : "#F3F4F6"}`,
}}
className={`flex items-center justify-between py-2 ${
dark ? "border-b border-slate-700" : "border-b border-gray-100"
}`}
>
<span className="text-sm" style={subtitleStyle}>
<span className="text-sm" style={{ color: dark ? "#9CA3AF" : "#6B7280" }}>
{item.level}
</span>
<span
className="text-sm font-semibold"
style={textStyle}
className={`text-sm font-semibold ${
dark ? "text-white" : "text-gray-800"
}`}
>
{item.value}
</span>
@@ -318,8 +314,9 @@ const SosialPage = () => {
{/* Info Sekolah */}
<h4
className="text-base font-semibold mb-4"
style={textStyle}
className={`text-base font-semibold mb-4 ${
dark ? "text-white" : "text-gray-800"
}`}
>
Info Sekolah
</h4>
@@ -327,17 +324,17 @@ const SosialPage = () => {
{schoolInfo.map((item, index) => (
<div
key={index}
className="flex items-center justify-between py-3 px-4 rounded-lg"
style={{
backgroundColor: dark ? "#334155" : "#F9FAFB",
}}
className={`flex items-center justify-between py-3 px-4 rounded-lg ${
dark ? "bg-slate-700" : "bg-gray-50"
}`}
>
<span className="text-sm" style={subtitleStyle}>
<span className="text-sm" style={{ color: dark ? "#9CA3AF" : "#6B7280" }}>
{item.label}
</span>
<span
className="text-lg font-bold"
style={textStyle}
className={`text-lg font-bold ${
dark ? "text-white" : "text-gray-800"
}`}
>
{item.value}
</span>
@@ -348,22 +345,23 @@ const SosialPage = () => {
</div>
{/* Row 4: Beasiswa Desa & Kalender Event Budaya */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{/* Beasiswa Desa */}
<div
className="rounded-xl shadow-sm p-6"
style={cardStyle}
className={`rounded-xl shadow-sm p-6 ${
dark ? "bg-slate-800 border border-slate-800" : "bg-white border border-white"
}`}
>
<div className="flex items-center justify-between mb-6">
<h3
className="text-lg font-semibold"
style={textStyle}
className={`text-lg font-semibold ${
dark ? "text-white" : "text-gray-800"
}`}
>
Beasiswa Desa
</h3>
<div
className="w-12 h-12 rounded-full flex items-center justify-center text-white"
style={{ backgroundColor: "#22C55E" }}
className="w-12 h-12 rounded-full flex items-center justify-center text-white bg-green-500"
>
<IconAward size={24} />
</div>
@@ -372,39 +370,39 @@ const SosialPage = () => {
{/* Two centered metrics */}
<div className="grid grid-cols-2 gap-4 mb-6">
<div
className="p-4 rounded-lg text-center"
style={{
backgroundColor: dark ? "#334155" : "#F9FAFB",
}}
className={`p-4 rounded-lg text-center ${
dark ? "bg-slate-700" : "bg-gray-50"
}`}
>
<p
className="text-3xl font-bold mb-1"
style={textStyle}
className={`text-3xl font-bold mb-1 ${
dark ? "text-white" : "text-gray-800"
}`}
>
{scholarshipData.penerima}
</p>
<p
className="text-xs"
style={subtitleStyle}
className={`text-xs ${
dark ? "text-gray-400" : "text-gray-500"
}`}
>
Penerima Beasiswa
</p>
</div>
<div
className="p-4 rounded-lg text-center"
style={{
backgroundColor: dark ? "#334155" : "#F9FAFB",
}}
className={`p-4 rounded-lg text-center ${
dark ? "bg-slate-700" : "bg-gray-50"
}`}
>
<p
className="text-3xl font-bold mb-1"
style={{ color: "#22C55E" }}
className={`text-3xl font-bold mb-1 text-green-500`}
>
{scholarshipData.dana}
</p>
<p
className="text-xs"
style={subtitleStyle}
className={`text-xs ${
dark ? "text-gray-400" : "text-gray-500"
}`}
>
Dana Tersalurkan
</p>
@@ -413,8 +411,9 @@ const SosialPage = () => {
{/* Footer text */}
<p
className="text-center text-sm"
style={subtitleStyle}
className={`text-center text-sm ${
dark ? "text-gray-400" : "text-gray-500"
}`}
>
Tahun Ajaran {scholarshipData.tahunAjaran}
</p>
@@ -422,12 +421,14 @@ const SosialPage = () => {
{/* Kalender Event Budaya */}
<div
className="rounded-xl shadow-sm p-6"
style={cardStyle}
className={`rounded-xl shadow-sm p-6 ${
dark ? "bg-slate-800 border border-slate-800" : "bg-white border border-white"
}`}
>
<h3
className="text-lg font-semibold mb-4"
style={textStyle}
className={`text-lg font-semibold mb-4 ${
dark ? "text-white" : "text-gray-800"
}`}
>
Kalender Event Budaya
</h3>
@@ -435,36 +436,34 @@ const SosialPage = () => {
{culturalEvents.map((event, index) => (
<div
key={index}
className="flex items-start gap-3 p-4 rounded-lg"
style={{
backgroundColor: dark ? "#334155" : "#F9FAFB",
}}
className={`flex items-start gap-3 p-4 rounded-lg ${
dark ? "bg-slate-700" : "bg-gray-50"
}`}
>
<div
className="w-10 h-10 rounded-full flex items-center justify-center flex-shrink-0"
style={{
backgroundColor: "#DBEAFE",
color: "#1E3A5F",
}}
className="w-10 h-10 rounded-full flex items-center justify-center flex-shrink-0 bg-blue-100 text-blue-900"
>
<IconCalendarEvent size={20} />
</div>
<div className="flex-1">
<p
className="text-sm font-medium"
style={textStyle}
className={`text-sm font-medium ${
dark ? "text-white" : "text-gray-800"
}`}
>
{event.nama}
</p>
<p
className="text-xs mt-1"
style={subtitleStyle}
className={`text-xs mt-1 ${
dark ? "text-gray-400" : "text-gray-500"
}`}
>
{event.tanggal}
</p>
<p
className="text-xs mt-1"
style={subtitleStyle}
className={`text-xs mt-1 ${
dark ? "text-gray-400" : "text-gray-500"
}`}
>
Location: {event.lokasi}
</p>