tukar nama MB Ipoh Perak kepada MBIP

This commit is contained in:
Saufi
2026-05-19 20:47:08 +08:00
parent 2642d0cb7c
commit 201595912f
9 changed files with 907 additions and 11 deletions

Binary file not shown.

722
manual/generate_manual.py Normal file
View File

@@ -0,0 +1,722 @@
"""
Penjana Manual Pengguna eCert MBIP
Format: Microsoft Word (.docx)
"""
from docx import Document
from docx.shared import Pt, Cm, RGBColor, Inches
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT
from docx.oxml.ns import qn
from docx.oxml import OxmlElement
import datetime
BASE_URL = "https://mysijil.mbip.my"
doc = Document()
# ── Margin halaman ────────────────────────────────────────────────────────────
for section in doc.sections:
section.top_margin = Cm(2.5)
section.bottom_margin = Cm(2.5)
section.left_margin = Cm(3.0)
section.right_margin = Cm(2.5)
# ── Helpers ───────────────────────────────────────────────────────────────────
def add_heading(text, level=1):
h = doc.add_heading(text, level=level)
h.runs[0].font.color.rgb = RGBColor(0x1a, 0x3a, 0x6b)
return h
def add_body(text):
p = doc.add_paragraph(text)
p.runs[0].font.size = Pt(11)
return p
def add_bullet(text):
p = doc.add_paragraph(text, style='List Bullet')
p.runs[0].font.size = Pt(11)
return p
def add_screenshot_box(caption, url, height_cm=7):
"""Kotak placeholder untuk tangkapan skrin."""
doc.add_paragraph()
# Jadual satu sel sebagai kotak
tbl = doc.add_table(rows=1, cols=1)
tbl.alignment = WD_TABLE_ALIGNMENT.CENTER
cell = tbl.cell(0, 0)
# Warna latar
tc = cell._tc
tcPr = tc.get_or_add_tcPr()
shd = OxmlElement('w:shd')
shd.set(qn('w:val'), 'clear')
shd.set(qn('w:color'), 'auto')
shd.set(qn('w:fill'), 'EEF2FF')
tcPr.append(shd)
# Tinggi sel
trPr = tbl.rows[0]._tr.get_or_add_trPr()
trHeight = OxmlElement('w:trHeight')
trHeight.set(qn('w:val'), str(int(height_cm * 567)))
trHeight.set(qn('w:hRule'), 'exact')
trPr.append(trHeight)
# Teks dalam kotak
p = cell.paragraphs[0]
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = p.add_run(f"\n\n[ TANGKAPAN SKRIN ]\n\n{caption}")
run.font.size = Pt(10)
run.font.color.rgb = RGBColor(0x64, 0x74, 0x8B)
run.font.italic = True
# Label URL
p2 = doc.add_paragraph()
p2.alignment = WD_ALIGN_PARAGRAPH.CENTER
run2 = p2.add_run(f"URL: {url}")
run2.font.size = Pt(9)
run2.font.color.rgb = RGBColor(0x1a, 0x56, 0xa0)
run2.font.italic = True
doc.add_paragraph()
def add_note(text):
p = doc.add_paragraph()
p.add_run("Nota: ").bold = True
run = p.add_run(text)
run.font.size = Pt(10)
run.font.italic = True
p.paragraph_format.left_indent = Cm(0.5)
def page_break():
doc.add_page_break()
# ═══════════════════════════════════════════════════════════════════════════════
# HALAMAN TAJUK
# ═══════════════════════════════════════════════════════════════════════════════
doc.add_paragraph()
doc.add_paragraph()
doc.add_paragraph()
t = doc.add_paragraph("eCert MBIP")
t.alignment = WD_ALIGN_PARAGRAPH.CENTER
r = t.runs[0]
r.font.size = Pt(32)
r.font.bold = True
r.font.color.rgb = RGBColor(0x1a, 0x3a, 0x6b)
t2 = doc.add_paragraph("Sistem Pengurusan Sijil Digital")
t2.alignment = WD_ALIGN_PARAGRAPH.CENTER
r2 = t2.runs[0]
r2.font.size = Pt(18)
r2.font.color.rgb = RGBColor(0x1a, 0x3a, 0x6b)
doc.add_paragraph()
t3 = doc.add_paragraph("MANUAL PENGGUNA — PENTADBIR")
t3.alignment = WD_ALIGN_PARAGRAPH.CENTER
r3 = t3.runs[0]
r3.font.size = Pt(16)
r3.font.bold = True
r3.font.color.rgb = RGBColor(0x55, 0x55, 0x55)
doc.add_paragraph()
doc.add_paragraph()
t4 = doc.add_paragraph("Majlis Bandaraya Ipoh Perak (MBIP)")
t4.alignment = WD_ALIGN_PARAGRAPH.CENTER
t4.runs[0].font.size = Pt(12)
t5 = doc.add_paragraph(f"Versi 1.0 · {datetime.date.today().strftime('%B %Y')}")
t5.alignment = WD_ALIGN_PARAGRAPH.CENTER
t5.runs[0].font.size = Pt(11)
t5.runs[0].font.color.rgb = RGBColor(0x88, 0x88, 0x88)
page_break()
# ═══════════════════════════════════════════════════════════════════════════════
# ISI KANDUNGAN (placeholder manual)
# ═══════════════════════════════════════════════════════════════════════════════
add_heading("Isi Kandungan", level=1)
toc_items = [
("1", "Pengenalan"),
("2", "Log Masuk ke Sistem"),
("3", "Dashboard Utama"),
("4", "Pengurusan Program"),
(" 4.1", "Cipta Program Baru"),
(" 4.2", "Kemaskini Maklumat Program"),
(" 4.3", "Tetapan Check-in dan Muat Turun"),
(" 4.4", "Publish dan Tutup Program"),
("5", "Pengurusan Peserta"),
(" 5.1", "Lihat Senarai Peserta"),
(" 5.2", "Tambah Peserta Satu-Satu"),
(" 5.3", "Import Peserta dari Excel"),
(" 5.4", "Export Senarai Peserta"),
("6", "Kod QR Check-in"),
("7", "Template Sijil"),
(" 7.1", "Muat Naik Template"),
(" 7.2", "Konfigurasi Kedudukan Teks"),
(" 7.3", "Jana Pratonton Sijil"),
("8", "Soalselidik Program"),
("9", "Pengurusan Sijil"),
("10", "Statistik Program"),
("11", "Set Soalselidik"),
(" 11.1", "Cipta Set Soalselidik"),
(" 11.2", "Tambah dan Urus Soalan"),
("12", "Pengurusan Pengguna (Super Admin)"),
("13", "Profil Pengguna"),
]
for num, title in toc_items:
p = doc.add_paragraph()
p.paragraph_format.left_indent = Cm(0.5) if num.startswith(" ") else Cm(0)
r = p.add_run(f"{num.strip()} {title}")
r.font.size = Pt(11)
page_break()
# ═══════════════════════════════════════════════════════════════════════════════
# BAB 1: PENGENALAN
# ═══════════════════════════════════════════════════════════════════════════════
add_heading("1. Pengenalan")
add_body(
"eCert MBIP ialah sistem pengurusan sijil digital yang dibangunkan untuk Majlis Bandaraya Ipoh Perak (MBIP). "
"Sistem ini membolehkan pentadbir mengurus program, menguruskan peserta, menjana sijil digital secara automatik, "
"dan mengumpul maklum balas peserta melalui soalselidik dalam talian."
)
doc.add_paragraph()
add_body("Fungsi utama sistem:")
add_bullet("Pengurusan program dan peserta")
add_bullet("Check-in peserta melalui kod QR")
add_bullet("Jana dan hantar sijil digital secara automatik")
add_bullet("Pengurusan template sijil")
add_bullet("Kutipan maklum balas melalui soalselidik")
add_bullet("Laporan statistik kehadiran dan penyertaan")
doc.add_paragraph()
add_body("Manual ini ditujukan kepada pentadbir sistem (Admin dan Super Admin) untuk menggunakan semua fungsi yang tersedia.")
page_break()
# ═══════════════════════════════════════════════════════════════════════════════
# BAB 2: LOG MASUK
# ═══════════════════════════════════════════════════════════════════════════════
add_heading("2. Log Masuk ke Sistem")
add_body("Untuk mengakses sistem eCert MBIP, pentadbir perlu log masuk menggunakan alamat emel dan kata laluan yang telah diberikan.")
doc.add_paragraph()
add_body("Langkah-langkah log masuk:")
add_bullet(f"Buka pelayar web dan pergi ke: {BASE_URL}/login")
add_bullet("Masukkan Alamat Emel yang berdaftar.")
add_bullet("Masukkan Kata Laluan.")
add_bullet("Klik butang Log Masuk.")
doc.add_paragraph()
add_screenshot_box(
"Halaman Log Masuk — Borang emel dan kata laluan",
f"{BASE_URL}/login"
)
add_note(
"Jika terlupa kata laluan, klik pautan 'Terlupa Kata Laluan?' di bawah borang log masuk. "
"Pautan set semula kata laluan akan dihantar ke alamat emel yang didaftarkan."
)
page_break()
# ═══════════════════════════════════════════════════════════════════════════════
# BAB 3: DASHBOARD
# ═══════════════════════════════════════════════════════════════════════════════
add_heading("3. Dashboard Utama")
add_body(
"Selepas log masuk, pentadbir akan dibawa ke halaman Dashboard. Dashboard memaparkan ringkasan aktiviti sistem "
"termasuk jumlah program aktif, jumlah peserta, dan sijil yang dijana."
)
doc.add_paragraph()
add_body("Elemen pada Dashboard:")
add_bullet("Jumlah program yang sedang aktif")
add_bullet("Senarai program terkini")
add_bullet("Pautan pantas ke fungsi utama")
add_screenshot_box(
"Dashboard Utama — Ringkasan statistik dan senarai program",
f"{BASE_URL}/admin/dashboard"
)
add_body("Bar navigasi di sebelah kiri (sidebar) menyediakan akses pantas ke semua modul sistem.")
page_break()
# ═══════════════════════════════════════════════════════════════════════════════
# BAB 4: PENGURUSAN PROGRAM
# ═══════════════════════════════════════════════════════════════════════════════
add_heading("4. Pengurusan Program")
add_body(
"Modul Program adalah teras sistem eCert MBIP. Setiap program mewakili satu acara atau kursus yang dianjurkan. "
"Pentadbir boleh mencipta, mengemaskini, dan mengurus status program dari modul ini."
)
add_screenshot_box(
"Senarai Program — Semua program yang telah dicipta",
f"{BASE_URL}/admin/programs"
)
# 4.1
add_heading("4.1 Cipta Program Baru", level=2)
add_body("Langkah-langkah mencipta program baru:")
add_bullet("Klik butang + Cipta Program di halaman Senarai Program.")
add_bullet("Isi maklumat program:")
fields_program = [
("Tajuk Program", "Nama program atau acara (wajib)"),
("Penerangan", "Huraian ringkas program"),
("Tarikh Mula / Tamat", "Tarikh pelaksanaan program"),
("Lokasi", "Tempat program diadakan"),
("Benarkan Walk-in", "Aktifkan jika peserta luar dibenarkan daftar semasa check-in"),
]
for field, desc in fields_program:
p = doc.add_paragraph()
p.paragraph_format.left_indent = Cm(1)
r1 = p.add_run(f"{field}: ")
r1.bold = True
r1.font.size = Pt(11)
p.add_run(desc).font.size = Pt(11)
add_bullet("Klik Simpan untuk menyimpan program.")
add_screenshot_box(
"Borang Cipta Program Baru — Isi maklumat program",
f"{BASE_URL}/admin/programs/create"
)
# 4.2
add_heading("4.2 Kemaskini Maklumat Program", level=2)
add_body(
"Untuk mengedit program sedia ada, klik ikon Edit (pensel) pada senarai program atau klik nama program "
"kemudian pilih tab Butiran."
)
add_screenshot_box(
"Halaman Butiran Program — Tab maklumat, peserta, template, soalselidik, sijil",
f"{BASE_URL}/admin/programs/{{uuid}}"
)
# 4.3
add_heading("4.3 Tetapan Check-in dan Muat Turun", level=2)
add_body("Pentadbir perlu menetapkan waktu check-in dan tempoh muat turun sijil dalam tetapan program:")
settings_table = [
("Mula Check-in", "Tarikh dan masa check-in dibuka untuk peserta"),
("Tamat Check-in", "Tarikh dan masa check-in ditutup"),
("Mula Muat Turun Sijil", "Peserta boleh muat turun sijil selepas tempoh ini"),
("Tamat Muat Turun Sijil", "Tempoh muat turun sijil tamat"),
]
for field, desc in settings_table:
p = doc.add_paragraph()
p.paragraph_format.left_indent = Cm(1)
r1 = p.add_run(f"{field}: ")
r1.bold = True
r1.font.size = Pt(11)
p.add_run(desc).font.size = Pt(11)
add_note("Semua masa menggunakan waktu Malaysia (MYT, UTC+8).")
# 4.4
add_heading("4.4 Publish dan Tutup Program", level=2)
add_body("Program perlu di-publish sebelum peserta dapat menggunakan pautan check-in QR.")
add_bullet("Klik butang Publish untuk mengaktifkan program. Status bertukar kepada Aktif.")
add_bullet("Klik butang Tutup untuk menamatkan program. Peserta tidak lagi dapat check-in.")
add_note("Program yang telah ditutup tidak boleh dibuka semula secara automatik.")
page_break()
# ═══════════════════════════════════════════════════════════════════════════════
# BAB 5: PENGURUSAN PESERTA
# ═══════════════════════════════════════════════════════════════════════════════
add_heading("5. Pengurusan Peserta")
add_body("Modul Peserta membolehkan pentadbir mengurus senarai peserta bagi setiap program.")
# 5.1
add_heading("5.1 Lihat Senarai Peserta", level=2)
add_body("Klik tab Peserta dalam halaman butiran program untuk melihat semua peserta berdaftar.")
add_body("Maklumat yang dipaparkan:")
add_bullet("Nama peserta")
add_bullet("No. Kad Pengenalan")
add_bullet("Status check-in (Hadir / Belum Hadir)")
add_bullet("Status sijil (Belum Jana / Dijana / Dihantar)")
add_bullet("Sumber pendaftaran (Pra-daftar / Walk-in)")
add_screenshot_box(
"Senarai Peserta — Status kehadiran dan sijil setiap peserta",
f"{BASE_URL}/admin/programs/{{uuid}}/participants"
)
# 5.2
add_heading("5.2 Tambah Peserta Satu-Satu", level=2)
add_body("Untuk menambah peserta secara manual:")
add_bullet("Klik butang + Tambah Peserta.")
add_bullet("Isi Nama Penuh dan No. Kad Pengenalan (12 digit).")
add_bullet("Isi maklumat tambahan jika perlu (emel, telefon, agensi).")
add_bullet("Klik Simpan.")
add_screenshot_box(
"Borang Tambah Peserta — Isi maklumat peserta",
f"{BASE_URL}/admin/programs/{{uuid}}/participants/create"
)
# 5.3
add_heading("5.3 Import Peserta dari Excel", level=2)
add_body("Untuk mendaftar ramai peserta sekaligus:")
add_bullet("Klik butang Import Excel.")
add_bullet("Muat turun templat Excel yang disediakan.")
add_bullet("Isi maklumat peserta dalam templat (Nama, No. KP, Emel, Telefon, Agensi).")
add_bullet("Muat naik semula fail Excel yang telah diisi.")
add_bullet("Semak ringkasan import dan klik Sahkan.")
add_screenshot_box(
"Halaman Import Peserta — Muat naik fail Excel",
f"{BASE_URL}/admin/programs/{{uuid}}/participants/import"
)
add_note("Sistem akan abaikan baris yang No. KP-nya sudah wujud dalam program yang sama.")
# 5.4
add_heading("5.4 Export Senarai Peserta", level=2)
add_body("Klik butang Export Excel untuk memuat turun senarai lengkap peserta beserta status check-in dan sijil ke dalam fail Excel.")
page_break()
# ═══════════════════════════════════════════════════════════════════════════════
# BAB 6: KOD QR CHECK-IN
# ═══════════════════════════════════════════════════════════════════════════════
add_heading("6. Kod QR Check-in")
add_body(
"Setiap program mempunyai Kod QR unik yang digunakan peserta untuk check-in. "
"Peserta mengimbas kod ini menggunakan telefon pintar untuk mendaftarkan kehadiran."
)
add_body("Cara menjana dan menggunakan Kod QR:")
add_bullet("Klik tab Kod QR dalam halaman butiran program.")
add_bullet("Klik Jana QR Code jika belum dijana.")
add_bullet("Paparkan Kod QR pada skrin besar atau cetak untuk peserta mengimbas.")
add_bullet("Klik Muat Turun untuk menyimpan imej Kod QR.")
add_screenshot_box(
"Halaman Kod QR — Jana, papar, dan muat turun QR Code",
f"{BASE_URL}/admin/programs/{{uuid}}/qr"
)
add_note(
"Kod QR boleh dinyahaktifkan (Deactivate) dan dijana semula jika diperlukan. "
"Kod lama tidak akan berfungsi selepas dinyahaktifkan."
)
page_break()
# ═══════════════════════════════════════════════════════════════════════════════
# BAB 7: TEMPLATE SIJIL
# ═══════════════════════════════════════════════════════════════════════════════
add_heading("7. Template Sijil")
add_body(
"Modul Template Sijil membolehkan pentadbir menyediakan reka bentuk sijil yang akan digunakan "
"untuk menjana sijil digital peserta."
)
# 7.1
add_heading("7.1 Muat Naik Template", level=2)
add_body("Langkah-langkah muat naik template sijil:")
add_bullet("Klik tab Template Sijil dalam halaman butiran program.")
add_bullet("Klik butang Pilih Fail dan pilih imej template (format JPG atau PNG, maksimum 10MB).")
add_bullet("Resolusi disyorkan: 1754 × 1240 piksel (A4 landscape) atau 1240 × 1754 piksel (portrait).")
add_bullet("Klik Muat Naik.")
add_screenshot_box(
"Halaman Muat Naik Template — Pilih fail imej sijil",
f"{BASE_URL}/admin/programs/{{uuid}}/template"
)
# 7.2
add_heading("7.2 Konfigurasi Kedudukan Teks", level=2)
add_body(
"Selepas template dimuat naik, pentadbir perlu menetapkan kedudukan teks pada sijil. "
"Koordinat dikira dari sudut kiri atas imej (piksel)."
)
add_body("Medan yang boleh dikonfigurasi:")
config_fields = [
("Nama Peserta", "Kedudukan X, Y, saiz font, warna, dan penjajaran (kiri/tengah/kanan)"),
("No. IC", "Saiz font No. IC yang dipaparkan di bawah nama"),
("No. Sijil (Pilihan)", "Aktifkan togol 'Papar' untuk menambah No. Sijil pada sijil. Tetapkan kedudukan X, Y."),
]
for field, desc in config_fields:
p = doc.add_paragraph()
p.paragraph_format.left_indent = Cm(1)
r1 = p.add_run(f"{field}: ")
r1.bold = True
r1.font.size = Pt(11)
p.add_run(desc).font.size = Pt(11)
add_bullet("Klik Simpan Konfigurasi untuk menyimpan tetapan.")
add_screenshot_box(
"Konfigurasi Template — Tetapkan kedudukan teks nama dan No. Sijil",
f"{BASE_URL}/admin/programs/{{uuid}}/template"
)
# 7.3
add_heading("7.3 Jana Pratonton Sijil", level=2)
add_body("Untuk menyemak kedudukan teks sebelum menjana sijil sebenar:")
add_bullet("Masukkan nama contoh dalam kotak Jana Pratonton.")
add_bullet("Klik butang Pratonton.")
add_bullet("Imej pratonton akan dipaparkan dengan teks pada koordinat yang ditetapkan.")
add_note("Pratonton menggunakan nilai koordinat terkini walaupun belum disimpan.")
page_break()
# ═══════════════════════════════════════════════════════════════════════════════
# BAB 8: SOALSELIDIK PROGRAM
# ═══════════════════════════════════════════════════════════════════════════════
add_heading("8. Soalselidik Program")
add_body(
"Pentadbir boleh mengaitkan set soalselidik dengan program. Peserta akan diminta mengisi soalselidik "
"selepas check-in sebelum sijil boleh dimuat turun."
)
add_body("Cara mengaitkan soalselidik dengan program:")
add_bullet("Klik tab Soalselidik dalam halaman butiran program.")
add_bullet("Pilih Set Soalselidik yang ingin digunakan daripada senarai tersedia.")
add_bullet("Klik Lampirkan Soalselidik.")
add_bullet("Klik Sahkan untuk mengesahkan penggunaan soalselidik ini.")
add_bullet("Klik Pratonton untuk melihat soalan yang akan dijawab peserta.")
add_screenshot_box(
"Halaman Soalselidik Program — Lampirkan dan pratonton soalselidik",
f"{BASE_URL}/admin/programs/{{uuid}}/questionnaire"
)
add_note("Soalselidik yang telah disahkan tidak boleh ditukar. Sah kan hanya apabila sudah pasti.")
page_break()
# ═══════════════════════════════════════════════════════════════════════════════
# BAB 9: PENGURUSAN SIJIL
# ═══════════════════════════════════════════════════════════════════════════════
add_heading("9. Pengurusan Sijil")
add_body(
"Modul Sijil membolehkan pentadbir menjana dan menghantar sijil digital kepada semua peserta yang hadir."
)
add_body("Fungsi yang tersedia:")
add_bullet("Jana Semua Sijil — Menjana sijil untuk semua peserta yang telah check-in.")
add_bullet("Hantar Emel Semua — Menghantar sijil kepada peserta melalui emel secara pukal.")
add_body("Status sijil setiap peserta:")
status_sijil = [
("Belum Jana", "Sijil belum dijana untuk peserta ini"),
("Dijana", "Sijil sudah dijana dan sedia untuk dihantar"),
("Dihantar", "Sijil telah dihantar melalui emel"),
("Dimuat Turun", "Peserta telah memuat turun sijil mereka"),
]
for status, desc in status_sijil:
p = doc.add_paragraph()
p.paragraph_format.left_indent = Cm(1)
r1 = p.add_run(f"{status}: ")
r1.bold = True
r1.font.size = Pt(11)
p.add_run(desc).font.size = Pt(11)
add_screenshot_box(
"Halaman Sijil — Senarai sijil dan fungsi jana/hantar pukal",
f"{BASE_URL}/admin/programs/{{uuid}}/certificates"
)
add_note("Pastikan template sijil telah dikonfigurasi terlebih dahulu sebelum menjana sijil.")
page_break()
# ═══════════════════════════════════════════════════════════════════════════════
# BAB 10: STATISTIK PROGRAM
# ═══════════════════════════════════════════════════════════════════════════════
add_heading("10. Statistik Program")
add_body(
"Halaman Statistik memaparkan data analitik terperinci bagi setiap program. "
"Pentadbir boleh memantau prestasi program melalui laporan yang disediakan."
)
add_body("Data yang dipaparkan:")
add_bullet("Jumlah peserta berdaftar vs. jumlah yang hadir")
add_bullet("Pecahan mengikut sesi (Slot masa check-in)")
add_bullet("Pecahan mengikut sumber pendaftaran (Pra-daftar / Walk-in)")
add_bullet("Status sijil (Dijana, Dihantar, Dimuat Turun)")
add_bullet("Keputusan soalselidik (jika soalselidik dikaitkan)")
add_screenshot_box(
"Halaman Statistik — Graf dan data analitik program",
f"{BASE_URL}/admin/programs/{{uuid}}/statistics"
)
add_body("Klik butang Export Excel untuk memuat turun laporan statistik dalam format Excel.")
page_break()
# ═══════════════════════════════════════════════════════════════════════════════
# BAB 11: SET SOALSELIDIK
# ═══════════════════════════════════════════════════════════════════════════════
add_heading("11. Set Soalselidik")
add_body(
"Modul Set Soalselidik membolehkan pentadbir membina borang soalan yang boleh digunakan semula "
"merentasi pelbagai program."
)
add_screenshot_box(
"Senarai Set Soalselidik — Semua set yang telah dicipta",
f"{BASE_URL}/admin/questionnaires"
)
# 11.1
add_heading("11.1 Cipta Set Soalselidik", level=2)
add_body("Langkah-langkah mencipta set soalselidik baru:")
add_bullet("Klik butang + Cipta Set Soalselidik.")
add_bullet("Masukkan Nama Set dan Penerangan (pilihan).")
add_bullet("Klik Simpan.")
add_screenshot_box(
"Borang Cipta Set Soalselidik — Nama dan penerangan",
f"{BASE_URL}/admin/questionnaires/create"
)
# 11.2
add_heading("11.2 Tambah dan Urus Soalan", level=2)
add_body("Selepas set dicipta, tambah soalan melalui halaman butiran set soalselidik.")
add_body("Jenis soalan yang tersedia:")
jenis_soalan = [
("Tajuk (Seksyen)", "Pengepala bahagian — boleh menjadi parent kepada soalan Rating"),
("Rating (1-5)", "Penilaian skala 1 hingga 5 — mesti diletakkan di bawah Tajuk"),
("Pilihan Tunggal", "Peserta pilih satu jawapan sahaja"),
("Pilihan Berganda", "Peserta boleh pilih lebih dari satu jawapan"),
("Teks Pendek", "Jawapan dalam satu baris"),
("Teks Panjang", "Jawapan berbilang baris"),
]
for jenis, desc in jenis_soalan:
p = doc.add_paragraph()
p.paragraph_format.left_indent = Cm(1)
r1 = p.add_run(f"{jenis}: ")
r1.bold = True
r1.font.size = Pt(11)
p.add_run(desc).font.size = Pt(11)
add_screenshot_box(
"Halaman Set Soalselidik — Senarai soalan dan borang tambah soalan",
f"{BASE_URL}/admin/questionnaires/{{id}}"
)
add_body("Ciri-ciri tambahan:")
add_bullet("Soalan Rating: Pentadbir boleh tetapkan label teks untuk setiap nilai (1-5) pada peringkat Tajuk.")
add_bullet("Susunan soalan boleh diubah dengan seret-dan-lepas (drag-and-drop).")
add_bullet("Soalan Rating tidak boleh dipindahkan keluar dari Tajuk induknya.")
add_bullet("Tetapkan soalan sebagai Wajib atau tidak wajib.")
add_note(
"Set soalselidik perlu di-Publish sebelum boleh dikaitkan dengan program. "
"Selepas di-Publish, soalan tidak boleh diubah."
)
page_break()
# ═══════════════════════════════════════════════════════════════════════════════
# BAB 12: PENGURUSAN PENGGUNA (SUPER ADMIN)
# ═══════════════════════════════════════════════════════════════════════════════
add_heading("12. Pengurusan Pengguna")
add_body(
"Modul ini hanya boleh diakses oleh Super Admin. "
"Super Admin boleh mencipta dan mengurus akaun pentadbir lain dalam sistem."
)
add_body("Fungsi yang tersedia:")
add_bullet("Lihat senarai semua pentadbir")
add_bullet("Cipta akaun pentadbir baru")
add_bullet("Kemaskini maklumat pentadbir")
add_bullet("Padam akaun pentadbir")
add_screenshot_box(
"Halaman Pengurusan Pengguna — Senarai pentadbir (Super Admin sahaja)",
f"{BASE_URL}/admin/users"
)
add_body("Jenis peranan pengguna:")
add_bullet("Super Admin — Akses penuh termasuk Pengurusan Pengguna")
add_bullet("Admin Program — Akses kepada semua program dan soalselidik, kecuali Pengurusan Pengguna")
add_note("Setiap sistem perlu sekurang-kurangnya satu akaun Super Admin yang aktif.")
page_break()
# ═══════════════════════════════════════════════════════════════════════════════
# BAB 13: PROFIL PENGGUNA
# ═══════════════════════════════════════════════════════════════════════════════
add_heading("13. Profil Pengguna")
add_body(
"Setiap pentadbir boleh mengurus maklumat akaun peribadi mereka melalui halaman Profil. "
"Klik nama pengguna atau butang Profil di bar navigasi kiri untuk mengakses halaman ini."
)
add_body("Fungsi yang tersedia:")
add_heading("Tukar Alamat Emel", level=2)
add_bullet("Masukkan Kata Laluan Semasa untuk pengesahan.")
add_bullet("Masukkan Emel Baru.")
add_bullet("Klik Kemaskini Emel.")
add_heading("Tukar Kata Laluan", level=2)
add_bullet("Masukkan Kata Laluan Semasa.")
add_bullet("Masukkan Kata Laluan Baru (minimum 8 aksara).")
add_bullet("Masukkan semula Kata Laluan Baru untuk pengesahan.")
add_bullet("Klik Tukar Kata Laluan.")
add_screenshot_box(
"Halaman Profil — Tukar emel dan kata laluan",
f"{BASE_URL}/admin/profile"
)
add_note("Kata laluan baru mestilah sekurang-kurangnya 8 aksara. Simpan kata laluan di tempat yang selamat.")
page_break()
# ═══════════════════════════════════════════════════════════════════════════════
# LAMPIRAN: ALIRAN KERJA SISTEM
# ═══════════════════════════════════════════════════════════════════════════════
add_heading("Lampiran: Aliran Kerja Tipikal")
add_body("Berikut adalah urutan langkah yang disyorkan untuk menjalankan sebuah program dari mula hingga selesai:")
workflow = [
("1", "Cipta Set Soalselidik", "Bina soalan maklum balas di Modul Set Soalselidik dan publish."),
("2", "Cipta Program", "Isi maklumat program, tarikh, dan tetapan check-in."),
("3", "Import Peserta", "Muat naik senarai peserta melalui Excel."),
("4", "Muat Naik Template Sijil", "Upload reka bentuk sijil dan konfigurasi kedudukan teks."),
("5", "Lampirkan Soalselidik", "Kaitkan set soalselidik dengan program dan sahkan."),
("6", "Publish Program", "Aktifkan program supaya peserta boleh check-in."),
("7", "Jana & Papar Kod QR", "Paparkan QR Code semasa acara untuk peserta mengimbas."),
("8", "Pantau Statistik", "Semak kehadiran dan maklum balas dalam masa nyata."),
("9", "Jana dan Hantar Sijil", "Selepas program tamat, jana sijil dan hantar melalui emel."),
]
tbl = doc.add_table(rows=1, cols=3)
tbl.style = 'Table Grid'
hdr = tbl.rows[0].cells
hdr[0].text = "Langkah"
hdr[1].text = "Tindakan"
hdr[2].text = "Penerangan"
for cell in hdr:
cell.paragraphs[0].runs[0].bold = True
cell.paragraphs[0].runs[0].font.size = Pt(10)
for step, action, desc in workflow:
row = tbl.add_row().cells
row[0].text = step
row[1].text = action
row[2].text = desc
for cell in row:
cell.paragraphs[0].runs[0].font.size = Pt(10)
doc.add_paragraph()
add_body(f"Untuk sokongan teknikal, hubungi pentadbir sistem atau lawati: {BASE_URL}")
# ── Simpan dokumen ─────────────────────────────────────────────────────────────
output_path = r"C:\Users\User\Aplikasi\ecert\manual\Manual_Pengguna_eCert_MBIP.docx"
doc.save(output_path)
print(f"Manual berjaya dijana: {output_path}")

Binary file not shown.