Skip to content

Commit 766738f

Browse files
chrisbbreuerclaude
andcommitted
fix(dashboard): batch sweep — 48 pages with rendering bugs
Five distinct categories of issues caused by inconsistent template patterns across the dashboard. All fixed in one pass so the next audit starts from a clean baseline: **1. Wrong @foreach syntax (3 pages)** — `/insights`, `/logs`, `/errors` used `@foreach(item in items)` (Vue/JS style). STX is Laravel-style: `@foreach(items as item)`. The wrong form left the literal `@foreach(...)` string in the rendered HTML — the user saw template directives leaking into the page body. Converted 9 occurrences total via regex sweep. **2. Bare `<script>` instead of `<script server>` (7 pages)** — `/access-tokens`, `/actions`, `/buddy`, `/commands`, `/environment`, `/releases`, `/[...all]`. STX only extracts SSR variables from `<script server>`; bare `<script>` is treated as client-only. Result: every `{{ }}` interpolation against a script-defined const rendered empty, and `@foreach`/`@if` directives saw an empty context. Converted with awk so we only flip the FIRST `<script>` (client `<script>` blocks lower in each file are intentionally untouched). **3. Function references in @foreach (35 pages, ~30 occurrences)** — The most common bug, by a wide margin. Pages that had `function paginatedPosts()` / `function filteredOrders()` / `function categoriesForFilter()` etc. were used as `@foreach(paginatedPosts as post)` instead of `@foreach(paginatedPosts() as post)`. STX iterated the function object itself, which isn't iterable, and rendered `[Foreach Error]: paginatedPosts is not iterable` on every page. Affected dirs: `/commerce/{coupons,gift-cards,manufacturers, orders,payments,pos,printers/{devices,receipts},products{,/detail}, reviews,taxes,units,variants,waitlist/{products,restaurant}}`, `/content/{authors,categories,comments,files,posts,seo,tags}`, `/data/{activity,dashboard}`, `/jobs/history`, `/management/permissions`, `/marketing/{campaigns,lists,reviews,social-posts}`, `/notifications/{email,history,sms}`, `/queries/{history,slow}`, `/realtime`, `/inbox`. Fixed via two-pass sweep that detected function declarations in the same file as the `@foreach` and appended `()` to the call site. **4. Stale 2024 hard-coded dates (`/analytics/events`)** — replaced the pre-baked "Feb 5, 2024 to Mar 6, 2024" date-range strings with a `formatRangeLabel(days)` helper that computes from `new Date()` so the placeholder doesn't ship out of date. **5. Duplicate insertion of `()` from prior foreach pass** — several pages now have idempotent `funcName()` invocations after the regex sweep ran across already-corrected files; rerunning the sweep is a no-op (verified with a second pass that produced 0 changes). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 9e59815 commit 766738f

48 files changed

Lines changed: 108 additions & 88 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

storage/framework/defaults/views/dashboard/[...all].stx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
@extends('layouts/default')
22

33
@section('content')
4-
<script>
4+
<script server>
55
</script>
66

77
<main>

storage/framework/defaults/views/dashboard/access-tokens/index.stx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
@extends('layouts/default')
22

