Diff -- /var/www/vhosts/3dshawn.com/repricer.3dshawn.com/TEMPLATES/repricer_calendar.html
Diff
/var/www/vhosts/3dshawn.com/repricer.3dshawn.com/TEMPLATES/repricer_calendar.html
added on local at 2026-07-01 21:47:24
Added
+123
lines
Removed
-0
lines
Context
0
unchanged
Blobs
from
to 58577e4f26b0
to 58577e4f26b0
Unified diff
Naive LCS-based line diff. Additions in emerald, deletions in rose. Both sides decompressed live from BLOB_STORE.| 1 | <style> | |
| 2 | .cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 0; background: transparent; border: 1px solid rgba(5,150,105,0.45); border-radius: var(--radius, 8px); overflow: hidden; } | |
| 3 | .cal-head { background: var(--col-bg-1); padding: 8px 10px; font-size: 11px; text-transform: uppercase; color: var(--col-text-muted, var(--col-text-dim)); font-weight: 600; letter-spacing: .05em; border-right: 1px solid rgba(5,150,105,0.45); border-bottom: 1px solid rgba(5,150,105,0.45); } | |
| 4 | .cal-head:nth-child(7) { border-right: none; } | |
| 5 | .cal-cell { background: linear-gradient(135deg, rgba(5,150,105,0.18) 0%, rgba(5,150,105,0.12) 100%); height: 130px; padding: 6px 8px; position: relative; font-size: 12px; overflow: hidden; cursor: pointer; transition: background 0.18s; border-right: 1px solid rgba(5,150,105,0.45); border-bottom: 1px solid rgba(5,150,105,0.45); } | |
| 6 | .cal-cell:nth-child(7n) { border-right: none; } | |
| 7 | .cal-cell:hover { background: linear-gradient(135deg, rgba(5,150,105,0.28) 0%, rgba(5,150,105,0.20) 100%); } | |
| 8 | .cal-cell.out { background: var(--col-bg-1); color: var(--col-text-dim); cursor: default; } | |
| 9 | .cal-cell.out:hover { background: var(--col-bg-1); } | |
| 10 | .cal-cell.today { background: var(--col-primary-soft, rgba(90,169,255,0.10)); } | |
| 11 | .cal-day-num { font-weight: 600; color: var(--col-text); font-size: 13px; } | |
| 12 | .cal-cell.out .cal-day-num { color: var(--col-text-dim); } | |
| 13 | .cal-cell.today .cal-day-num { color: var(--col-primary); } | |
| 14 | .cal-evt-item { display: block; margin-top: 4px; padding: 3px 6px; border-radius: 4px; background: var(--col-bg-3, rgba(255,255,255,0.04)); color: var(--col-text); font-size: 11.5px; border-left: 3px solid var(--col-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } | |
| 15 | .cal-more { display: block; margin-top: 4px; font-size: 11px; color: var(--col-primary); font-weight: 600; } | |
| 16 | /* Overlay */ | |
| 17 | .cal-overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.65); z-index: 1000; align-items: flex-start; justify-content: center; padding-top: 60px; } | |
| 18 | .cal-overlay.open { display: flex; } | |
| 19 | .cal-overlay-card { background: var(--col-surface); border: 1px solid var(--col-border); border-radius: 12px; width: 100%; max-width: 600px; max-height: 80vh; overflow-y: auto; padding: 22px 24px; } | |
| 20 | .cal-overlay-head { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 14px; } | |
| 21 | .cal-overlay-head h2 { margin: 0; font-size: 22px; } | |
| 22 | .cal-overlay-close { background: none; border: none; color: var(--col-text-dim); cursor: pointer; font-size: 22px; padding: 0; line-height: 1; } | |
| 23 | .cal-overlay-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 18px; } | |
| 24 | .cal-overlay-item { display: flex; gap: 10px; padding: 10px 12px; background: var(--col-bg-3, rgba(255,255,255,0.04)); border-left: 3px solid var(--col-primary); border-radius: 6px; color: var(--col-text); align-items: center; } | |
| 25 | .cal-overlay-item .meta { font-size: 11px; color: var(--col-text-dim); } | |
| 26 | .cal-overlay-item form { margin-left: auto; } | |
| 27 | .cal-add-form { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; padding-top: 14px; border-top: 1px solid var(--col-border); } | |
| 28 | .cal-add-form input, .cal-add-form select, .cal-add-form textarea { padding: 8px 10px; border-radius: 6px; border: 1px solid var(--col-border); background: var(--col-surface-2, var(--col-bg-3)); color: var(--col-text); font-family: inherit; font-size: 13px; } | |
| 29 | .cal-add-form .full { grid-column: 1 / -1; } | |
| 30 | .cal-add-form button { padding: 8px 14px; } | |
| 31 | </style> | |
| 32 | <div class="page-header"> | |
| 33 | <div><h1>Calendar</h1><p class="subtitle">$month_label $y · click a day to view or add an event.</p></div> | |
| 34 | <div class="flex-end"> | |
| 35 | <a class="btn btn-sm[if:$scope_me] btn-primary[/if][if:!$scope_me] btn-ghost[/if]" href="/calendar.cgi?y=$y&m=$m&scope=me">My events</a> | |
| 36 | [if:$has_my_team]<a class="btn btn-sm[if:$scope_my_team] btn-primary[/if][if:!$scope_my_team] btn-ghost[/if]" href="/calendar.cgi?y=$y&m=$m&scope=my_team">My team</a>[/if] | |
| 37 | [if:$has_division]<a class="btn btn-sm[if:$scope_division] btn-primary[/if][if:!$scope_division] btn-ghost[/if]" href="/calendar.cgi?y=$y&m=$m&scope=division">My division</a>[/if] | |
| 38 | [if:$is_admin]<a class="btn btn-sm[if:$scope_team] btn-primary[/if][if:!$scope_team] btn-ghost[/if]" href="/calendar.cgi?y=$y&m=$m&scope=team">Workspace events</a>[/if] | |
| 39 | <a class="btn btn-ghost btn-sm" href="/calendar.cgi?y=$py&m=$pm">← $pm/$py</a> | |
| 40 | <a class="btn btn-ghost btn-sm" href="/calendar.cgi">Today</a> | |
| 41 | <a class="btn btn-ghost btn-sm" href="/calendar.cgi?y=$ny&m=$nm">$nm/$ny →</a> | |
| 42 | </div> | |
| 43 | </div> | |
| 44 | ||
| 45 | <div class="cal-grid"> | |
| 46 | <div class="cal-head">Sun</div><div class="cal-head">Mon</div><div class="cal-head">Tue</div><div class="cal-head">Wed</div><div class="cal-head">Thu</div><div class="cal-head">Fri</div><div class="cal-head">Sat</div> | |
| 47 | [loop:@cells] | |
| 48 | <div class="cal-cell[if:!$loop1.in_month] out[/if][if:$loop1.is_today] today[/if][if:$loop1.is_weekend] weekend[/if]" data-date="$loop1.d_str"> | |
| 49 | <div class="cal-day-num">$loop1.day_num</div> | |
| 50 | [if:$loop1.has_events] | |
| 51 | [loop:@loop1.events_top] | |
| 52 | <div class="cal-evt-item" style="border-left-color:$loop2.color" title="$loop2.kind">$loop2.title</div> | |
| 53 | [/loop] | |
| 54 | [if:$loop1.more_count]<a class="cal-more" href="#">+$loop1.more_count more</a>[/if] | |
| 55 | [/if] | |
| 56 | </div> | |
| 57 | [/loop] | |
| 58 | </div> | |
| 59 | ||
| 60 | <div class="cal-overlay" id="cal-overlay"> | |
| 61 | <div class="cal-overlay-card"> | |
| 62 | <div class="cal-overlay-head"> | |
| 63 | <h2 id="cal-overlay-date">-</h2> | |
| 64 | <button class="cal-overlay-close" onclick="closeCalOverlay()">×</button> | |
| 65 | </div> | |
| 66 | <div class="cal-overlay-list" id="cal-overlay-list"></div> | |
| 67 | <form class="cal-add-form" method="POST" action="/calendar.cgi"> | |
| 68 | <input type="hidden" name="act" value="create"> | |
| 69 | <input type="hidden" name="event_date" id="cal-add-due"> | |
| 70 | <input type="hidden" name="back" value="/calendar.cgi?y=$y&m=$m"> | |
| 71 | <select name="kind" id="cal-add-kind"> | |
| 72 | <option value="reprice_rule">Repricing rule check</option><option value="marketplace_review">Marketplace review</option><option value="competitor_audit">Competitor audit</option><option value="meeting">Meeting</option><option value="other">Other</option> | |
| 73 | </select> | |
| 74 | <input type="text" name="title" placeholder="Title (e.g. ship product, call lead)..." required> | |
| 75 | <textarea class="full" name="notes" placeholder="Notes (optional)" rows="2"></textarea> | |
| 76 | <button type="submit" class="btn btn-primary full">Add to this day</button> | |
| 77 | </form> | |
| 78 | </div> | |
| 79 | </div> | |
| 80 | ||
| 81 | <script> | |
| 82 | (function(){ | |
| 83 | var overlay = document.getElementById('cal-overlay'); | |
| 84 | var dateLabel = document.getElementById('cal-overlay-date'); | |
| 85 | var listEl = document.getElementById('cal-overlay-list'); | |
| 86 | var dueInput = document.getElementById('cal-add-due'); | |
| 87 | var dayData = $cells_json; | |
| 88 | document.querySelectorAll('.cal-cell:not(.out)').forEach(function(cell){ | |
| 89 | cell.addEventListener('click', function(e){ | |
| 90 | var d = cell.dataset.date; | |
| 91 | openCalOverlay(d); | |
| 92 | }); | |
| 93 | }); | |
| 94 | function openCalOverlay(dstr) { | |
| 95 | var data = dayData[dstr] || {events: []}; | |
| 96 | dateLabel.textContent = dstr; | |
| 97 | dueInput.value = dstr; | |
| 98 | listEl.innerHTML = ''; | |
| 99 | if (!data.events.length) { | |
| 100 | listEl.innerHTML = '<div style="color:var(--col-text-dim);font-size:13px;padding:10px 0">No events on this day. Add one below.</div>'; | |
| 101 | } else { | |
| 102 | data.events.forEach(function(ev){ | |
| 103 | var div = document.createElement('div'); | |
| 104 | div.className = 'cal-overlay-item'; | |
| 105 | div.style.borderLeftColor = ev.color || '#5aa9ff'; | |
| 106 | div.innerHTML = '<div style="flex:1"><div style="font-weight:600">' + escapeHtml(ev.title) + '</div><div class="meta">' + escapeHtml(ev.kind || 'event') + (ev.notes ? ' · ' + escapeHtml(ev.notes) : '') + '</div></div>' + | |
| 107 | '<form method="POST" action="/calendar.cgi" onsubmit="return confirm(\\'Delete this event?\\');">' + | |
| 108 | '<input type="hidden" name="act" value="delete">' + | |
| 109 | '<input type="hidden" name="event_id" value="' + ev.id + '">' + | |
| 110 | '<input type="hidden" name="back" value="/calendar.cgi?y=$y&m=$m">' + | |
| 111 | '<button class="btn btn-ghost btn-sm" type="submit" style="color:#f87171">Delete</button>' + | |
| 112 | '</form>'; | |
| 113 | listEl.appendChild(div); | |
| 114 | }); | |
| 115 | } | |
| 116 | overlay.classList.add('open'); | |
| 117 | } | |
| 118 | window.closeCalOverlay = function(){ overlay.classList.remove('open'); }; | |
| 119 | overlay.addEventListener('click', function(e){ if (e.target === overlay) closeCalOverlay(); }); | |
| 120 | document.addEventListener('keydown', function(e){ if (e.key === 'Escape') closeCalOverlay(); }); | |
| 121 | function escapeHtml(s) { return String(s||'').replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); } | |
| 122 | })(); | |
| 123 | </script> |