Add user management, change log and customer archive
- Multi-user auth with username/password (replaces single password) - Default admin account created automatically (admin/cuitunet2024) - User CRUD with admin/user roles (only admin can manage users) - All customer changes logged with timestamp, user and details - Customer deletion now archives instead of permanently removing - Archive view with restore and permanent delete options - Tab navigation: Asiakkaat, Arkisto, Muutosloki, Käyttäjät - Protect users.json, changelog.json and archive.json in .gitignore Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
258
index.html
258
index.html
@@ -13,7 +13,8 @@
|
||||
<h1>CuituNet Intra</h1>
|
||||
<p>Kirjaudu sisään</p>
|
||||
<form id="login-form">
|
||||
<input type="password" id="login-password" placeholder="Salasana" required autofocus>
|
||||
<input type="text" id="login-username" placeholder="Käyttäjätunnus" required autofocus>
|
||||
<input type="password" id="login-password" placeholder="Salasana" required>
|
||||
<button type="submit">Kirjaudu</button>
|
||||
</form>
|
||||
<div id="login-error" class="error" style="display:none"></div>
|
||||
@@ -33,85 +34,160 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<span id="user-info" class="user-info"></span>
|
||||
<button id="btn-add" class="btn-primary">+ Lisää asiakas</button>
|
||||
<button id="btn-logout" class="btn-secondary">Kirjaudu ulos</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="main-container">
|
||||
<div class="content-layout">
|
||||
<!-- Vasen: taulukko -->
|
||||
<div class="content-main">
|
||||
<!-- Toolbar: haku -->
|
||||
<div class="toolbar">
|
||||
<div class="search-bar">
|
||||
<span class="search-icon">🔍</span>
|
||||
<input type="text" id="search-input" placeholder="Hae yrityksen nimellä, osoitteella tai yhteyshenkilöllä...">
|
||||
<!-- Tabs -->
|
||||
<div class="tab-bar">
|
||||
<button class="tab active" data-tab="customers">Asiakkaat</button>
|
||||
<button class="tab" data-tab="archive">Arkisto</button>
|
||||
<button class="tab" data-tab="changelog">Muutosloki</button>
|
||||
<button class="tab" data-tab="users" id="tab-users" style="display:none">Käyttäjät</button>
|
||||
</div>
|
||||
|
||||
<!-- Tab: Asiakkaat -->
|
||||
<div class="tab-content active" id="tab-content-customers">
|
||||
<div class="main-container">
|
||||
<div class="content-layout">
|
||||
<div class="content-main">
|
||||
<div class="toolbar">
|
||||
<div class="search-bar">
|
||||
<span class="search-icon">🔍</span>
|
||||
<input type="text" id="search-input" placeholder="Hae yrityksen nimellä, osoitteella tai yhteyshenkilöllä...">
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-card">
|
||||
<table id="customer-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-sort="yritys">Yritys ↕</th>
|
||||
<th data-sort="asennusosoite">Osoite ↕</th>
|
||||
<th data-sort="kaupunki">Kaupunki ↕</th>
|
||||
<th data-sort="liittymanopeus">Nopeus ↕</th>
|
||||
<th data-sort="hinta">Hinta/kk ↕</th>
|
||||
<th data-sort="sopimuskausi">Sopimus ↕</th>
|
||||
<th>Toiminnot</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="customer-tbody"></tbody>
|
||||
</table>
|
||||
<div id="no-customers" class="empty-state" style="display:none">
|
||||
<div class="empty-icon">📋</div>
|
||||
<p>Ei asiakkaita vielä.</p>
|
||||
<p class="empty-hint">Klikkaa "+ Lisää asiakas" lisätäksesi ensimmäisen asiakkaan.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="summary-bar">
|
||||
<span id="customer-count">0 asiakasta</span>
|
||||
<span id="total-billing">Laskutus yhteensä: 0,00 €/kk</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Taulukko -->
|
||||
<div class="table-card">
|
||||
<table id="customer-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-sort="yritys">Yritys ↕</th>
|
||||
<th data-sort="asennusosoite">Osoite ↕</th>
|
||||
<th data-sort="kaupunki">Kaupunki ↕</th>
|
||||
<th data-sort="liittymanopeus">Nopeus ↕</th>
|
||||
<th data-sort="hinta">Hinta/kk ↕</th>
|
||||
<th data-sort="sopimuskausi">Sopimus ↕</th>
|
||||
<th>Toiminnot</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="customer-tbody"></tbody>
|
||||
</table>
|
||||
<div id="no-customers" class="empty-state" style="display:none">
|
||||
<div class="empty-icon">📋</div>
|
||||
<p>Ei asiakkaita vielä.</p>
|
||||
<p class="empty-hint">Klikkaa "+ Lisää asiakas" lisätäksesi ensimmäisen asiakkaan.</p>
|
||||
<aside class="sidebar-stats">
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Asiakkaita</div>
|
||||
<div class="stat-value" id="stat-count">0</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Liittymiä</div>
|
||||
<div class="stat-value" id="stat-connections">0</div>
|
||||
</div>
|
||||
<div class="stat-card highlight">
|
||||
<div class="stat-label">Laskutus / kk</div>
|
||||
<div class="stat-value stat-highlight" id="stat-billing">0,00 €</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Laskutus / vuosi</div>
|
||||
<div class="stat-value" id="stat-yearly">0,00 €</div>
|
||||
</div>
|
||||
<div class="stat-card trivia">
|
||||
<div class="stat-label">Keskihinta / kk</div>
|
||||
<div class="stat-value" id="stat-avg-price">-</div>
|
||||
</div>
|
||||
<div class="stat-card trivia">
|
||||
<div class="stat-label">Suosituin postinumero</div>
|
||||
<div class="stat-value" id="stat-top-zip">-</div>
|
||||
<div class="stat-sub" id="stat-top-zip-detail"></div>
|
||||
</div>
|
||||
<div class="stat-card trivia">
|
||||
<div class="stat-label">Nopeudet</div>
|
||||
<div id="stat-speed-table" class="speed-table"></div>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Yhteenveto -->
|
||||
<div class="summary-bar">
|
||||
<span id="customer-count">0 asiakasta</span>
|
||||
<span id="total-billing">Laskutus yhteensä: 0,00 €/kk</span>
|
||||
<!-- Tab: Arkisto -->
|
||||
<div class="tab-content" id="tab-content-archive">
|
||||
<div class="main-container">
|
||||
<div class="table-card">
|
||||
<table id="archive-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Yritys</th>
|
||||
<th>Liittymiä</th>
|
||||
<th>Arkistoitu</th>
|
||||
<th>Arkistoija</th>
|
||||
<th>Toiminnot</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="archive-tbody"></tbody>
|
||||
</table>
|
||||
<div id="no-archive" class="empty-state" style="display:none">
|
||||
<div class="empty-icon">🗃</div>
|
||||
<p>Arkisto on tyhjä.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Oikea: tilastot -->
|
||||
<aside class="sidebar-stats">
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Asiakkaita</div>
|
||||
<div class="stat-value" id="stat-count">0</div>
|
||||
<!-- Tab: Muutosloki -->
|
||||
<div class="tab-content" id="tab-content-changelog">
|
||||
<div class="main-container">
|
||||
<div class="table-card">
|
||||
<table id="changelog-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Aika</th>
|
||||
<th>Käyttäjä</th>
|
||||
<th>Toiminto</th>
|
||||
<th>Asiakas</th>
|
||||
<th>Lisätiedot</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="changelog-tbody"></tbody>
|
||||
</table>
|
||||
<div id="no-changelog" class="empty-state" style="display:none">
|
||||
<div class="empty-icon">📜</div>
|
||||
<p>Ei lokimerkintöjä.</p>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Liittymiä</div>
|
||||
<div class="stat-value" id="stat-connections">0</div>
|
||||
</div>
|
||||
<div class="stat-card highlight">
|
||||
<div class="stat-label">Laskutus / kk</div>
|
||||
<div class="stat-value stat-highlight" id="stat-billing">0,00 €</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Laskutus / vuosi</div>
|
||||
<div class="stat-value" id="stat-yearly">0,00 €</div>
|
||||
</div>
|
||||
<div class="stat-card trivia">
|
||||
<div class="stat-label">Keskihinta / kk</div>
|
||||
<div class="stat-value" id="stat-avg-price">-</div>
|
||||
</div>
|
||||
<div class="stat-card trivia">
|
||||
<div class="stat-label">Suosituin postinumero</div>
|
||||
<div class="stat-value" id="stat-top-zip">-</div>
|
||||
<div class="stat-sub" id="stat-top-zip-detail"></div>
|
||||
</div>
|
||||
<div class="stat-card trivia">
|
||||
<div class="stat-label">Nopeudet</div>
|
||||
<div id="stat-speed-table" class="speed-table"></div>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tab: Käyttäjät (vain admin) -->
|
||||
<div class="tab-content" id="tab-content-users">
|
||||
<div class="main-container">
|
||||
<div style="margin-bottom:1rem;">
|
||||
<button class="btn-primary" id="btn-add-user">+ Lisää käyttäjä</button>
|
||||
</div>
|
||||
<div class="table-card">
|
||||
<table id="users-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Käyttäjätunnus</th>
|
||||
<th>Nimi</th>
|
||||
<th>Rooli</th>
|
||||
<th>Luotu</th>
|
||||
<th>Toiminnot</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="users-tbody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -129,7 +205,6 @@
|
||||
</div>
|
||||
<form id="customer-form">
|
||||
<input type="hidden" id="form-id">
|
||||
|
||||
<h3>Perustiedot</h3>
|
||||
<div class="form-grid">
|
||||
<div class="form-group">
|
||||
@@ -141,10 +216,8 @@
|
||||
<input type="text" id="form-ytunnus" placeholder="1234567-8">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Liittymät <button type="button" class="btn-add-row" id="btn-add-liittyma">+ Lisää liittymä</button></h3>
|
||||
<div id="liittymat-container"></div>
|
||||
|
||||
<h3>Yhteystiedot</h3>
|
||||
<div class="form-grid">
|
||||
<div class="form-group">
|
||||
@@ -160,7 +233,6 @@
|
||||
<input type="email" id="form-sahkoposti">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Laskutustiedot</h3>
|
||||
<div class="form-group" style="margin-bottom:0.75rem;">
|
||||
<label class="checkbox-label">
|
||||
@@ -198,12 +270,10 @@
|
||||
<input type="text" id="form-elaskuvalittaja" placeholder="esim. DABAFIHH">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Lisätiedot</h3>
|
||||
<div class="form-group full-width">
|
||||
<textarea id="form-lisatiedot" rows="3" placeholder="Vapaamuotoiset muistiinpanot..."></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="btn-primary" id="form-submit">Tallenna</button>
|
||||
<button type="button" class="btn-secondary" id="form-cancel">Peruuta</button>
|
||||
@@ -212,7 +282,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tiedot-modal (klikkaa riviä) -->
|
||||
<!-- Tiedot-modal -->
|
||||
<div id="detail-modal" class="modal" style="display:none">
|
||||
<div class="modal-content modal-wide">
|
||||
<div class="modal-header">
|
||||
@@ -222,12 +292,50 @@
|
||||
<div id="detail-body"></div>
|
||||
<div class="form-actions">
|
||||
<button class="btn-primary" id="detail-edit">Muokkaa</button>
|
||||
<button class="btn-danger" id="detail-delete">Poista</button>
|
||||
<button class="btn-danger" id="detail-delete">Arkistoi</button>
|
||||
<button class="btn-secondary" id="detail-cancel">Sulje</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Käyttäjä-modal -->
|
||||
<div id="user-modal" class="modal" style="display:none">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h2 id="user-modal-title">Lisää käyttäjä</h2>
|
||||
<button class="modal-close" id="user-modal-close">×</button>
|
||||
</div>
|
||||
<form id="user-form">
|
||||
<input type="hidden" id="user-form-id">
|
||||
<div class="form-grid">
|
||||
<div class="form-group">
|
||||
<label for="user-form-username">Käyttäjätunnus *</label>
|
||||
<input type="text" id="user-form-username" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="user-form-nimi">Nimi</label>
|
||||
<input type="text" id="user-form-nimi">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="user-form-password">Salasana <span id="user-pw-hint"></span></label>
|
||||
<input type="password" id="user-form-password">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="user-form-role">Rooli</label>
|
||||
<select id="user-form-role">
|
||||
<option value="user">Käyttäjä</option>
|
||||
<option value="admin">Ylläpitäjä</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="btn-primary">Tallenna</button>
|
||||
<button type="button" class="btn-secondary" id="user-form-cancel">Peruuta</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user