Files
project_v19/cpp_entry/views/portal_templates.xml
T

434 lines
31 KiB
XML
Raw Normal View History

2026-07-01 14:41:49 +07:00
<?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}&amp;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}&amp;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>