33
@section('content')
4-
<script>
4+
<script server>
55
const tokens = [
66
{
77
name: 'Mobile App Token',

storage/framework/defaults/views/dashboard/actions/index.stx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
@extends('layouts/default')
22

33
@section('content')
4-
<script>
4+
<script server>
55
</script>
66

77
<div class="py-4 lg:py-8 min-h-screen dark:bg-neutral-800">

storage/framework/defaults/views/dashboard/analytics/events/index.stx

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,18 @@ const dateRanges: DateRange[] = [
6262

6363
// Selected date range
6464
let selectedDateRange = 'last30days'
65-
let dateRangeDisplay = 'Last 30 Days: Feb 5, 2024 to Mar 6, 2024'
65+
66+
// Compute the date-range label from "now" so the placeholder doesn't
67+
// ship looking out of date. Real data should replace this once the
68+
// analytics backend is wired up.
69+
function formatRangeLabel(days) {
70+
const fmt = (d) => d.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })
71+
const end = new Date()
72+
const start = new Date()
73+
start.setDate(end.getDate() - days)
74+
return `Last ${days} Days: ${fmt(start)} to ${fmt(end)}`
75+
}
76+
let dateRangeDisplay = formatRangeLabel(30)
6677
let comparisonType = 'no-comparison'
6778
let customStartDate = ''
6879
let customEndDate = ''
@@ -346,23 +357,32 @@ function updateDataForDateRange() {
346357
console.log('Updating data for date range:', selectedDateRange)
347358
console.log('Comparison type:', comparisonType)
348359

349-
// Update date range display
360+
// Update date range display. Computed from "now" so the labels stay
361+
// accurate without anyone editing this file every quarter.
362+
const fmt = (d) => d.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })
363+
const now = new Date()
364+
const daysAgo = (n) => { const d = new Date(); d.setDate(d.getDate() - n); return d }
350365
if (selectedDateRange === 'last7days') {
351-
dateRangeDisplay = 'Last 7 Days: Feb 28, 2024 to Mar 6, 2024'
366+
dateRangeDisplay = `Last 7 Days: ${fmt(daysAgo(7))} to ${fmt(now)}`
352367
} else if (selectedDateRange === 'last30days') {
353-
dateRangeDisplay = 'Last 30 Days: Feb 5, 2024 to Mar 6, 2024'
368+
dateRangeDisplay = formatRangeLabel(30)
354369
} else if (selectedDateRange === 'thisMonth') {
355-
dateRangeDisplay = 'This Month: Mar 1, 2024 to Mar 6, 2024'
370+
const start = new Date(now.getFullYear(), now.getMonth(), 1)
371+
dateRangeDisplay = `This Month: ${fmt(start)} to ${fmt(now)}`
356372
} else if (selectedDateRange === 'lastMonth') {
357-
dateRangeDisplay = 'Last Month: Feb 1, 2024 to Feb 29, 2024'
373+
const start = new Date(now.getFullYear(), now.getMonth() - 1, 1)
374+
const end = new Date(now.getFullYear(), now.getMonth(), 0)
375+
dateRangeDisplay = `Last Month: ${fmt(start)} to ${fmt(end)}`
358376
} else if (selectedDateRange === 'thisYear') {
359-
dateRangeDisplay = 'This Year: Jan 1, 2024 to Mar 6, 2024'
377+
const start = new Date(now.getFullYear(), 0, 1)
378+
dateRangeDisplay = `This Year: ${fmt(start)} to ${fmt(now)}`
360379
} else if (selectedDateRange === 'custom' && customStartDate && customEndDate) {
361380
const start = formatDate(customStartDate)
362381
const end = formatDate(customEndDate)
363382
dateRangeDisplay = `Custom Range: ${start} to ${end}`
364383
} else {
365-
dateRangeDisplay = 'All Time: Sep 7, 2023 to Mar 6, 2024'
384+
const start = new Date(now.getFullYear() - 1, now.getMonth(), now.getDate())
385+
dateRangeDisplay = `All Time: ${fmt(start)} to ${fmt(now)}`
366386
}
367387

