365 lines
22 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="reservations_page_template" name="Dine360 Reservations Page">
<t t-call="dine360_dashboard.dashboard_layout">
<t t-set="active_page" t-value="'reservations'"/>
<!-- Page Title & Header -->
<section class="o_page_header">
<div>
<h1 class="o_heading_title">Table Reservations</h1>
<p class="o_heading_subtitle">Real-time guest bookings, seating schedule, and WhatsApp guest notifications</p>
</div>
<div class="o_header_controls">
<div class="o_status_tag">
<span class="o_green_dot"/>
<span>Online Reservations: Active</span>
</div>
<div class="o_date_picker_btn">
<i class="fa fa-calendar me-2 text-muted"/>
<span><t t-esc="current_date_str or 'Today'"/></span>
</div>
<button type="button" class="o_btn_red_action" data-open-modal="modalNewReservation">
<i class="fa fa-plus me-1"/> New Reservation
</button>
</div>
</section>
<!-- Row 1: KPI Summary Cards -->
<section class="o_kpi_grid mb-4">
<!-- KPI 1: Total Reservations -->
<div class="o_kpi_card">
<div class="o_kpi_top">
<div class="o_kpi_icon_box bg-red-light text-danger">
<i class="fa fa-calendar fs-5"/>
</div>
<span class="o_kpi_trend text-danger"><i class="fa fa-arrow-up"/> Live</span>
</div>
<div class="o_kpi_label">Total Bookings</div>
<div class="o_kpi_number"><t t-esc="reservation_stats['total']"/></div>
<div class="o_kpi_footer">
<span class="o_kpi_sub">All scheduled guests</span>
<svg class="o_sparkline" viewBox="0 0 100 30" preserveAspectRatio="none">
<path d="M0 25 Q20 15 40 22 T80 10 T100 5" fill="none" stroke="#ef4444" stroke-width="2.5" stroke-linecap="round"/>
</svg>
</div>
</div>
<!-- KPI 2: Confirmed -->
<div class="o_kpi_card">
<div class="o_kpi_top">
<div class="o_kpi_icon_box bg-green-light text-success">
<i class="fa fa-check-circle fs-5"/>
</div>
<span class="o_kpi_trend text-success"><i class="fa fa-arrow-up"/> Confirmed</span>
</div>
<div class="o_kpi_label">Confirmed Bookings</div>
<div class="o_kpi_number"><t t-esc="reservation_stats['confirmed']"/></div>
<div class="o_kpi_footer">
<span class="o_kpi_sub">Ready for seating</span>
<svg class="o_sparkline" viewBox="0 0 100 30" preserveAspectRatio="none">
<path d="M0 20 Q30 25 50 15 T80 18 T100 8" fill="none" stroke="#16a34a" stroke-width="2.5" stroke-linecap="round"/>
</svg>
</div>
</div>
<!-- KPI 3: Pending / Draft -->
<div class="o_kpi_card">
<div class="o_kpi_top">
<div class="o_kpi_icon_box bg-amber-light text-warning">
<i class="fa fa-clock-o fs-5"/>
</div>
<span class="o_kpi_trend text-warning">Pending</span>
</div>
<div class="o_kpi_label">Draft / Pending</div>
<div class="o_kpi_number"><t t-esc="reservation_stats['draft']"/></div>
<div class="o_kpi_footer">
<span class="o_kpi_sub">Requires confirmation</span>
<svg class="o_sparkline" viewBox="0 0 100 30" preserveAspectRatio="none">
<path d="M0 15 Q25 22 50 18 T80 25 T100 12" fill="none" stroke="#f59e0b" stroke-width="2.5" stroke-linecap="round"/>
</svg>
</div>
</div>
<!-- KPI 4: Seated / Completed -->
<div class="o_kpi_card">
<div class="o_kpi_top">
<div class="o_kpi_icon_box bg-slate-light text-primary">
<i class="fa fa-cutlery fs-5"/>
</div>
<span class="o_kpi_trend text-primary">Completed</span>
</div>
<div class="o_kpi_label">Seated / Done</div>
<div class="o_kpi_number"><t t-esc="reservation_stats['completed']"/></div>
<div class="o_kpi_footer">
<span class="o_kpi_sub">Guests dined</span>
<svg class="o_sparkline" viewBox="0 0 100 30" preserveAspectRatio="none">
<path d="M0 25 Q35 20 60 15 T100 10" fill="none" stroke="#3b82f6" stroke-width="2.5" stroke-linecap="round"/>
</svg>
</div>
</div>
</section>
<!-- Row 2: Toolbar (Filters & Search) -->
<div class="o_page_toolbar">
<div class="o_filter_pills">
<div class="o_filter_pill active" data-filter="all">All Bookings (<t t-esc="reservation_stats['total']"/>)</div>
<div class="o_filter_pill" data-filter="confirmed">Confirmed (<t t-esc="reservation_stats['confirmed']"/>)</div>
<div class="o_filter_pill" data-filter="draft">Draft / Pending (<t t-esc="reservation_stats['draft']"/>)</div>
<div class="o_filter_pill" data-filter="completed">Completed (<t t-esc="reservation_stats['completed']"/>)</div>
<div class="o_filter_pill" data-filter="cancelled">Cancelled (<t t-esc="reservation_stats['cancelled']"/>)</div>
</div>
<div class="o_toolbar_search">
<i class="fa fa-search text-muted"/>
<input type="text" class="o_toolbar_search_input" placeholder="Search guest name, phone, or reservation #..."/>
</div>
</div>
<!-- Row 3: Reservations Data Table -->
<div class="o_modern_table_card mb-4">
<div class="o_card_header">
<div class="d-flex align-items-center gap-2">
<h3 class="o_card_title mb-0">Live Guest Bookings List</h3>
<span class="o_count_pill"><t t-esc="reservation_stats['total']"/> Reservations</span>
</div>
<div class="d-flex align-items-center gap-2">
<button type="button" class="o_btn_red_small" data-open-modal="modalNewReservation">
<i class="fa fa-plus me-1"/> New Reservation
</button>
<a href="/web#action=dine360_reservation.action_restaurant_reservation" class="o_btn_white_small">
Open in Backend
</a>
</div>
</div>
<div class="table-responsive">
<table class="o_modern_table">
<thead>
<tr>
<th>Booking Ref</th>
<th>Guest Details</th>
<th>Date &amp; Time Slot</th>
<th>Party &amp; Table</th>
<th>Occasion / Notes</th>
<th>Status</th>
<th class="text-end">Quick Actions</th>
</tr>
</thead>
<tbody>
<t t-if="not reservations">
<tr>
<td colspan="7" class="text-center py-5 text-muted">
<i class="fa fa-calendar-o fa-3x mb-3 text-secondary"/>
<h5>No reservations found</h5>
<p class="small">Click "New Reservation" to record a table booking.</p>
</td>
</tr>
</t>
<t t-foreach="reservations" t-as="res">
<tr data-search-item="true" data-filter-item="true" t-att-data-status="res['state']">
<!-- Booking Ref -->
<td>
<span class="font-monospace fw-bold text-dark"><t t-esc="res['name']"/></span>
<t t-if="res.get('is_admin_override')">
<span class="badge bg-danger ms-1 small" title="Admin Override">Override</span>
</t>
</td>
<!-- Guest Details -->
<td>
<div class="fw-bold text-dark"><t t-esc="res['customer_name']"/></div>
<div class="small text-muted d-flex align-items-center gap-2 mt-1">
<t t-if="res.get('phone')">
<span><i class="fa fa-phone text-muted me-1"/><t t-esc="res['phone']"/></span>
</t>
<t t-if="res.get('whatsapp_url')">
<a t-att-href="res['whatsapp_url']" target="_blank" class="text-success fw-bold text-decoration-none" title="Send WhatsApp Message">
<i class="fa fa-whatsapp text-success"/> WhatsApp
</a>
</t>
</div>
</td>
<!-- Date & Time Slot -->
<td>
<div class="fw-semibold text-dark"><i class="fa fa-clock-o text-muted me-1"/><t t-esc="res['start_time_fmt']"/></div>
<div class="small text-muted"><t t-esc="res['date_fmt']"/></div>
</td>
<!-- Party & Table -->
<td>
<div class="badge bg-light text-dark border">
<i class="fa fa-users text-danger me-1"/> <t t-esc="res['num_people']"/> Guests
</div>
<div class="small text-muted mt-1">
<i class="fa fa-th text-muted me-1"/>
<t t-if="res.get('table_name')"><t t-esc="res['table_name']"/></t>
<t t-else="">Any Available Table</t>
<t t-if="res.get('floor_name')"> (<t t-esc="res['floor_name']"/>)</t>
</div>
</td>
<!-- Occasion / Notes -->
<td>
<t t-if="res.get('occasion')">
<span class="badge bg-info-subtle text-primary border border-info-subtle mb-1"><t t-esc="res['occasion'].title()"/></span>
</t>
<div class="small text-muted text-truncate" style="max-width:180px;" t-att-title="res.get('special_requests', '')">
<t t-esc="res.get('special_requests') or 'No special requests'"/>
</div>
</td>
<!-- Status Badge -->
<td>
<t t-if="res['state'] == 'confirmed'">
<span class="o_badge_status success">
<span class="o_badge_dot"/> Confirmed
</span>
</t>
<t t-elif="res['state'] == 'draft'">
<span class="o_badge_status warning">
<span class="o_badge_dot"/> Draft
</span>
</t>
<t t-elif="res['state'] == 'completed'">
<span class="o_badge_status info">
<span class="o_badge_dot"/> Completed
</span>
</t>
<t t-elif="res['state'] == 'cancelled'">
<span class="o_badge_status danger">
<span class="o_badge_dot"/> Cancelled
</span>
</t>
<t t-else="">
<span class="o_badge_status secondary">
<t t-esc="res['state']"/>
</span>
</t>
</td>
<!-- Quick Actions -->
<td class="text-end">
<div class="d-inline-flex gap-1">
<t t-if="res['state'] == 'draft'">
<button type="button" class="btn btn-sm btn-outline-success o_btn_update_reservation" t-att-data-res-id="res['id']" data-status="confirmed" title="Confirm Reservation">
<i class="fa fa-check"/> Confirm
</button>
</t>
<t t-if="res['state'] == 'confirmed'">
<button type="button" class="btn btn-sm btn-outline-primary o_btn_update_reservation" t-att-data-res-id="res['id']" data-status="completed" title="Seat &amp; Complete">
<i class="fa fa-cutlery"/> Seat
</button>
</t>
<t t-if="res['state'] not in ('cancelled', 'completed')">
<button type="button" class="btn btn-sm btn-outline-danger o_btn_update_reservation" t-att-data-res-id="res['id']" data-status="cancelled" title="Cancel Booking">
<i class="fa fa-times"/>
</button>
</t>
<a t-att-href="'/web#id=%s&amp;model=restaurant.reservation&amp;view_type=form' % res['id']" class="btn btn-sm btn-light border text-muted" title="View Record">
<i class="fa fa-external-link"/>
</a>
</div>
</td>
</tr>
</t>
</tbody>
</table>
</div>
</div>
<!-- MODAL: Create New Table Reservation -->
<div id="modalNewReservation" class="o_dine_modal">
<div class="o_modal_backdrop"/>
<div class="o_modal_dialog">
<div class="o_modal_header">
<div class="d-flex align-items-center gap-2">
<div class="o_settings_icon" style="width:34px;height:34px;font-size:15px;">
<i class="fa fa-calendar"/>
</div>
<h4 class="o_modal_title">Create Table Reservation</h4>
</div>
<button type="button" class="o_modal_close_btn o_modal_close">&amp;times;</button>
</div>
<form id="formNewReservation">
<div class="o_modal_body">
<div class="row">
<div class="col-md-6 o_form_group">
<label class="o_form_label">Guest Name *</label>
<input type="text" name="customer_name" required="required" placeholder="Guest Full Name" class="o_form_control"/>
</div>
<div class="col-md-6 o_form_group">
<label class="o_form_label">Phone Number *</label>
<input type="tel" name="phone" required="required" placeholder="+91 98765 43210" class="o_form_control"/>
</div>
</div>
<div class="row">
<div class="col-md-6 o_form_group">
<label class="o_form_label">Email Address</label>
<input type="email" name="email" placeholder="guest@example.com" class="o_form_control"/>
</div>
<div class="col-md-6 o_form_group">
<label class="o_form_label">Number of People *</label>
<input type="number" name="num_people" required="required" min="1" max="50" value="2" class="o_form_control"/>
</div>
</div>
<div class="row">
<div class="col-md-6 o_form_group">
<label class="o_form_label">Reservation Date &amp; Time *</label>
<input type="datetime-local" name="start_time" required="required" class="o_form_control"/>
</div>
<div class="col-md-6 o_form_group">
<label class="o_form_label">Dining Occasion</label>
<select name="occasion" class="o_form_control">
<option value="casual">Casual Dining</option>
<option value="birthday">Birthday Celebration</option>
<option value="anniversary">Anniversary</option>
<option value="business">Business Meal</option>
<option value="date">Date Night</option>
<option value="other">Other Occasion</option>
</select>
</div>
</div>
<div class="row">
<div class="col-md-6 o_form_group">
<label class="o_form_label">Preferred Table</label>
<select name="table_id" class="o_form_control">
<option value="">-- Any Available Table --</option>
<t t-foreach="available_tables" t-as="table">
<option t-att-value="table['id']">
<t t-esc="table['name']"/> (<t t-esc="table.get('seats', 4)"/> Seats - <t t-esc="table.get('floor_name', 'Main')"/>)
</option>
</t>
</select>
</div>
<div class="col-md-6 o_form_group">
<label class="o_form_label">Preferred Zone / Area</label>
<input type="text" name="preferred_zone" placeholder="Window Seat, Terrace, AC..." class="o_form_control"/>
</div>
</div>
<div class="o_form_group">
<label class="o_form_label">Special Requests / Dietary Notes</label>
<textarea name="special_requests" rows="2" placeholder="Vegetarian, High chair for child, quiet corner..." class="o_form_control"></textarea>
</div>
</div>
<div class="o_modal_footer">
<button type="button" class="btn btn-light o_modal_close">Cancel</button>
<button type="submit" class="o_btn_red_action">
<i class="fa fa-check me-1"/> Confirm Booking &amp; Notify Guest
</button>
</div>
</form>
</div>
</div>
</t>
</template>
</odoo>