534 lines
32 KiB
PHP
534 lines
32 KiB
PHP
<div class="page-header">
|
||
<div>
|
||
<div style="display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap;">
|
||
<h1 class="page-title"><?= e($session['title']) ?></h1>
|
||
<span class="badge badge-<?= match($session['status']) {
|
||
'open' => 'completed',
|
||
'closed' => 'warning',
|
||
'arrived' => 'processing',
|
||
default => 'neutral'
|
||
} ?>" style="font-size: 0.85rem; padding: 0.35rem 0.75rem;">
|
||
<?= strtoupper(e($session['status'])) ?>
|
||
</span>
|
||
</div>
|
||
<p class="page-subtitle">
|
||
🏢 Canteen: <strong><?= e($session['canteen_name']) ?></strong> •
|
||
👤 Hosted by: <strong><?= e($session['creator_name']) ?></strong> (@<?= e($session['creator_username']) ?>) •
|
||
📅 Date: <strong><?= date('F j, Y', strtotime($session['session_date'])) ?></strong>
|
||
</p>
|
||
</div>
|
||
|
||
<!-- Status Controls for Session Creator -->
|
||
<?php if ($isCreator): ?>
|
||
<div style="display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap;">
|
||
<form method="POST" action="/sessions/<?= e($session['id']) ?>/status" style="display: inline-flex; gap: 0.5rem;">
|
||
<?= \App\Core\View::csrfField() ?>
|
||
<select name="status" class="form-select" onchange="this.form.submit()" style="font-size: 0.85rem; padding: 0.4rem 0.75rem;">
|
||
<option value="open" <?= $session['status'] === 'open' ? 'selected' : '' ?>>🟢 Status: Open (Taking Orders)</option>
|
||
<option value="closed" <?= $session['status'] === 'closed' ? 'selected' : '' ?>>🟡 Status: Closed (Sent to Canteen)</option>
|
||
<option value="arrived" <?= $session['status'] === 'arrived' ? 'selected' : '' ?>>🔵 Status: Food Arrived (Billing)</option>
|
||
<option value="completed" <?= $session['status'] === 'completed' ? 'selected' : '' ?>>⚪ Status: Completed / Settled</option>
|
||
</select>
|
||
</form>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
<?php if (!empty($session['notes'])): ?>
|
||
<div class="alert alert-info" style="background-color: #eff6ff; border: 1px solid #bfdbfe; color: #1e40af; margin-bottom: 1.5rem;">
|
||
<span>📢 <strong>Host Note:</strong> <?= e($session['notes']) ?></span>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<!-- Quick Stats Bar -->
|
||
<div class="grid-stats" style="margin-bottom: 1.5rem;">
|
||
<div class="stat-card">
|
||
<div>
|
||
<div class="stat-label">Coworkers Ordered</div>
|
||
<div class="stat-value"><?= count($session['orders']) ?></div>
|
||
</div>
|
||
<div class="stat-icon" style="background: #eef2ff; color: #4f46e5;">👥</div>
|
||
</div>
|
||
|
||
<div class="stat-card">
|
||
<div>
|
||
<div class="stat-label">Total Food Items</div>
|
||
<div class="stat-value"><?= array_sum(array_column($session['recap'], 'total_quantity')) ?></div>
|
||
</div>
|
||
<div class="stat-icon" style="background: #ecfdf5; color: #10b981;">🍱</div>
|
||
</div>
|
||
|
||
<div class="stat-card">
|
||
<div>
|
||
<div class="stat-label">Total Session Bill</div>
|
||
<div class="stat-value"><?= money(array_sum(array_column($session['orders'], 'total_bill'))) ?></div>
|
||
</div>
|
||
<div class="stat-icon" style="background: #fffbeb; color: #f59e0b;">💵</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Main 2-Column Hub Layout -->
|
||
<div style="display: grid; grid-template-columns: 1.2fr 1fr; gap: 1.5rem; align-items: start;">
|
||
|
||
<!-- Left Column: Self-Ordering Widget & Live Coworker Orders Feed -->
|
||
<div>
|
||
|
||
<!-- Interactive Self-Order Form (Alpine.js) -->
|
||
<?php if ($session['status'] === 'open'): ?>
|
||
<div class="card" x-data="canteenOrderForm()" style="border: 2px solid var(--primary);">
|
||
<div class="card-header" style="background: var(--primary-light); display: flex; justify-content: space-between; align-items: center;">
|
||
<div>
|
||
<h2 class="card-title" style="color: var(--primary);">
|
||
<?= $myOrder ? '✏️ Update Your Lunch Order' : '➕ Place Your Lunch Order' ?>
|
||
</h2>
|
||
<p style="font-size: 0.8rem; color: var(--text-muted); margin-top: 0.15rem;">
|
||
Ordering as: <strong><?= e($currentUser['name']) ?></strong> (@<?= e($currentUser['username']) ?>)
|
||
</p>
|
||
</div>
|
||
|
||
<?php if ($myOrder): ?>
|
||
<span class="badge badge-completed">Already Ordered</span>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
<div class="card-body">
|
||
<form method="POST" action="/employee-orders" @submit="validateSubmit($event)">
|
||
<?= \App\Core\View::csrfField() ?>
|
||
<input type="hidden" name="session_id" value="<?= e($session['id']) ?>">
|
||
|
||
<!-- Multi-Select Menu Selection -->
|
||
<div class="form-group">
|
||
<label class="form-label" style="display: flex; justify-content: space-between; align-items: center;">
|
||
<span>Click items to Multi-Select:</span>
|
||
<span style="font-size: 0.75rem; font-weight: normal; color: var(--text-muted);">
|
||
<span x-text="selectedItems.length">0</span> item(s) selected
|
||
</span>
|
||
</label>
|
||
|
||
<?php if (empty($session['menus'])): ?>
|
||
<div style="padding: 1.5rem; text-align: center; background: #f8fafc; border-radius: var(--radius-sm); border: 1px dashed var(--border-color);">
|
||
<p style="color: var(--text-muted); font-size: 0.9rem;">No menu listed yet for today.</p>
|
||
</div>
|
||
<?php else: ?>
|
||
<div class="menu-grid" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 0.6rem;">
|
||
<?php foreach ($session['menus'] as $menu): ?>
|
||
<div class="menu-select-card"
|
||
:class="{ 'is-selected': isSelected(<?= e($menu['id']) ?>) }"
|
||
@click="toggleItem(<?= e($menu['id']) ?>, '<?= addslashes(e($menu['name'])) ?>')">
|
||
<div style="display: flex; align-items: flex-start; gap: 0.5rem;">
|
||
<input type="checkbox"
|
||
:checked="isSelected(<?= e($menu['id']) ?>)"
|
||
style="margin-top: 0.2rem; pointer-events: none;">
|
||
<div style="flex: 1;">
|
||
<div style="font-weight: 600; font-size: 0.875rem; line-height: 1.3;">
|
||
<?= e($menu['name']) ?>
|
||
</div>
|
||
<?php if ((float)$menu['final_price'] > 0): ?>
|
||
<div style="font-size: 0.775rem; color: var(--success); font-weight: 600; margin-top: 0.2rem;">
|
||
<?= money($menu['final_price']) ?>
|
||
</div>
|
||
<?php else: ?>
|
||
<div style="font-size: 0.725rem; color: var(--text-muted); margin-top: 0.2rem;">
|
||
(Price settled on arrival)
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
<!-- Selected Items Customizer (Quantity & Notes) -->
|
||
<template x-if="selectedItems.length > 0">
|
||
<div style="margin-top: 1.25rem; background: #f8fafc; border: 1px solid var(--border-color); border-radius: var(--radius-sm); padding: 1rem;">
|
||
<div style="font-weight: 600; font-size: 0.85rem; margin-bottom: 0.75rem; color: var(--text-main);">
|
||
📝 Customize Quantities & Requests:
|
||
</div>
|
||
|
||
<div style="display: flex; flex-direction: column; gap: 0.75rem;">
|
||
<template x-for="(item, idx) in selectedItems" :key="idx">
|
||
<div style="display: flex; align-items: center; gap: 0.75rem; background: white; padding: 0.6rem 0.75rem; border-radius: var(--radius-sm); border: 1px solid var(--border-color); flex-wrap: wrap;">
|
||
<input type="hidden" :name="`items[${idx}][session_menu_id]`" :value="item.id">
|
||
<input type="hidden" :name="`items[${idx}][item_name]`" :value="item.name">
|
||
|
||
<div style="flex: 2; min-width: 140px; font-weight: 600; font-size: 0.85rem;" x-text="item.name"></div>
|
||
|
||
<div style="display: flex; align-items: center; gap: 0.35rem;">
|
||
<button type="button" class="btn btn-secondary btn-sm" style="padding: 0.15rem 0.5rem; height: 28px;" @click="item.quantity = Math.max(1, item.quantity - 1)">-</button>
|
||
<input type="number" min="1" :name="`items[${idx}][quantity]`" class="form-control" style="width: 50px; text-align: center; padding: 0.2rem;" x-model.number="item.quantity">
|
||
<button type="button" class="btn btn-secondary btn-sm" style="padding: 0.15rem 0.5rem; height: 28px;" @click="item.quantity++">+</button>
|
||
</div>
|
||
|
||
<div style="flex: 3; min-width: 160px;">
|
||
<input type="text" :name="`items[${idx}][notes]`" class="form-control" placeholder="Notes (e.g. no spicy, extra egg)" x-model="item.notes" style="font-size: 0.825rem; padding: 0.3rem 0.5rem;">
|
||
</div>
|
||
|
||
<button type="button" @click="removeItem(idx)" style="background: none; border: none; color: var(--danger); font-size: 1.25rem; cursor: pointer; padding: 0 0.25rem;">×</button>
|
||
</div>
|
||
</template>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<!-- General Order Note -->
|
||
<div class="form-group" style="margin-top: 1rem;">
|
||
<label class="form-label">General Note (Optional)</label>
|
||
<input type="text" name="notes" class="form-control" placeholder="e.g. Please put in plastic bag" value="<?= e($myOrder['notes'] ?? '') ?>">
|
||
</div>
|
||
|
||
<button type="submit" class="btn btn-primary" style="width: 100%; padding: 0.75rem; margin-top: 0.5rem; font-size: 1rem;">
|
||
🚀 <?= $myOrder ? 'Update My Order' : 'Submit My Lunch Order' ?>
|
||
</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
<?php else: ?>
|
||
<div class="card" style="background: #f8fafc; border: 1px dashed var(--border-color);">
|
||
<div class="card-body" style="text-align: center; padding: 2rem;">
|
||
<div style="font-size: 2rem; margin-bottom: 0.5rem;">🔒</div>
|
||
<h3 style="font-size: 1.1rem; font-weight: 600;">Orders Closed for this Session</h3>
|
||
<p style="color: var(--text-muted); font-size: 0.875rem; margin-top: 0.25rem;">
|
||
This order session is no longer taking new submissions. Please contact the host (<strong><?= e($session['creator_name']) ?></strong>) directly.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<!-- Live Coworker Orders Feed -->
|
||
<div class="card" style="margin-top: 1.5rem;">
|
||
<div class="card-header">
|
||
<div>
|
||
<h2 class="card-title">📋 Orders in this Session (<?= count($session['orders']) ?> people)</h2>
|
||
<p style="font-size: 0.8rem; color: var(--text-muted);">Real-time feed of all team members who joined</p>
|
||
</div>
|
||
</div>
|
||
|
||
<?php if (empty($session['orders'])): ?>
|
||
<div class="card-body" style="text-align: center; padding: 3rem; color: var(--text-muted);">
|
||
No orders placed yet. Be the first to order above!
|
||
</div>
|
||
<?php else: ?>
|
||
<div style="display: flex; flex-direction: column;">
|
||
<?php foreach ($session['orders'] as $order): ?>
|
||
<div style="padding: 1.25rem 1.5rem; border-bottom: 1px solid var(--border-color); display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; flex-wrap: wrap; <?= (int)$order['user_id'] === (int)$currentUser['id'] ? 'background-color: #faf5ff;' : '' ?>">
|
||
<div style="flex: 1; min-width: 250px;">
|
||
<div style="display: flex; align-items: center; gap: 0.5rem;">
|
||
<strong style="font-size: 1rem; color: var(--text-main);">
|
||
<?= e($order['user_name']) ?>
|
||
<?= (int)$order['user_id'] === (int)$currentUser['id'] ? ' <span style="font-size: 0.75rem; color: var(--primary); font-weight: normal;">(You)</span>' : '' ?>
|
||
</strong>
|
||
<?php if (!empty($order['mattermost_username'])): ?>
|
||
<span style="font-size: 0.775rem; color: var(--text-muted); background: #f1f5f9; padding: 0.15rem 0.4rem; border-radius: var(--radius-sm);">@<?= e($order['mattermost_username']) ?></span>
|
||
<?php endif; ?>
|
||
<span style="font-size: 0.75rem; color: var(--text-muted); margin-left: auto;"><?= date('H:i', strtotime($order['created_at'])) ?></span>
|
||
</div>
|
||
|
||
<ul style="list-style: none; margin-top: 0.5rem; display: flex; flex-direction: column; gap: 0.35rem;">
|
||
<?php foreach ($order['items'] as $item): ?>
|
||
<li style="font-size: 0.9rem; display: flex; align-items: center; gap: 0.5rem;">
|
||
<span style="font-weight: 700; color: var(--primary); background: var(--primary-light); padding: 0.1rem 0.45rem; border-radius: var(--radius-sm); font-size: 0.8rem;"><?= e($item['quantity']) ?>x</span>
|
||
<span><?= e($item['item_name']) ?></span>
|
||
<?php if (!empty($item['notes'])): ?>
|
||
<em style="color: var(--text-muted); font-size: 0.8rem;">(<?= e($item['notes']) ?>)</em>
|
||
<?php endif; ?>
|
||
<?php if ((float)$item['total_price'] > 0): ?>
|
||
<span style="margin-left: auto; font-weight: 600; font-size: 0.85rem;"><?= money($item['total_price']) ?></span>
|
||
<?php endif; ?>
|
||
</li>
|
||
<?php endforeach; ?>
|
||
</ul>
|
||
|
||
<?php if (!empty($order['notes'])): ?>
|
||
<div style="margin-top: 0.5rem; font-size: 0.8rem; color: var(--text-muted); background: #f8fafc; padding: 0.35rem 0.6rem; border-radius: var(--radius-sm);">
|
||
💬 Note: <?= e($order['notes']) ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
<!-- Personal Bill & Payment Status -->
|
||
<div style="text-align: right; min-width: 140px;">
|
||
<div style="font-size: 1.15rem; font-weight: 700; color: var(--text-main);">
|
||
<?= (float)$order['total_bill'] > 0 ? money($order['total_bill']) : '<span style="font-size: 0.8rem; color: var(--text-muted); font-weight: normal;">Pending Price</span>' ?>
|
||
</div>
|
||
|
||
<div style="margin-top: 0.35rem;">
|
||
<?php if ($isCreator): ?>
|
||
<form method="POST" action="/employee-orders/<?= e($order['id']) ?>/toggle-paid" style="display: inline;">
|
||
<?= \App\Core\View::csrfField() ?>
|
||
<input type="hidden" name="session_id" value="<?= e($session['id']) ?>">
|
||
<button type="submit" class="badge badge-<?= $order['status'] === 'paid' ? 'completed' : 'pending' ?>" style="cursor: pointer; border: none;">
|
||
<?= $order['status'] === 'paid' ? '✓ PAID' : '⌛ UNPAID' ?>
|
||
</button>
|
||
</form>
|
||
<?php else: ?>
|
||
<span class="badge badge-<?= $order['status'] === 'paid' ? 'completed' : 'pending' ?>">
|
||
<?= $order['status'] === 'paid' ? '✓ PAID' : '⌛ UNPAID' ?>
|
||
</span>
|
||
<?php endif; ?>
|
||
|
||
<?php if ($isCreator || (int)$order['user_id'] === (int)$currentUser['id']): ?>
|
||
<form method="POST" action="/employee-orders/<?= e($order['id']) ?>/delete" style="display: inline; margin-left: 0.35rem;" onsubmit="return confirm('Cancel this order?');">
|
||
<?= \App\Core\View::csrfField() ?>
|
||
<input type="hidden" name="session_id" value="<?= e($session['id']) ?>">
|
||
<button type="submit" style="background: none; border: none; color: var(--danger); font-size: 0.8rem; cursor: pointer;">✕</button>
|
||
</form>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<!-- Right Column: Host Tools (Recap, Settlement, Menu Management) -->
|
||
<div>
|
||
|
||
<!-- 1. Canteen Recap (1-Click Copy for Canteen Placement) -->
|
||
<div class="card" x-data="canteenRecapHelper()">
|
||
<div class="card-header" style="background: #f0fdf4; border-bottom: 1px solid #bbf7d0;">
|
||
<div>
|
||
<h2 class="card-title" style="color: #166534;">📦 Canteen Order Summary</h2>
|
||
<p style="font-size: 0.8rem; color: #15803d;">Grouped quantities for ordering</p>
|
||
</div>
|
||
<button type="button" class="btn btn-sm btn-success" @click="copyCanteenText()">
|
||
📋 <span x-text="copyBtnText">Copy Canteen Text</span>
|
||
</button>
|
||
</div>
|
||
|
||
<div class="card-body">
|
||
<?php if (empty($session['recap'])): ?>
|
||
<p style="color: var(--text-muted); font-size: 0.875rem; text-align: center; padding: 1rem;">
|
||
No items ordered yet.
|
||
</p>
|
||
<?php else: ?>
|
||
<div style="display: flex; flex-direction: column; gap: 0.5rem; margin-bottom: 1rem;">
|
||
<?php foreach ($session['recap'] as $recap): ?>
|
||
<div style="display: flex; justify-content: space-between; align-items: flex-start; padding: 0.4rem 0; border-bottom: 1px dashed var(--border-color);">
|
||
<div>
|
||
<span style="font-weight: 700; color: var(--primary); font-size: 0.95rem;"><?= e($recap['total_quantity']) ?>x</span>
|
||
<strong style="margin-left: 0.35rem; font-size: 0.9rem;"><?= e($recap['item_name']) ?></strong>
|
||
<?php if (!empty($recap['combined_notes'])): ?>
|
||
<div style="font-size: 0.775rem; color: var(--text-muted); margin-left: 1.5rem;">
|
||
Note: <?= e($recap['combined_notes']) ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<textarea x-ref="recapText" style="display: none;"><?= e(generateCanteenCopyText($session)) ?></textarea>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 2. End-of-Day Food Arrival & Bill Settlement (Available for Host) -->
|
||
<?php if ($isCreator): ?>
|
||
<div class="card" style="border: 2px solid #3b82f6;" x-data="mattermostRecapHelper()">
|
||
<div class="card-header" style="background: #eff6ff; border-bottom: 1px solid #bfdbfe;">
|
||
<div>
|
||
<h2 class="card-title" style="color: #1e40af;">💰 Settle Canteen Bill (Arrival)</h2>
|
||
<p style="font-size: 0.8rem; color: #1e3a8a;">Enter final receipt prices to compute everyone's bill</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card-body">
|
||
<form method="POST" action="/sessions/<?= e($session['id']) ?>/settle-prices">
|
||
<?= \App\Core\View::csrfField() ?>
|
||
|
||
<div style="display: flex; flex-direction: column; gap: 0.6rem; margin-bottom: 1rem;">
|
||
<?php foreach ($session['menus'] as $menu): ?>
|
||
<div style="display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; font-size: 0.875rem;">
|
||
<span style="flex: 1; font-weight: 500;"><?= e($menu['name']) ?>:</span>
|
||
<div style="display: flex; align-items: center; gap: 0.25rem;">
|
||
<span style="color: var(--text-muted);">$</span>
|
||
<input type="number"
|
||
step="0.01"
|
||
min="0"
|
||
name="prices[<?= e($menu['id']) ?>]"
|
||
class="form-control"
|
||
style="width: 90px; padding: 0.25rem 0.5rem; text-align: right;"
|
||
value="<?= (float)$menu['final_price'] > 0 ? e($menu['final_price']) : '' ?>"
|
||
placeholder="0.00">
|
||
</div>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
|
||
<button type="submit" class="btn btn-primary" style="width: 100%; font-size: 0.9rem;">
|
||
⚡ Save Prices & Compute All Bills
|
||
</button>
|
||
</form>
|
||
|
||
<?php if (array_sum(array_column($session['orders'], 'total_bill')) > 0): ?>
|
||
<div style="margin-top: 1.25rem; border-top: 1px solid var(--border-color); padding-top: 1rem;">
|
||
<button type="button" class="btn btn-secondary" style="width: 100%; font-size: 0.85rem;" @click="copyMattermostText()">
|
||
📢 <span x-text="mmBtnText">Copy Mattermost Billing Breakdown</span>
|
||
</button>
|
||
<textarea x-ref="mattermostText" style="display: none;"><?= e(generateMattermostBillText($session)) ?></textarea>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 3. Host Menu Manager -->
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h2 class="card-title">📝 Menu Options Manager</h2>
|
||
</div>
|
||
<div class="card-body">
|
||
<form method="POST" action="/sessions/<?= e($session['id']) ?>/add-menu">
|
||
<?= \App\Core\View::csrfField() ?>
|
||
<div class="form-group">
|
||
<label class="form-label" style="font-size: 0.85rem;">Add More Items (Paste line by line):</label>
|
||
<textarea name="menu_text" class="form-textarea" rows="2" placeholder="e.g. Extra Kerupuk Es Kopi Susu" required></textarea>
|
||
</div>
|
||
<button type="submit" class="btn btn-secondary btn-sm" style="width: 100%;">+ Add to Menu</button>
|
||
</form>
|
||
|
||
<?php if (!empty($session['menus'])): ?>
|
||
<div style="margin-top: 1rem; border-top: 1px solid var(--border-color); padding-top: 0.75rem;">
|
||
<ul style="list-style: none; display: flex; flex-direction: column; gap: 0.35rem;">
|
||
<?php foreach ($session['menus'] as $m): ?>
|
||
<li style="display: flex; justify-content: space-between; align-items: center; font-size: 0.85rem; padding: 0.25rem 0;">
|
||
<span>• <?= e($m['name']) ?></span>
|
||
<form method="POST" action="/sessions/<?= e($session['id']) ?>/delete-menu" style="display: inline;">
|
||
<?= \App\Core\View::csrfField() ?>
|
||
<input type="hidden" name="menu_id" value="<?= e($m['id']) ?>">
|
||
<button type="submit" style="background: none; border: none; color: var(--text-muted); cursor: pointer; font-size: 0.9rem;" title="Delete item">×</button>
|
||
</form>
|
||
</li>
|
||
<?php endforeach; ?>
|
||
</ul>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<!-- Alpine.js Multi-Select Form Logic -->
|
||
<script>
|
||
function canteenOrderForm() {
|
||
<?php
|
||
$initialItems = [];
|
||
if (!empty($myOrder['items'])) {
|
||
foreach ($myOrder['items'] as $item) {
|
||
$initialItems[] = [
|
||
'id' => $item['session_menu_id'] ? (int)$item['session_menu_id'] : null,
|
||
'name' => $item['item_name'],
|
||
'quantity' => (int)$item['quantity'],
|
||
'notes' => $item['notes'] ?? '',
|
||
];
|
||
}
|
||
}
|
||
?>
|
||
return {
|
||
selectedItems: <?= json_encode($initialItems) ?>,
|
||
|
||
isSelected(menuId) {
|
||
return this.selectedItems.some(i => i.id === menuId);
|
||
},
|
||
|
||
toggleItem(menuId, menuName) {
|
||
const idx = this.selectedItems.findIndex(i => i.id === menuId);
|
||
if (idx >= 0) {
|
||
this.selectedItems.splice(idx, 1);
|
||
} else {
|
||
this.selectedItems.push({
|
||
id: menuId,
|
||
name: menuName,
|
||
quantity: 1,
|
||
notes: ''
|
||
});
|
||
}
|
||
},
|
||
|
||
removeItem(index) {
|
||
this.selectedItems.splice(index, 1);
|
||
},
|
||
|
||
validateSubmit(e) {
|
||
if (this.selectedItems.length === 0) {
|
||
alert('Please click on at least one menu item to select it!');
|
||
e.preventDefault();
|
||
return;
|
||
}
|
||
}
|
||
};
|
||
}
|
||
|
||
function canteenRecapHelper() {
|
||
return {
|
||
copyBtnText: 'Copy Canteen Text',
|
||
copyCanteenText() {
|
||
const text = this.$refs.recapText.value;
|
||
navigator.clipboard.writeText(text).then(() => {
|
||
this.copyBtnText = '✓ Copied to Clipboard!';
|
||
setTimeout(() => this.copyBtnText = 'Copy Canteen Text', 2500);
|
||
});
|
||
}
|
||
};
|
||
}
|
||
|
||
function mattermostRecapHelper() {
|
||
return {
|
||
mmBtnText: 'Copy Mattermost Breakdown',
|
||
copyMattermostText() {
|
||
const text = this.$refs.mattermostText.value;
|
||
navigator.clipboard.writeText(text).then(() => {
|
||
this.mmBtnText = '✓ Mattermost Summary Copied!';
|
||
setTimeout(() => this.mmBtnText = 'Copy Mattermost Breakdown', 2500);
|
||
});
|
||
}
|
||
};
|
||
}
|
||
</script>
|
||
|
||
<?php
|
||
function generateCanteenCopyText(array $session): string {
|
||
$out = "🍱 *Order Makan Siang - " . $session['title'] . "*\n";
|
||
$out .= "Canteen: " . $session['canteen_name'] . " (" . $session['session_date'] . ")\n\n";
|
||
$out .= "Rekap Pesanan:\n";
|
||
foreach ($session['recap'] as $r) {
|
||
$out .= "- " . $r['total_quantity'] . "x " . $r['item_name'];
|
||
if (!empty($r['combined_notes'])) {
|
||
$out .= " (" . $r['combined_notes'] . ")";
|
||
}
|
||
$out .= "\n";
|
||
}
|
||
$totalQty = array_sum(array_column($session['recap'], 'total_quantity'));
|
||
$out .= "\nTotal: " . $totalQty . " item(s). Terima kasih!";
|
||
return $out;
|
||
}
|
||
|
||
function generateMattermostBillText(array $session): string {
|
||
$out = "📢 **Tagihan Makan Siang (" . $session['title'] . ")**\n\n";
|
||
$out .= "| Nama | Pesanan | Total Tagihan | Status |\n";
|
||
$out .= "|:---|:---|:---|:---|\n";
|
||
|
||
foreach ($session['orders'] as $o) {
|
||
$itemList = [];
|
||
foreach ($o['items'] as $i) {
|
||
$itemList[] = $i['quantity'] . "x " . $i['item_name'];
|
||
}
|
||
$tag = !empty($o['mattermost_username']) ? "@" . $o['mattermost_username'] : $o['user_name'];
|
||
$status = $o['status'] === 'paid' ? "✅ Lunas" : "⏳ Belum";
|
||
$out .= "| " . $tag . " | " . implode(', ', $itemList) . " | " . money($o['total_bill']) . " | " . $status . " |\n";
|
||
}
|
||
|
||
$totalBill = array_sum(array_column($session['orders'], 'total_bill'));
|
||
$out .= "\n**Total Keseluruhan:** " . money($totalBill) . "\n";
|
||
$out .= "Mohon transfer/bayar ke " . $session['creator_name'] . " ya. Terima kasih! 🙏";
|
||
return $out;
|
||
}
|
||
?>
|