Add multiple connections per customer, contract period, and layout redesign

- Refactor data model: each customer now has a liittymat array (auto-migration from old format)
- Add sopimuskausi (1/12/24/36 kk) and alkupvm fields per connection
- Form supports adding/removing multiple connection rows per company
- Add "use same as installation address" checkbox for billing address
- Move stat cards to compact sidebar on the right
- Place search bar above customer table

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-10 00:21:31 +02:00
parent c648c9311c
commit 695d8c6545
4 changed files with 650 additions and 287 deletions

View File

@@ -10,7 +10,7 @@
<!-- Login -->
<div id="login-screen" class="login-screen">
<div class="login-box">
<h1>🔒 CuituNet Intra</h1>
<h1>CuituNet Intra</h1>
<p>Kirjaudu sisään</p>
<form id="login-form">
<input type="password" id="login-password" placeholder="Salasana" required autofocus>
@@ -39,70 +39,79 @@
</header>
<div class="main-container">
<!-- Stat-kortit -->
<div class="stats-row">
<div class="stat-card">
<div class="stat-label">Asiakkaita</div>
<div class="stat-value" id="stat-count">0</div>
</div>
<div class="stat-card">
<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 stat-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 stat-trivia stat-wide">
<div class="stat-label">Nopeudet</div>
<div id="stat-speed-table" class="speed-table"></div>
</div>
<div class="stat-card stat-trivia">
<div class="stat-label">Keskihinta / kk</div>
<div class="stat-value" id="stat-avg-price">-</div>
</div>
</div>
<div class="content-layout">
<!-- Vasen: taulukko -->
<div class="content-main">
<!-- Toolbar: haku -->
<div class="toolbar">
<div class="search-bar">
<span class="search-icon">&#128269;</span>
<input type="text" id="search-input" placeholder="Hae yrityksen nimellä, osoitteella tai yhteyshenkilöllä...">
</div>
</div>
<!-- Toolbar: haku + info -->
<div class="toolbar">
<div class="search-bar">
<span class="search-icon">&#128269;</span>
<input type="text" id="search-input" placeholder="Hae yrityksen nimellä, osoitteella tai yhteyshenkilöllä...">
</div>
</div>
<!-- Taulukko -->
<div class="table-card">
<table id="customer-table">
<thead>
<tr>
<th data-sort="yritys">Yritys &#8597;</th>
<th data-sort="asennusosoite">Osoite &#8597;</th>
<th data-sort="kaupunki">Kaupunki &#8597;</th>
<th data-sort="liittymanopeus">Nopeus &#8597;</th>
<th data-sort="hinta">Hinta/kk &#8597;</th>
<th data-sort="sopimuskausi">Sopimus &#8597;</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">&#128203;</div>
<p>Ei asiakkaita vielä.</p>
<p class="empty-hint">Klikkaa "+ Lisää asiakas" lisätäksesi ensimmäisen asiakkaan.</p>
</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="postinumero">Postinro ↕</th>
<th data-sort="kaupunki">Kaupunki ↕</th>
<th data-sort="liittymanopeus">Nopeus ↕</th>
<th data-sort="hinta">Hinta/kk ↕</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">&#128203;</div>
<p>Ei asiakkaita vielä.</p>
<p class="empty-hint">Klikkaa "Lisää asiakas" lisätäksesi ensimmäisen asiakkaan.</p>
<!-- Yhteenveto -->
<div class="summary-bar">
<span id="customer-count">0 asiakasta</span>
<span id="total-billing">Laskutus yhteensä: 0,00 €/kk</span>
</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>
<!-- 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>
</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>
@@ -113,7 +122,7 @@
<!-- Asiakas-modal -->
<div id="customer-modal" class="modal" style="display:none">
<div class="modal-content">
<div class="modal-content modal-wide">
<div class="modal-header">
<h2 id="modal-title">Lisää asiakas</h2>
<button class="modal-close" id="modal-close">&times;</button>
@@ -133,33 +142,8 @@
</div>
</div>
<h3>Asennusosoite</h3>
<div class="form-grid">
<div class="form-group full-width">
<label for="form-asennusosoite">Osoite</label>
<input type="text" id="form-asennusosoite" placeholder="esim. Kauppakatu 5">
</div>
<div class="form-group">
<label for="form-postinumero">Postinumero</label>
<input type="text" id="form-postinumero" placeholder="20100">
</div>
<div class="form-group">
<label for="form-kaupunki">Kaupunki</label>
<input type="text" id="form-kaupunki" placeholder="Turku">
</div>
</div>
<h3>Liittymä</h3>
<div class="form-grid">
<div class="form-group">
<label for="form-liittymanopeus">Liittymänopeus</label>
<input type="text" id="form-liittymanopeus" placeholder="esim. 100/100">
</div>
<div class="form-group">
<label for="form-hinta">Hinta €/kk</label>
<input type="number" id="form-hinta" step="0.01" min="0">
</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">
@@ -178,19 +162,29 @@
</div>
<h3>Laskutustiedot</h3>
<div class="form-grid">
<div class="form-group full-width">
<label for="form-laskutusosoite">Laskutusosoite</label>
<input type="text" id="form-laskutusosoite">
</div>
<div class="form-group">
<label for="form-laskutuspostinumero">Postinumero</label>
<input type="text" id="form-laskutuspostinumero" placeholder="20100">
</div>
<div class="form-group">
<label for="form-laskutuskaupunki">Kaupunki</label>
<input type="text" id="form-laskutuskaupunki">
<div class="form-group" style="margin-bottom:0.75rem;">
<label class="checkbox-label">
<input type="checkbox" id="form-billing-same">
Käytä samoja kuin ensimmäisen liittymän asennusosoite
</label>
</div>
<div id="billing-fields">
<div class="form-grid">
<div class="form-group full-width">
<label for="form-laskutusosoite">Laskutusosoite</label>
<input type="text" id="form-laskutusosoite">
</div>
<div class="form-group">
<label for="form-laskutuspostinumero">Postinumero</label>
<input type="text" id="form-laskutuspostinumero" placeholder="20100">
</div>
<div class="form-group">
<label for="form-laskutuskaupunki">Kaupunki</label>
<input type="text" id="form-laskutuskaupunki">
</div>
</div>
</div>
<div class="form-grid" style="margin-top:0.75rem;">
<div class="form-group">
<label for="form-laskutussahkoposti">Laskutussähköposti</label>
<input type="email" id="form-laskutussahkoposti">
@@ -220,7 +214,7 @@
<!-- Tiedot-modal (klikkaa riviä) -->
<div id="detail-modal" class="modal" style="display:none">
<div class="modal-content">
<div class="modal-content modal-wide">
<div class="modal-header">
<h2 id="detail-title">Asiakkaan tiedot</h2>
<button class="modal-close" id="detail-close">&times;</button>