toadstoolTally/index.html

241 lines
14 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Toadstool Cottage Counter</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@600;700&family=Nunito:wght@400;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css" crossorigin="anonymous" referrerpolicy="no-referrer">
<link rel="icon" type="image/png" sizes="32x32" href="assets/icons/appicon-32x32.png">
<link rel="icon" type="image/png" sizes="128x128" href="assets/icons/appicon-128x128.png">
<link rel="apple-touch-icon" href="assets/icons/appicon-256x256.png">
<link rel="manifest" href="assets/site.webmanifest">
<meta name="theme-color" content="#e4e8d5">
<link rel="stylesheet" href="assets/style.css">
</head>
<body>
<header>
<div class="brand">
<img class="brand-icon" src="assets/icons/appicon-128x128.png" alt="Toadstool Cottage Counter icon">
<h1 id="appTitle">Toadstool Cottage Counter</h1>
</div>
<div class="header-controls">
<button class="header-btn hidden" id="installBtn" title="Install app"><i class="fa-solid fa-download"></i></button>
<button class="header-btn" id="motionBtn" onclick="toggleAnimations()" title="Toggle Animations"><i class="fa-solid fa-wand-magic-sparkles"></i></button>
<button class="header-btn" id="themeBtn" onclick="toggleTheme()" title="Toggle Dark Mode"><i class="fa-solid fa-moon"></i></button>
<button class="header-btn" id="focusBtn" onclick="toggleFocusMode()" title="Focus Mode (Keeps Screen On)"><i class="fa-solid fa-eye"></i></button>
<button class="header-btn" id="saveLoadBtn" onclick="openSaveModal()" title="Save/Load"><i class="fa-solid fa-floppy-disk"></i></button>
<button class="header-btn" id="authBtn" onclick="openAuthModal()" title="Sign in to sync"><i class="fa-solid fa-user"></i></button>
</div>
</header>
<input type="file" id="importFile" accept="application/json" class="hidden-input" />
<div class="container" id="app"></div>
<button class="fab" onclick="openModal('addProject')">+</button>
<button class="fab fab-pattern" onclick="openPatternComposer()" title="Open Pattern Composer"><i class="fa-solid fa-swatchbook"></i></button>
<div class="modal-overlay" id="modalOverlay">
<div class="modal-content">
<h3 class="modal-title" id="modalTitle">Title</h3>
<input type="text" class="modal-input" id="modalInput" autocomplete="off">
<div class="pattern-picker" id="patternPicker">
<label for="patternSelect">Pattern (optional)</label>
<select id="patternSelect">
<option value="">No pattern</option>
</select>
</div>
<div class="modal-actions">
<button class="modal-btn btn-cancel" onclick="closeModal()">Cancel</button>
<button class="modal-btn btn-save" onclick="saveModal()">Save</button>
</div>
</div>
</div>
<div class="color-overlay" id="colorOverlay">
<div class="color-modal">
<h3 class="color-title">Pick a color</h3>
<div class="color-grid" id="colorGrid"></div>
<div class="color-custom">
<label for="customColorInput">Custom:</label>
<input type="color" id="customColorInput" />
</div>
<button class="modal-btn btn-cancel" onclick="closeColorPicker()">Close</button>
</div>
</div>
<div class="save-overlay" id="saveOverlay">
<div class="save-modal">
<h3 class="color-title">Save or Load</h3>
<p class="save-subtext">Choose projects to include:</p>
<div class="save-list" id="saveList"></div>
<div class="save-actions">
<button class="modal-btn btn-cancel" onclick="closeSaveModal()">Cancel</button>
<button class="modal-btn btn-save" onclick="exportSelected()">Save</button>
<button class="modal-btn btn-save" onclick="triggerImport()">Load</button>
</div>
<div class="import-selection hidden" id="importSelection">
<p class="save-subtext">Imported file projects:</p>
<div class="save-list" id="importList"></div>
<div class="save-actions">
<button class="modal-btn btn-cancel" onclick="cancelImportSelection()">Cancel</button>
<button class="modal-btn btn-save" onclick="applyImportSelection()">Add Selected</button>
</div>
</div>
</div>
</div>
<div class="auth-overlay" id="authOverlay">
<div class="auth-modal">
<div class="auth-modal-head">
<div>
<h3 class="color-title">Sign in (optional)</h3>
<p class="auth-subtext">Stay free forever. Sign in only if you want cloud backups and device switching.</p>
</div>
<button class="pattern-close" onclick="closeAuthModal()">&times;</button>
</div>
<div class="auth-status">
<span id="authStatusBadge" class="status-pill">Signed out</span>
<span id="authLastSync" class="status-subtext">Last sync: never</span>
</div>
<div class="auth-tabs">
<button class="auth-tab" data-mode="login" onclick="setAuthMode('login')">Login</button>
<button class="auth-tab" data-mode="signup" onclick="setAuthMode('signup')">Sign up</button>
</div>
<form class="auth-form" onsubmit="return submitAuth(event)">
<div class="auth-when-out">
<label class="field-label" for="authEmail">Email</label>
<input id="authEmail" type="email" placeholder="you@example.com" autocomplete="email">
<label class="field-label" for="authPassword">Password</label>
<input id="authPassword" type="password" placeholder="••••••••" autocomplete="current-password">
<p class="auth-hint">Cloud sync is not required. Offline data stays on this device. When enabled, well sync projects/patterns securely.</p>
<div class="auth-actions">
<button type="button" class="modal-btn btn-cancel" onclick="closeAuthModal()">Cancel</button>
<button type="submit" class="modal-btn btn-save">Continue</button>
</div>
</div>
<div class="auth-when-in">
<label class="field-label" for="authDisplayName">Display name</label>
<input id="authDisplayName" type="text" placeholder="Your name">
<label class="field-label" for="authNote">Profile note</label>
<textarea id="authNote" rows="2" placeholder="Add a note for your patterns..."></textarea>
<div class="auth-actions auth-actions-stack">
<button type="button" class="modal-btn btn-save" onclick="autoSync()">Sync now</button>
<button type="button" class="modal-btn btn-save" onclick="saveProfile()">Save profile</button>
<button type="button" class="modal-btn btn-cancel" onclick="logoutAuth()">Log out</button>
</div>
<div id="adminPanel" class="admin-panel" style="display:none;">
<h4>Admin</h4>
<div class="admin-actions">
<button type="button" class="modal-btn btn-save" onclick="fetchPendingUsers()">Refresh pending</button>
<button type="button" class="modal-btn btn-save" onclick="downloadBackup()">Download backup</button>
<label class="modal-btn btn-save">
Restore backup
<input type="file" id="restoreInput" accept="application/json" style="display:none;" onchange="uploadRestore(event)">
</label>
</div>
<div id="pendingList" class="admin-list"></div>
</div>
</div>
</form>
</div>
</div>
<div class="pattern-overlay" id="patternOverlay">
<div class="pattern-sheet">
<div class="pattern-sheet-header">
<div class="pattern-sheet-title">
<h2>Pattern Composer</h2>
<p class="pattern-sheet-subtitle">Draft rows plus materials, gauge, and abbreviations.</p>
</div>
<div class="pattern-modes">
<button class="pattern-mode" data-mode="crochet" onclick="setPatternMode('crochet')">Crochet</button>
<button class="pattern-mode" data-mode="knit" onclick="setPatternMode('knit')">Knit</button>
</div>
<div class="pattern-save-indicator" id="patternSaveIndicator">Saved</div>
<button class="pattern-close" onclick="closePatternComposer()">&times;</button>
</div>
<div class="pattern-toolbar">
<div class="pattern-toolbar-left">
<button class="toolbar-btn" onclick="savePatternDraft()" title="Save draft to basket"><i class="fa-solid fa-bookmark"></i> Save</button>
<button class="toolbar-btn" onclick="exportPatternPDF()" title="Export PDF"><i class="fa-solid fa-file-pdf"></i> PDF</button>
<button class="toolbar-btn" onclick="sharePattern()" title="Share link"><i class="fa-solid fa-link"></i> Share</button>
<button class="toolbar-btn" onclick="clearPatternOutput()" title="Clear draft"><i class="fa-solid fa-eraser"></i> Clear</button>
</div>
<div class="pattern-toolbar-right">
<span class="pattern-save-indicator small" id="patternSaveIndicatorMini">Saved</span>
</div>
</div>
<div class="pattern-body">
<div class="pattern-tabs">
<button class="pattern-tab" data-tab="info" onclick="showPatternTab('info')">Pattern Info</button>
<button class="pattern-tab" data-tab="steps" onclick="showPatternTab('steps')">Steps</button>
<button class="pattern-tab" data-tab="view" onclick="showPatternTab('view')">View</button>
<button class="pattern-tab" data-tab="library" onclick="showPatternTab('library')">My Basket</button>
</div>
<div class="pattern-section" data-section="info">
<label class="field-label" for="patternTitle">Title</label>
<input id="patternTitle" type="text" placeholder="e.g., Baby Fox Plush">
<label class="field-label" for="patternDesigner">Designer / Credits</label>
<input id="patternDesigner" type="text" placeholder="Your name or shop">
<label class="field-label" for="patternMaterials">Materials (one per line)</label>
<textarea id="patternMaterials" placeholder="Yarn (Color A) worsted&#10;Yarn (Color B) accent&#10;Hook 4.0 mm&#10;Safety eyes, stuffing, needle"></textarea>
<div class="field-group-inline">
<div>
<label class="field-label" for="patternGaugeSts">Stitches / 4in (10cm)</label>
<input id="patternGaugeSts" type="text" placeholder="e.g., 16 sc">
</div>
<div>
<label class="field-label" for="patternGaugeRows">Rows / 4in (10cm)</label>
<input id="patternGaugeRows" type="text" placeholder="e.g., 18 rows">
</div>
</div>
<label class="field-label" for="patternGaugeHook">Hook / Needles</label>
<input id="patternGaugeHook" type="text" placeholder="e.g., 4.0 mm hook">
<label class="field-label" for="patternSize">Finished size</label>
<input id="patternSize" type="text" placeholder="Approx. 6 in / 15 cm tall">
<label class="field-label" for="patternGauge">Gauge (extra notes)</label>
<textarea id="patternGauge" placeholder="Magic ring start; or any extra gauge notes"></textarea>
<div class="abbrev-head">
<label class="field-label" for="patternAbbrev">Abbreviations</label>
<button class="secondary" onclick="loadDefaultAbbrev()">Load defaults</button>
</div>
<div id="patternAbbrevList" class="abbrev-grid"></div>
<textarea id="patternAbbrev" placeholder="sc single crochet&#10;dc double crochet&#10;inc increase&#10;k knit&#10;p purl"></textarea>
<label class="field-label" for="patternStitches">Stitch guide / special stitches</label>
<textarea id="patternStitches" placeholder="Magic ring: ...&#10;Invisible decrease: ...&#10;Kfb: knit front and back ..."></textarea>
<label class="field-label" for="patternNotes">Notes / finishing</label>
<textarea id="patternNotes" placeholder="Assembly, finishing, safety warnings, credits..."></textarea>
<div class="pattern-row-actions pattern-footer">
<button class="secondary" onclick="importPatternJSON()">Import JSON</button>
</div>
</div>
<div class="pattern-section" data-section="steps">
<div class="pattern-steps-head">
<h4>Steps</h4>
<button class="primary" onclick="addStep()">+ Step</button>
</div>
<div id="patternSteps"></div>
</div>
<div class="pattern-section" data-section="library">
<div class="pattern-steps-head">
<h4>Saved Patterns</h4>
<button class="primary" onclick="savePatternDraft()">Save Draft to Basket</button>
</div>
<div id="patternLibrary" class="pattern-library"></div>
</div>
<div class="pattern-section" data-section="view">
<div id="patternView" class="pattern-view"></div>
</div>
</div>
</div>
</div>
<script src="assets/app.js"></script>
<footer class="footer-bg" aria-hidden="true"></footer>
</body>
</html>