true-perfect-code
Version: 1.2.67

P11SlotPlanner Component

The P11SlotPlanner is a high-performance, logic-driven time management engine designed for Blazor WASM and Capacitor. Unlike traditional date-pickers, it uses a zero-latency boolean-map architecture to handle 24h schedules with micro-second precision. Key features include an interactive 'Hollow-Donut' SVG visualization, WCAG-compliant keyboard navigation, and a hybrid data model that allows for both standalone confirmation and real-time parent-state synchronization. Optimized for mobile-first UX, it ensures fluid slot toggling even on low-powered devices.

Single Day Planning

Classic standalone mode with integrated range selection and internal accept button.

Processing hours: 8:00 - 18:00 Range Selection

Weekend Planner

Select slots for Saturday and Sunday. Changes are synced instantly.

Saturday
Sunday

Implementation

<div class="container mt-5">
    <div class="border-bottom mb-4 pb-2">
        <h2 class="fw-bold"><i class="bi bi-clock-history me-2"></i> Single Day Planning</h2>
        <p class="text-muted">Classic standalone mode with integrated range selection and internal accept button.</p>
    </div>

    <P11SlotPlanner SlotSize="15"
                    ViewRangeStartHour="8"
                    ViewRangeEndHour="18"
                    ColorActive="#b02a37"
                    ColorInactive="#e9ecef"
                    ColorAccent="#212529"
                    IsVisibleRangeSelection="true"
                    UseRangeSelector="true"
                    IsVisibleAcceptButton="true"
                    EnableInstantBinding="false"
                    @bind-OccupiedSlotIndices="_myBookings"
                    OnAccept="HandleSave" />
</div>

<hr />

<div class="container mt-5">
    <div class="card shadow-lg border-0">
        <div class="card-header bg-dark text-white p-4">
            <h3 class="mb-0"><i class="bi bi-calendar3-range me-2"></i> Weekend Planner</h3>
            <p class="mb-0 opacity-75">Select slots for Saturday and Sunday. Changes are synced instantly.</p>
        </div>

        <div class="card-body p-4 bg-light">
            <div class="row">
                @* SATURDAY COLUMN *@
                <div class="col-md-6 border-end">
                    <h5 class="fw-bold text-primary mb-3"><i class="bi bi-calendar-event me-2"></i> Saturday</h5>
                    <P11SlotPlanner SlotSize="30"
                                    ViewRangeStartHour="10"
                                    ViewRangeEndHour="22"
                                    ColorActive="#0d6efd"
                                    IsVisibleRangeSelection="false"
                                    IsVisibleAcceptButton="false"
                                    EnableInstantBinding="true"
                                    @bind-OccupiedSlotIndices="_saturdayBookings" />
                </div>

                @* SUNDAY COLUMN *@
                <div class="col-md-6">
                    <h5 class="fw-bold text-danger mb-3"><i class="bi bi-calendar-check me-2"></i> Sunday</h5>
                    <P11SlotPlanner SlotSize="30"
                                    ViewRangeStartHour="10"
                                    ViewRangeEndHour="18"
                                    ColorActive="#dc3545"
                                    IsVisibleRangeSelection="false"
                                    IsVisibleAcceptButton="false"
                                    EnableInstantBinding="true"
                                    @bind-OccupiedSlotIndices="_sundayBookings" />
                </div>
            </div>
        </div>

        @* MASTER ACTION FOOTER *@
        <div class="card-footer bg-white p-4 d-flex justify-content-between align-items-center">
            <div class="text-muted small">
                Total Slots: <strong>@(_saturdayBookings.Count + _sundayBookings.Count)</strong>
            </div>
            <button type="button" class="btn btn-success btn-lg px-5 fw-bold shadow" @onclick="HandleMasterSave">
                SAVE WEEKEND PLAN <i class="bi bi-cloud-upload-fill ms-2"></i>
            </button>
        </div>
    </div>
</div>                  
@code {
    // Initial data: 08:00 (Slot 33 for 15m), 08:30 (Slot 35)
    private List<int> _myBookings = new() { 33, 35 };

    private void HandleSave()
    {
        Console.WriteLine($"--- SAVING SINGLE DAY ---");
        foreach (var slotId in _myBookings.OrderBy(x => x))
        {
            int totalMinutes = (slotId - 1) * 15;
            int h = totalMinutes / 60;
            int m = totalMinutes % 60;
            Console.WriteLine($"Slot: {slotId} ({h:D2}:{m:D2})");
        }
    }


    private List<int> _saturdayBookings = new() { 21, 22 }; // Beispiel-Daten
    private List<int> _sundayBookings = new();

    private void HandleMasterSave()
    {
        // Da EnableInstantBinding="true" ist, sind _saturdayBookings
        // und _sundayBookings bereits auf dem neuesten Stand!

        Console.WriteLine("--- SAVING WEEKEND PLAN ---");

        ProcessDay("Saturday", _saturdayBookings, 30);
        ProcessDay("Sunday", _sundayBookings, 30);
    }

    private void ProcessDay(string dayName, List<int> indices, int slotSize)
    {
        Console.WriteLine($"{dayName} selection:");
        foreach (var slotId in indices.OrderBy(x => x))
        {
            int totalMinutes = (slotId - 1) * slotSize;
            int h = totalMinutes / 60;
            int m = totalMinutes % 60;
            Console.WriteLine($" - Slot: {slotId} ({h:D2}:{m:D2})");
        }
    }
}             


Component API: P11SlotPlanner

Parameter / Event Type Default Description
Core Logic & Data
OccupiedSlotIndices List<int> new() The 1-based indices of selected slots. Primary data source for binding.
SlotSize int 5 Size of a single slot in minutes. Supports 5, 10, 15, 30, 60.
EnableInstantBinding bool false If true, updates the parent immediately on every click without needing 'Accept'.
OccupiedSlotIndicesChanged EventCallback - Fired when the selection changes (manually or via instant binding).
View & UI Control
ViewRangeStartHour int 8 First visible hour in the UI grid (0-23).
ViewRangeEndHour int 18 Last visible hour in the UI grid (1-24).
IsVisibleRangeSelection bool true Toggles the visibility of the time-range adjustment header.
UseRangeSelector bool false Switch between slider-track and dropdown-menus for range selection.
IsVisibleAcceptButton bool true Shows/Hides the footer 'Accept' button.
Styling & Branding
ColorActive string #0d6efd Hex/CSS color for selected slots and active donut segments.
ColorAccent string #0d6efd Accent color for UI highlights like the range track bridge.
CssClass string? null Optional CSS classes for the root container.
Localization (Texts)
TextAcceptButton string? "ACCEPT..." Custom label for the confirmation button.
IconAcceptButton string? "bi-check..." Bootstrap icon class for the confirmation button.
TextProcessingHours string? "Processing..." Label for the active time range display.
An unhandled error has occurred. Reload 🗙