368388
// Generate comparison data if needed
@@ -641,7 +661,7 @@ function handleComparisonTypeChange() {
641661
</tr>
642662
</thead>
643663
<tbody class="divide-gray-200 divide-y dark:divide-neutral-700">
644-
@foreach(activeEvents as event)
664+
@foreach(activeEvents() as event)
645665
<tr
646666
class="hover:bg-gray-50 dark:hover:bg-neutral-700/50 cursor-pointer"
647667
onclick="viewEventDetails(event)"
@@ -830,7 +850,7 @@ window.addEventListener('load', () => {
830850
</tr>
831851
</thead>
832852
<tbody class="divide-gray-200 divide-y dark:divide-neutral-700">
833-
@foreach(blockedEvents as event)
853+
@foreach(blockedEvents() as event)
834854
<tr
835855
class="hover:bg-gray-50 dark:hover:bg-neutral-700/50"
836856
>

storage/framework/defaults/views/dashboard/buddy/index.stx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
@extends('layouts/default')
22

33
@section('content')
4-
<script>
4+
<script server>
55
interface User {
66
id: number
77
name: string

storage/framework/defaults/views/dashboard/commands/index.stx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
@extends('layouts/default')
22

33
@section('content')
4-
<script>
4+
<script server>
55
</script>
66

77
<div class="py-4 lg:py-8 min-h-screen dark:bg-neutral-800">

storage/framework/defaults/views/dashboard/commerce/gift-cards/index.stx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ async function addGiftCard() {
461461
</tr>
462462
</thead>
463463
<tbody class="bg-white dark:bg-neutral-800 divide-gray-200 divide-y dark:divide-neutral-700">
464-
@foreach(filteredGiftCards as card)
464+
@foreach(filteredGiftCards() as card)
465465
<tr>
466466
<td class="pl-4 pr-3 py-4 sm:pl-6 font-medium text-gray-900 text-sm whitespace-nowrap dark:text-white">
467467
{{ card.code }}

storage/framework/defaults/views/dashboard/commerce/manufacturers/index.stx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ function addManufacturer() {
255255
class="block pl-3 pr-10 py-1.5 w-full text-gray-900 sm:leading-6 sm:text-sm dark:text-white dark:bg-neutral-800 border-0 ring-1 ring-gray-300 ring-inset rounded-md dark:ring-neutral-700 focus:ring-2 focus:ring-blue-600 focus:ring-inset"
256256
>
257257
<option value="all">All Countries</option>
258-
@foreach(countries as country)
258+
@foreach(countries() as country)
259259
<option value="{{ country }}">{{ country }}</option>
260260
@endforeach
261261
</select>
@@ -338,7 +338,7 @@ function addManufacturer() {
338338
</tr>
339339
</thead>
340340
<tbody class="bg-white dark:bg-neutral-800 divide-gray-200 divide-y dark:divide-neutral-700">
341-
@foreach(filteredManufacturers as manufacturer)
341+
@foreach(filteredManufacturers() as manufacturer)
342342
<tr>
343343
<td class="pl-4 pr-3 py-4 sm:pl-6 font-medium text-gray-900 text-sm whitespace-nowrap dark:text-white">
344344
{{ manufacturer.name }}

storage/framework/defaults/views/dashboard/commerce/payments/index.stx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ function totalAmount() {
547547
</tr>
548548
</thead>
549549
<tbody class="bg-white dark:bg-neutral-800 divide-gray-200 divide-y dark:divide-neutral-700">
550-
@foreach(paginatedTransactions as transaction)
550+
@foreach(paginatedTransactions() as transaction)
551551
<tr>
552552
<td class="pl-4 pr-3 py-4 sm:pl-6 font-medium text-gray-900 text-sm whitespace-nowrap dark:text-white">
553553
{{ transaction.orderId }}

storage/framework/defaults/views/dashboard/commerce/pos/index.stx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ function scrollToOrder(): void {
605605
@else
606606
<div class="grid gap-6 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
607607
<!-- Menu item card -->
608-
@foreach(filteredMenuItems as item)
608+
@foreach(filteredMenuItems() as item)
609609
<div
610610
class="overflow-hidden relative bg-white dark:bg-neutral-800 border border-gray-200 rounded-lg dark:border-neutral-700 shadow-sm hover:shadow-md transition group"
611611
class="!item.available 'opacity-70': { {{ } }}"
@@ -710,7 +710,7 @@ function scrollToOrder(): void {
710710
</td>
711711
</tr>
712712
@endif
713-
@foreach(filteredMenuItems as item)
713+
@foreach(filteredMenuItems() as item)
714714
<tr class="hover:bg-gray-50 dark:hover:bg-neutral-700" class="!item.available 'opacity-70': { {{ } }}">
715715
<td class="pl-4 pr-3 py-4 sm:pl-6 text-sm whitespace-nowrap">
716716
<div class="flex items-center">

0 commit comments

Comments
 (0)