434 lines
31 KiB
XML
434 lines
31 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
||
<odoo>
|
||
<!-- =======================================================
|
||
TEMPLATE: List of CPP Entries
|
||
======================================================= -->
|
||
<template id="portal_my_cpp_entries" name="My CPP Entries">
|
||
<t t-call="portal.portal_layout">
|
||
<div class="container mt-4 khmer-text">
|
||
<!-- Error Alert -->
|
||
<t t-if="error">
|
||
<div class="alert alert-danger alert-dismissible fade show">
|
||
<i class="fa fa-exclamation-triangle me-2"/>
|
||
<strong>Error:</strong> <t t-esc="error"/>
|
||
<button type="button" class="btn-close" data-bs-dismiss="alert"/>
|
||
</div>
|
||
</t>
|
||
|
||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||
<h2><i class="fa fa-list-alt me-2"/>បញ្ជី</h2>
|
||
<a href="/my/cpp_entries/new" class="btn btn-primary">
|
||
<i class="fa fa-plus me-1"/>បង្កើតថ្មី
|
||
</a>
|
||
</div>
|
||
|
||
<t t-if="entries">
|
||
<div class="table-responsive">
|
||
<table class="table table-hover align-middle">
|
||
<thead class="table-light">
|
||
<tr>
|
||
<th>ថ្ងៃបង្កើត</th>
|
||
<th>រាជធានី/ខេត្ដ</th>
|
||
<th>ស្រុក/ខណ្ឌ</th>
|
||
<th>ឃុំ/សង្កាត់</th>
|
||
<th>ការិយាល័យបោះឆ្នោត</th>
|
||
<th class="text-center">អ្នកបោះឆ្នោត</th>
|
||
<th class="text-center">មិនទាន់បោះឆ្នោត</th>
|
||
<th class="text-end">សកម្មភាព</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<t t-foreach="entries" t-as="entry">
|
||
<tr>
|
||
<td><t t-esc="entry.create_date.strftime('%d/%m/%Y') if entry.create_date else '-'"/></td>
|
||
<td><t t-esc="entry.province_id.location_name or '-'"/></td>
|
||
<td><t t-esc="entry.district_id.location_name or '-'"/></td>
|
||
<td><t t-esc="entry.commune_id.location_name or '-'"/></td>
|
||
<td><t t-esc="entry.al_office or '-'"/></td>
|
||
<td class="text-center"><span class="badge bg-success"><t t-esc="entry.voter_count or 0"/></span></td>
|
||
<td class="text-center"><span class="badge bg-warning text-dark"><t t-esc="entry.non_voter_count or 0"/></span></td>
|
||
<td class="text-end">
|
||
<a t-attf-href="/my/cpp_entries/#{entry.id}" class="btn btn-sm btn-outline-primary">
|
||
<i class="fa fa-eye"/> មើល
|
||
</a>
|
||
</td>
|
||
</tr>
|
||
</t>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</t>
|
||
<t t-else="">
|
||
<div class="alert alert-info text-center">
|
||
<i class="fa fa-info-circle me-2"/>
|
||
មិនទាន់មានទិន្នន័យ។ <a href="/my/cpp_entries/new">ចុចទីនេះ</a> ដើម្បីបង្កើតថ្មី។
|
||
</div>
|
||
</t>
|
||
</div>
|
||
</t>
|
||
</template>
|
||
|
||
<!-- =======================================================
|
||
TEMPLATE: Main CPP Entry Form
|
||
======================================================= -->
|
||
<template id="portal_cpp_form" name="CPP Entry Form">
|
||
<t t-call="portal.portal_layout">
|
||
<div class="container mt-4 o_portal_cpp_form">
|
||
<!-- Error Alert -->
|
||
<t t-if="error">
|
||
<div class="alert alert-danger alert-dismissible fade show">
|
||
<i class="fa fa-exclamation-triangle me-2"/>
|
||
<strong>Error:</strong> <t t-esc="error"/>
|
||
<button type="button" class="btn-close" data-bs-dismiss="alert"/>
|
||
</div>
|
||
</t>
|
||
|
||
<h2 class="mb-4 text-primary">
|
||
<i class="fa fa-edit me-2"/>
|
||
<t t-if="entry.id">កែបញ្ជីឈ្មោះ</t>
|
||
<t t-else="">បង្កើតបញ្ជីឈ្មោះថ្មី</t>
|
||
</h2>
|
||
|
||
<form t-attf-action="/my/cpp_entries/submit" method="post" class="bg-white p-4 rounded shadow-sm border">
|
||
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
|
||
<input type="hidden" name="entry_id" t-att-value="entry.id or 0"/>
|
||
|
||
<!-- Location Section -->
|
||
<div class="row mb-4 p-3 bg-light rounded">
|
||
<div class="col-12 mb-2"><h5 class="fw-bold text-secondary">📍 ព័ត៌មានទីតាំង</h5></div>
|
||
<!-- Province -->
|
||
<div class="col-md-4 mb-3">
|
||
<label class="form-label fw-bold">រាជធានី/ខេត្ដ <span class="text-danger">*</span></label>
|
||
<select name="province_id" class="form-select" required="1" id="province_select">
|
||
<option value="">-- ជ្រើសរើសរាជធានី/ខេត្ដ --</option>
|
||
<t t-foreach="provinces" t-as="prov">
|
||
<option t-att-value="prov.id" t-att-selected="entry.province_id.id == prov.id">
|
||
<t t-esc="prov.location_name"/>
|
||
</option>
|
||
</t>
|
||
</select>
|
||
</div>
|
||
|
||
<!-- District -->
|
||
<div class="col-md-4 mb-3">
|
||
<label class="form-label fw-bold">ស្រុក/ខណ្ឌ</label>
|
||
<select name="district_id" class="form-select" id="district_select">
|
||
<option value="">-- ជ្រើសរើសស្រុក/ខណ្ឌ --</option>
|
||
<t t-if="entry.district_id">
|
||
<option t-att-value="entry.district_id.id" selected="selected">
|
||
<t t-esc="entry.district_id.location_name"/>
|
||
</option>
|
||
</t>
|
||
</select>
|
||
</div>
|
||
|
||
<!-- Commune -->
|
||
<div class="col-md-4 mb-3">
|
||
<label class="form-label fw-bold">ឃុំ/សង្កាត់</label>
|
||
<select name="commune_id" class="form-select" id="commune_select">
|
||
<option value="">-- ជ្រើសរើសឃុំ/សង្កាត់ --</option>
|
||
<t t-if="entry.commune_id">
|
||
<option t-att-value="entry.commune_id.id" selected="selected">
|
||
<t t-esc="entry.commune_id.location_name"/>
|
||
</option>
|
||
</t>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-4 mb-3">
|
||
<label class="form-label fw-bold">លេខការិយាល័យ</label>
|
||
<input name="al_office" class="form-control form-control-lg" placeholder="លេខការិយាល័យ" t-att-value="entry.al_office or ''"/>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ✅ CONDITIONAL: Only show tables/buttons IF Entry is Saved -->
|
||
<t t-if="entry.id">
|
||
<!-- Table 1: Non-Voters List (Pink/Red) -->
|
||
<div class="card mb-4 border-danger">
|
||
<div class="card-header bg-danger text-white d-flex justify-content-between align-items-center">
|
||
<h5 class="mb-0">📋 បញ្ជីឈ្មោះអ្នកមិនទាន់បោះឆ្នោត</h5>
|
||
<span class="badge bg-light text-danger fs-6">
|
||
<t t-esc="len(entry.info_ids.filtered(lambda r: not r.status_vote))"/> នាក់
|
||
</span>
|
||
</div>
|
||
<div class="card-body p-0">
|
||
<div class="table-responsive">
|
||
<table class="table table-bordered table-striped mb-0 align-middle">
|
||
<thead class="table-light">
|
||
<tr>
|
||
<th style="width:5%" class="text-center">ល.រ.</th>
|
||
<th style="width:8%">ភេទ</th>
|
||
<th style="width:20%">ឈ្មោះ</th>
|
||
<th style="width:12%">ថ្ងៃកំណើត</th>
|
||
<th style="width:25%">អាសយដ្ឋាន</th>
|
||
<!-- <th style="width:10%" class="text-center">ទូរសព្ទ</th>-->
|
||
<th style="width:10%" class="text-center">ជាសមាជិក</th>
|
||
<th style="width:12%" class="text-center">ស្ថានភាព</th>
|
||
<th style="width:12%" class="text-center">សកម្មភាព</th>
|
||
<th style="width:8%" class="text-center">រូប</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<t t-if="entry.info_ids.filtered(lambda r: not r.status_vote)">
|
||
<t t-foreach="entry.info_ids.filtered(lambda r: not r.status_vote)" t-as="voter">
|
||
<tr>
|
||
<td class="text-center fw-bold"><t t-esc="voter_index + 1"/></td>
|
||
<td>
|
||
<span t-if="voter.gender" t-attf-class="badge bg-#{'info' if voter.gender.name == 'ប្រុស' else 'danger'}">
|
||
<t t-esc="voter.gender.name or '-'"/>
|
||
</span>
|
||
<span t-else="" class="text-muted">-</span>
|
||
</td>
|
||
<td class="fw-medium"><t t-esc="voter.name or '–'"/></td>
|
||
<td><t t-esc="voter.dob or '-'"/></td>
|
||
<td><t t-esc="voter.address or '-'"/></td>
|
||
<!-- <td class="text-center"><t t-esc="voter.phone or '-'"/></td>-->
|
||
<td><t t-esc="voter.cpp_member or '-'"/> </td>
|
||
<td class="text-center">
|
||
<span class="badge bg-warning text-dark">មិនទាន់បោះឆ្នោត</span>
|
||
</td>
|
||
<td class="text-center">
|
||
<!-- ✅ TOGGLE BUTTON: Mark as Voted -->
|
||
<a t-attf-href="/my/cpp_entries/voter/#{voter.id}/toggle_vote?csrf_token=#{request.csrf_token()}"
|
||
class="btn btn-sm btn-success py-0 me-1"
|
||
title="កំណត់ថាបានបោះឆ្នោត">
|
||
<i class="fa fa-check"/> បានបោះរួច
|
||
</a>
|
||
<a t-attf-href="/my/cpp_entries/voter/#{voter.id}/edit" class="btn btn-sm btn-outline-primary py-0 me-1"><i class="fa fa-pencil"/></a>
|
||
<!-- <a t-attf-href="/my/cpp_entries/voter/#{voter.id}/delete?csrf_token=#{request.csrf_token()}" class="btn btn-sm btn-outline-danger py-0" onclick="return confirm('តើអ្នកពិតជាចង់លុកឈ្មោះនេះមែនទេ?');"><i class="fa fa-trash"/></a>-->
|
||
</td>
|
||
<td class="text-center">
|
||
<t t-if="voter.photo">
|
||
<img t-att-src="image_data_uri(voter.photo)" class="rounded" style="width:40px;height:40px;object-fit:cover;" alt="Photo"/>
|
||
</t>
|
||
<t t-else=""><span class="text-muted small">–</span></t>
|
||
</td>
|
||
</tr>
|
||
</t>
|
||
</t>
|
||
<t t-else="">
|
||
<tr><td colspan="9" class="text-center text-muted py-4"><i class="fa fa-info-circle me-1"/> មិនទាន់មានទិន្នន័យ</td></tr>
|
||
</t>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
<div class="card-footer bg-white">
|
||
<a t-attf-href="/my/cpp_entries/voter/new?entry_id=#{entry.id}&status_vote=0" class="btn btn-success btn-sm">
|
||
<i class="fa fa-plus me-1"/> បន្ថែមអ្នកមិនទាន់បោះឆ្នោត
|
||
</a>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Table 2: Voters List (Green) -->
|
||
<div class="card mb-4 border-success">
|
||
<div class="card-header bg-success text-white d-flex justify-content-between align-items-center">
|
||
<h5 class="mb-0">✅ បញ្ជីឈ្មោះអនកបានបោះឆ្នោត</h5>
|
||
<span class="badge bg-light text-success fs-6">
|
||
<t t-esc="len(entry.info_ids.filtered(lambda r: r.status_vote))"/> នាក់
|
||
</span>
|
||
</div>
|
||
<div class="card-body p-0">
|
||
<div class="table-responsive">
|
||
<table class="table table-bordered table-striped mb-0 align-middle">
|
||
<thead class="table-light">
|
||
<tr>
|
||
<th style="width:5%" class="text-center">ល.រ.</th>
|
||
<th style="width:8%">ភេទ</th>
|
||
<th style="width:20%">ឈ្មោះ</th>
|
||
<th style="width:12%">ថ្ងៃកំណើត</th>
|
||
<th style="width:25%">អាសយដ្ឋាន</th>
|
||
<!-- <th style="width:10%" class="text-center">ទូរស័ព្ទ</th>-->
|
||
<th style="width:12%" class="text-center">ស្ថានភាព</th>
|
||
<th style="width:12%" class="text-center">សកម្មភាព</th>
|
||
<th style="width:8%" class="text-center">រូប</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<t t-if="entry.info_ids.filtered(lambda r: r.status_vote)">
|
||
<t t-foreach="entry.info_ids.filtered(lambda r: r.status_vote)" t-as="voter">
|
||
<tr>
|
||
<td class="text-center fw-bold"><t t-esc="voter_index + 1"/></td>
|
||
<td>
|
||
<span t-if="voter.gender" t-attf-class="badge bg-#{'info' if voter.gender.name == 'ប្រុស' else 'danger'}">
|
||
<t t-esc="voter.gender.name or '-'"/>
|
||
</span>
|
||
<span t-else="" class="text-muted">-</span>
|
||
</td>
|
||
<td class="fw-medium"><t t-esc="voter.name or '–'"/></td>
|
||
<td><t t-esc="voter.dob or '-'"/></td>
|
||
<td><t t-esc="voter.address or '-'"/></td>
|
||
<!-- <td class="text-center"><t t-esc="voter.phone or '-'"/></td>-->
|
||
<td class="text-center">
|
||
<span class="badge bg-success">បោះឆ្នោតរួច</span>
|
||
</td>
|
||
<td class="text-center">
|
||
<!-- ✅ TOGGLE BUTTON: Mark as Not Voted -->
|
||
<a t-attf-href="/my/cpp_entries/voter/#{voter.id}/toggle_vote?csrf_token=#{request.csrf_token()}"
|
||
class="btn btn-sm btn-warning py-0 me-1"
|
||
title="កំណត់ថាមិនទាន់បោះឆ្នោត">
|
||
<i class="fa fa-undo"/> មិនទាន់បោះឆ្នោត
|
||
</a>
|
||
<a t-attf-href="/my/cpp_entries/voter/#{voter.id}/edit" class="btn btn-sm btn-outline-primary py-0 me-1"><i class="fa fa-pencil"/></a>
|
||
<a t-attf-href="/my/cpp_entries/voter/#{voter.id}/delete?csrf_token=#{request.csrf_token()}" class="btn btn-sm btn-outline-danger py-0" onclick="return confirm('តើអ្នកពិតជាចង់លុកឈ្មោះនេះមែនទេ?');"><i class="fa fa-trash"/></a>
|
||
</td>
|
||
<td class="text-center">
|
||
<t t-if="voter.photo">
|
||
<img t-att-src="image_data_uri(voter.photo)" class="rounded" style="width:40px;height:40px;object-fit:cover;" alt="Photo"/>
|
||
</t>
|
||
<t t-else=""><span class="text-muted small">–</span></t>
|
||
</td>
|
||
</tr>
|
||
</t>
|
||
</t>
|
||
<t t-else="">
|
||
<tr><td colspan="9" class="text-center text-muted py-4"><i class="fa fa-info-circle me-1"/> មិនទាន់មានទិន្នន័យ</td></tr>
|
||
</t>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
<!-- <div class="card-footer bg-white">-->
|
||
<!-- <a t-attf-href="/my/cpp_entries/voter/new?entry_id=#{entry.id}&status_vote=1" class="btn btn-success btn-sm">-->
|
||
<!-- <i class="fa fa-plus me-1"/> បន្ថែមអ្នកបានបោះឆ្នោត-->
|
||
<!-- </a>-->
|
||
<!-- </div>-->
|
||
</div>
|
||
</t>
|
||
<t t-else="">
|
||
<!-- ✅ Info Message if entry is NOT saved yet -->
|
||
<div class="alert alert-info">
|
||
<i class="fa fa-info-circle me-2"/>
|
||
<strong>ចំណាំ:</strong> សូមចុច <b>"រក្សាទុក"</b> ដើម្បីបង្កើតបញ្ជីជាមុនសិន ទើបអាចបន្ថែមអ្នកបោះឆ្នោតបាន។
|
||
</div>
|
||
</t>
|
||
|
||
<!-- Action Buttons -->
|
||
<div class="d-flex justify-content-between mt-4 pt-3 border-top">
|
||
<a href="/my/cpp_entries" class="btn btn-outline-secondary px-4">
|
||
<i class="fa fa-arrow-left me-1"/> ត្រប់
|
||
</a>
|
||
<div>
|
||
<button type="submit" class="btn btn-primary px-5">
|
||
<i class="fa fa-save me-1"/> រក្សាទុកព័ត៌មាន
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</t>
|
||
</template>
|
||
|
||
<!-- =======================================================
|
||
TEMPLATE: Voter Add/Edit Form
|
||
======================================================= -->
|
||
<template id="portal_voter_form" name="Voter Information Form">
|
||
<t t-call="portal.portal_layout">
|
||
<div class="container mt-4" style="max-width: 750px;">
|
||
<nav aria-label="breadcrumb" class="mb-4">
|
||
<ol class="breadcrumb">
|
||
<li class="breadcrumb-item"><a href="/my">ផ្ទាំងគ្រប់គ្រង</a></li>
|
||
<li class="breadcrumb-item"><a href="/my/cpp_entries">CPP Entries</a></li>
|
||
<li class="breadcrumb-item"><a t-attf-href="/my/cpp_entries/#{entry.id}">បញ្ជី</a></li>
|
||
<li class="breadcrumb-item active">
|
||
<t t-if="voter.id">កែព័ត៌មាន</t>
|
||
<t t-else="">បន្ថែមថ្មី</t>
|
||
</li>
|
||
</ol>
|
||
</nav>
|
||
|
||
<div class="card shadow-sm border-0">
|
||
<div class="card-header bg-primary text-white">
|
||
<h4 class="mb-0"><i class="fa fa-user me-2"/>
|
||
<t t-if="voter.id">កែព័ត៌មានអ្នកបោះឆ្នោត</t>
|
||
<t t-else="">បន្ថែមអ្នកបោះឆ្នោតថ្មី</t>
|
||
</h4>
|
||
</div>
|
||
|
||
<form t-attf-action="/my/cpp_entries/voter/submit" method="post" enctype="multipart/form-data" class="card-body">
|
||
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
|
||
|
||
<!-- ✅ Hidden Fields for ID tracking -->
|
||
<input type="hidden" name="entry_id" t-att-value="entry.id"/>
|
||
<input type="hidden" name="voter_id" t-att-value="voter.id or 0"/>
|
||
|
||
<!-- Photo Upload Section -->
|
||
<div class="photo-upload-container text-center mb-4">
|
||
<div class="position-relative d-inline-block">
|
||
<!-- ✅ Show existing photo if available -->
|
||
<t t-if="voter.photo">
|
||
<img t-att-src="image_data_uri(voter.photo)"
|
||
id="photo_preview"
|
||
class="rounded-circle border border-3 border-light shadow"
|
||
style="width:120px;height:120px;object-fit:cover;display:block;"
|
||
alt="Profile Photo"/>
|
||
</t>
|
||
<!-- ✅ Show placeholder if no photo -->
|
||
<t t-else="">
|
||
<div class="photo-placeholder rounded-circle bg-light d-flex align-items-center justify-content-center border border-3 border-light shadow"
|
||
style="width:120px;height:120px;">
|
||
<i class="fa fa-user fa-3x text-muted"/>
|
||
</div>
|
||
</t>
|
||
|
||
<!-- ✅ Camera button with file input -->
|
||
<label for="photo_upload"
|
||
class="position-absolute bottom-0 end-0 btn btn-sm btn-primary rounded-circle shadow"
|
||
style="width:36px;height:36px;padding:0;line-height:36px;text-align:center;cursor:pointer;z-index:10;">
|
||
<i class="fa fa-camera" style="font-size:14px;"/>
|
||
<input type="file"
|
||
name="photo"
|
||
id="photo_upload"
|
||
class="d-none"
|
||
accept="image/*"/>
|
||
</label>
|
||
</div>
|
||
<small class="text-muted d-block mt-2">រូបថត (JPEG, PNG - អតិបរមា 2MB)</small>
|
||
</div>
|
||
|
||
<!-- Personal Info -->
|
||
<div class="row">
|
||
<div class="col-md-6 mb-3">
|
||
<label class="form-label fw-bold">ឈ្មោះ <span class="text-danger">*</span></label>
|
||
<input type="text" name="name" class="form-control form-control-lg" required="1" placeholder="បញ្ចូល្មោះពេញ" t-att-value="voter.name or ''"/>
|
||
</div>
|
||
<div class="col-md-6 mb-3">
|
||
<label class="form-label fw-bold">ភេទ</label>
|
||
<select name="gender" class="form-select form-select-lg">
|
||
<option value="">-- ជ្រើសរើសភេទ --</option>
|
||
<t t-foreach="genders" t-as="g">
|
||
<option t-att-value="g.id" t-att-selected="voter.gender.id == g.id"><t t-esc="g.name"/></option>
|
||
</t>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-6 mb-3">
|
||
<label class="form-label fw-bold">ថ្ងៃខែឆ្នាំកំណើត</label>
|
||
<input type="date" name="dob" class="form-control form-control-lg" t-att-value="voter.dob"/>
|
||
</div>
|
||
<div class="col-md-6 mb-3">
|
||
<label class="form-label fw-bold">លេខទូរស័ព្ទ</label>
|
||
<input type="tel" name="phone" class="form-control form-control-lg" placeholder="012 345 678" t-att-value="voter.phone or ''"/>
|
||
</div>
|
||
<div class="col-12 mb-3">
|
||
<label class="form-label fw-bold">អាសយដ្ឋាន</label>
|
||
<textarea name="address" class="form-control" rows="3" placeholder="បញ្ចូលអាសយដ្ឋានពេញ" t-esc="voter.address or ''"/>
|
||
</div>
|
||
<div class="col-12 mb-4">
|
||
<div class="form-check form-switch">
|
||
<input class="form-check-input" type="checkbox" name="status_vote" id="status_vote" t-att-checked="'checked' if status_vote == 1 else None"/>
|
||
<label class="form-check-label fw-bold" for="status_vote">✅ បោះឆ្នោតរួច</label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="d-flex justify-content-between mt-4 pt-3 border-top">
|
||
<a t-attf-href="/my/cpp_entries/#{entry.id}" class="btn btn-outline-secondary px-4"><i class="fa fa-times me-1"/> បោះបង់</a>
|
||
<button type="submit" class="btn btn-primary px-5">
|
||
<i class="fa fa-save me-1"/> <t t-if="voter.id">កែប្រែ</t><t t-else="">បន្ថែម</t>
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</t>
|
||
</template>
|
||
</odoo> |