Roesstad/index.html

315 lines
No EOL
15 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Family Tree | Slektstre</title>
<meta name="description" content="Visual auto-sorting family tree logger with birth and death dates, generational hierarchy, and interactive canvas.">
<!-- Google Fonts -->
<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=Outfit:wght@300;400;500;600;700&family=Plus+Jakarta+Sans:wght@400;500;600&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
</head>
<body class="dark-theme">
<!-- Main Application Header -->
<header class="app-header">
<div class="header-left">
<div class="brand">
<div class="brand-icon">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 2v20M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"></path>
</svg>
</div>
<div>
<h1 class="brand-title">Røsstad Tree</h1>
<span class="brand-subtitle" id="statsSubtitle">Loading family records...</span>
</div>
</div>
<!-- View Mode Switcher -->
<div class="view-toggle-group">
<button id="viewTreeBtn" class="toggle-btn active" title="Visual Tree View">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="3" y="3" width="7" height="7"></rect>
<rect x="14" y="3" width="7" height="7"></rect>
<rect x="14" y="14" width="7" height="7"></rect>
<rect x="3" y="14" width="7" height="7"></rect>
</svg>
<span>Tree Canvas</span>
</button>
<button id="viewListBtn" class="toggle-btn" title="Registry Table View">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="8" y1="6" x2="21" y2="6"></line>
<line x1="8" y1="12" x2="21" y2="12"></line>
<line x1="8" y1="18" x2="21" y2="18"></line>
<line x1="3" y1="6" x2="3.01" y2="6"></line>
<line x1="3" y1="12" x2="3.01" y2="12"></line>
<line x1="3" y1="18" x2="3.01" y2="18"></line>
</svg>
<span>Registry List</span>
</button>
</div>
</div>
<!-- Search and Global Actions -->
<div class="header-right">
<div class="search-box">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="search-icon">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
<input type="text" id="searchInput" placeholder="Search person by name or year..." autocomplete="off">
<button id="clearSearchBtn" class="clear-search-btn" title="Clear search">&times;</button>
</div>
<button id="addNewPersonBtn" class="btn btn-primary" title="Add a new family member">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="12" y1="5" x2="12" y2="19"></line>
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
<span>Add Person</span>
</button>
<!-- Data & Settings Menu Button -->
<div class="dropdown">
<button id="dataMenuBtn" class="btn btn-secondary icon-only" title="Data options">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="1"></circle>
<circle cx="12" cy="5" r="1"></circle>
<circle cx="12" cy="19" r="1"></circle>
</svg>
</button>
<div id="dataDropdownMenu" class="dropdown-menu">
<button id="exportJsonBtn" class="dropdown-item">
<span>📥 Export JSON Backup</span>
</button>
<button id="importJsonBtn" class="dropdown-item">
<span>📤 Import JSON File</span>
</button>
<input type="file" id="importFileInput" accept=".json" style="display: none;">
<div class="dropdown-divider"></div>
<button id="loadSampleDataBtn" class="dropdown-item">
<span>🔄 Load Sample Family</span>
</button>
<button id="clearAllDataBtn" class="dropdown-item danger">
<span>🗑️ Clear All Records</span>
</button>
</div>
</div>
<!-- Theme Toggle -->
<button id="themeToggleBtn" class="btn btn-secondary icon-only" title="Toggle Dark/Light Mode">
<span id="themeIcon">🌙</span>
</button>
</div>
</header>
<!-- Main Workspace -->
<main class="main-viewport">
<!-- Visual Tree View -->
<section id="treeViewSection" class="view-panel active">
<!-- Canvas Controls Overlay -->
<div class="canvas-controls">
<button id="zoomInBtn" class="control-btn" title="Zoom In">+</button>
<button id="zoomOutBtn" class="control-btn" title="Zoom Out">&minus;</button>
<button id="zoomResetBtn" class="control-btn" title="Reset Zoom / Fit to Screen">Fit</button>
<div class="control-divider"></div>
<button id="autoSortBtn" class="control-btn auto-sort-btn" title="Re-sort and organize tree">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21.5 2v6h-6M21.34 15.57a10 10 0 1 1-.57-8.38l5.67-5.67"/>
</svg>
<span>Auto-Sort</span>
</button>
</div>
<!-- Canvas Helper Hint -->
<div class="canvas-hint">
<span>💡 Click & drag canvas to pan • Scroll to zoom • Click cards to inspect</span>
</div>
<!-- Zoomable / Pannable Tree Container -->
<div id="treeViewport" class="tree-viewport">
<div id="treeCanvas" class="tree-canvas">
<!-- SVG Connection Lines -->
<svg id="treeSvg" class="tree-svg"></svg>
<!-- Interactive Tree Nodes Layer -->
<div id="treeNodesLayer" class="tree-nodes-layer">
<!-- Generational tiers and cards rendered by script.js -->
</div>
</div>
</div>
</section>
<!-- Registry List View -->
<section id="listViewSection" class="view-panel">
<div class="list-container">
<div class="list-header-row">
<div>
<h2>Family Members Registry</h2>
<p class="text-muted">Chronological list of all logged family members with birth and death dates.</p>
</div>
<div class="list-actions">
<button id="listAddPersonBtn" class="btn btn-primary">
<span>+ Add Member</span>
</button>
</div>
</div>
<div class="table-card">
<div class="table-responsive">
<table class="registry-table" id="registryTable">
<thead>
<tr>
<th data-sort="name">Name <span class="sort-indicator">↕</span></th>
<th data-sort="gender">Gender <span class="sort-indicator">↕</span></th>
<th data-sort="birthDate">Birth Date <span class="sort-indicator">↕</span></th>
<th data-sort="deathDate">Death Date <span class="sort-indicator">↕</span></th>
<th data-sort="lifespan">Lifespan / Age <span class="sort-indicator">↕</span></th>
<th>Parents</th>
<th>Spouse</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="registryTableBody">
<!-- Populated dynamically -->
</tbody>
</table>
</div>
</div>
</div>
</section>
</main>
<!-- Modal: Add / Edit Family Member -->
<div id="personModal" class="modal-backdrop" style="display: none;">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h2 id="personModalTitle">Add Family Member</h2>
<button type="button" class="close-btn" id="closePersonModalBtn" aria-label="Close modal">&times;</button>
</div>
<form id="personForm" class="person-form">
<input type="hidden" id="personId">
<!-- Name fields -->
<div class="form-row">
<div class="form-group flex-1">
<label for="firstNameInput">First Name <span class="req">*</span></label>
<input type="text" id="firstNameInput" placeholder="e.g. Henrik" required>
</div>
<div class="form-group flex-1">
<label for="lastNameInput">Last Name <span class="req">*</span></label>
<input type="text" id="lastNameInput" placeholder="e.g. Røsstad" required>
</div>
</div>
<!-- Gender & Living status -->
<div class="form-row">
<div class="form-group flex-1">
<label for="genderSelect">Gender</label>
<select id="genderSelect">
<option value="male">Male</option>
<option value="female">Female</option>
<option value="other">Other / Unspecified</option>
</select>
</div>
<div class="form-group flex-1 checkbox-group-container">
<label>Status</label>
<label class="custom-checkbox">
<input type="checkbox" id="isLivingCheckbox" checked>
<span class="checkbox-label">Person is still living</span>
</label>
</div>
</div>
<!-- Dates Section -->
<div class="form-row">
<div class="form-group flex-1">
<label for="birthDateInput">Birth Date <span class="req">*</span></label>
<input type="date" id="birthDateInput" required>
</div>
<div class="form-group flex-1" id="deathDateFieldGroup" style="display: none;">
<label for="deathDateInput">Death Date</label>
<input type="date" id="deathDateInput">
</div>
</div>
<div class="form-divider">Relationships</div>
<!-- Parents Selection -->
<div class="form-row">
<div class="form-group flex-1">
<label for="parent1Select">Parent 1</label>
<select id="parent1Select">
<option value="">-- None / Unknown --</option>
</select>
</div>
<div class="form-group flex-1">
<label for="parent2Select">Parent 2</label>
<select id="parent2Select">
<option value="">-- None / Unknown --</option>
</select>
</div>
</div>
<!-- Spouse Selection -->
<div class="form-row">
<div class="form-group flex-1">
<label for="spouseSelect">Spouse / Partner</label>
<select id="spouseSelect">
<option value="">-- None / Unmarried --</option>
</select>
</div>
</div>
<!-- Notes / Biography -->
<div class="form-group">
<label for="notesInput">Notes / Biography (Optional)</label>
<textarea id="notesInput" rows="2" placeholder="Birthplace, occupation, notable life events..."></textarea>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" id="cancelPersonBtn">Cancel</button>
<button type="submit" class="btn btn-primary" id="savePersonBtn">Save Person</button>
</div>
</form>
</div>
</div>
</div>
<!-- Modal: View Details & Quick Actions -->
<div id="detailsModal" class="modal-backdrop" style="display: none;">
<div class="modal-dialog modal-dialog-sm">
<div class="modal-content">
<div class="modal-header">
<h3 id="detailsModalTitle">Person Details</h3>
<button type="button" class="close-btn" id="closeDetailsModalBtn">&times;</button>
</div>
<div class="modal-body" id="detailsModalBody">
<!-- Dynamic Details -->
</div>
<div class="modal-footer justify-between">
<button type="button" class="btn btn-danger-outline" id="detailsDeleteBtn">Delete</button>
<div class="footer-actions">
<button type="button" class="btn btn-secondary" id="detailsAddChildBtn">+ Add Child</button>
<button type="button" class="btn btn-primary" id="detailsEditBtn">Edit</button>
</div>
</div>
</div>
</div>
</div>
<!-- Toast Notification -->
<div id="toastNotification" class="toast-notification"></div>
<script src="script.js"></script>
</body>
</html>