{#if pageState === 'loading'}
{:else if pageState === 'authorized' && weekStart}

Schedule

{formatWeekLabel(weekStart)}
{#if loading}
{:else}
{#each getWeekDays(weekStart) as day, dayIdx (formatDate(day))} {@const isToday = formatDate(day) === todayStr}
{dayHeaders[dayIdx]}
{day.getDate()}
{/each}
{#each timeRange.hours as h (h)}
{formatHour(h)}
{/each}
{#each timeRange.hours as h (h)}
{#each getWeekDays(weekStart) as day (formatDate(day))} {@const dateStr = formatDate(day)} {@const isToday = dateStr === todayStr} {@const dayBookings = bookingsByDate.get(dateStr) || []} {@const dayBlockers = blockersByDate.get(dateStr) || []}
{#each dayBlockers.filter((b) => new SvelteDate(b.start_time).getHours() === h) as b (b.id)} {@const startMinutes = new SvelteDate(b.start_time).getMinutes()} {@const topOffset = (startMinutes / 60) * HOUR_HEIGHT} {@const heightPx = Math.max((b.duration_minutes / 60) * HOUR_HEIGHT, 20)}
{b.description || 'Blocker'}
{#if heightPx > 36}
{formatTimeShort(b.start_time)} · {formatDuration( b.duration_minutes )}
{/if}
{/each} {#each dayBookings.filter((b) => new SvelteDate(b.start_time).getHours() === h) as b (b.id)} {@const startMinutes = new SvelteDate(b.start_time).getMinutes()} {@const topOffset = (startMinutes / 60) * HOUR_HEIGHT} {@const heightPx = Math.max((b.duration_minutes / 60) * HOUR_HEIGHT, 20)} {@const isCancelled = b.status === 'client_cancelled' || b.status === 'we_cancelled' || b.status === 'no_show'} {@const hasOverlap = isCancelled && dayBookings.some( (other) => other.id !== b.id && !( other.status === 'client_cancelled' || other.status === 'we_cancelled' || other.status === 'no_show' ) && bookingsOverlap(b, other) )} {#if !hasOverlap} {/if} {/each}
{/each}
{/each}
{#each getWeekDays(weekStart) as day, dayIdx (formatDate(day))} {@const dateStr = formatDate(day)} {@const wh = workingHours.find((w) => w.date === dateStr)} {@const colLeft = `calc(${dayIdx} * (100% / 7))`} {@const colWidth = `calc(100% / 7)`} {#if !wh?.isOpen}
Closed
{:else} {@const openPx = gridPxFromTime(wh.startTime, timeRange.minStart)} {@const closePx = gridPxFromTime(wh.endTime, timeRange.minStart)} {#if openPx > 0}
{/if} {#if closePx < timeRange.hours.length * SLOT_HEIGHT}
{/if}
{/if} {/each} {#if isCurrentWeek} {@const nowTime = `${String(Math.floor(nowMinutes / 60)).padStart(2, '0')}:${String(nowMinutes % 60).padStart(2, '0')}`} {@const nowPx = gridPxFromTime(nowTime, timeRange.minStart)} {@const todayIdx = getWeekDays(weekStart!).findIndex( (d) => formatDate(d) === todayStr )} {@const colLeft = `calc(${todayIdx} * (100% / 7))`} {@const colWidth = `calc(100% / 7)`} {#if nowPx >= 0 && nowPx <= timeRange.hours.length * SLOT_HEIGHT && todayIdx !== -1}
{/if} {/if}
{/if}
{/if}