404 lines
26 KiB
Plaintext
404 lines
26 KiB
Plaintext
|
|
<!DOCTYPE html>
|
|||
|
|
<html lang="nl">
|
|||
|
|
<head>
|
|||
|
|
<meta charset="UTF-8">
|
|||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|||
|
|
<title><%= client.name %> — Mek-Tech Consulting</title>
|
|||
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
|
|||
|
|
<link rel="stylesheet" href="/css/style.css">
|
|||
|
|
<link rel="stylesheet" href="/css/dynamic.css">
|
|||
|
|
<link rel="icon" href="/img/favicon.svg" type="image/svg+xml">
|
|||
|
|
<script src="https://unpkg.com/lucide@latest"></script>
|
|||
|
|
<style>
|
|||
|
|
.tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--border); margin-bottom: 1.25rem; overflow-x: auto; }
|
|||
|
|
.tab-btn {
|
|||
|
|
padding: .5rem 1rem; background: none; border: none; border-bottom: 2px solid transparent;
|
|||
|
|
color: var(--text-muted); font-size: .8rem; font-weight: 500; cursor: pointer;
|
|||
|
|
white-space: nowrap; transition: all .15s; font-family: inherit;
|
|||
|
|
}
|
|||
|
|
.tab-btn:hover { color: var(--text); }
|
|||
|
|
.tab-btn.active { color: var(--accent); border-bottom-color: var(--accent); }
|
|||
|
|
.tab-panel { display: none; }
|
|||
|
|
.tab-panel.active { display: block; }
|
|||
|
|
.file-item { display: flex; align-items: center; gap: .5rem; background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); padding: .5rem .75rem; }
|
|||
|
|
.file-icon { font-size: 1.1rem; flex-shrink: 0; }
|
|||
|
|
.file-info { flex: 1; }
|
|||
|
|
.file-name { font-size: .85rem; color: var(--text); }
|
|||
|
|
.file-meta { font-size: .7rem; color: var(--text-muted); }
|
|||
|
|
.note-item { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); padding: .75rem; border-left: 3px solid var(--accent); }
|
|||
|
|
.note-meta { font-size: .7rem; color: var(--text-muted); }
|
|||
|
|
.note-content { font-size: .85rem; color: var(--text); white-space: pre-wrap; margin-top: .25rem; }
|
|||
|
|
.diagram-item { display: flex; align-items: center; gap: .5rem; background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); padding: .5rem .75rem; text-decoration: none; color: inherit; transition: all .15s; }
|
|||
|
|
.diagram-item:hover { border-color: var(--text-dim); }
|
|||
|
|
.diagram-icon { width: 32px; height: 32px; border-radius: var(--radius); display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: .65rem; flex-shrink: 0; }
|
|||
|
|
.diagram-icon.data_architecture { background: var(--cyan-bg); color: var(--cyan); }
|
|||
|
|
.diagram-icon.network_topology { background: var(--purple-bg); color: var(--purple); }
|
|||
|
|
.diagram-icon.system_architecture { background: var(--green-bg); color: var(--green); }
|
|||
|
|
.client-email-btn { display: inline-flex; align-items: center; gap: .35rem; }
|
|||
|
|
.files-grid { display: flex; flex-direction: column; gap: .35rem; }
|
|||
|
|
.notes-list { display: flex; flex-direction: column; gap: .5rem; }
|
|||
|
|
.inline-form { display: inline; }
|
|||
|
|
.upload-zone { border: 2px dashed var(--border); border-radius: var(--radius); padding: 1.5rem; text-align: center; cursor: pointer; transition: all .15s; margin-bottom: .75rem; }
|
|||
|
|
.upload-zone:hover { border-color: var(--accent); background: var(--border-light); }
|
|||
|
|
.upload-zone p { color: var(--text-muted); font-size: .8rem; }
|
|||
|
|
.tab-btn { display: inline-flex; align-items: center; gap: .4rem; }
|
|||
|
|
.tab-btn i { width: 14px; height: 14px; }
|
|||
|
|
</style>
|
|||
|
|
</head>
|
|||
|
|
<body>
|
|||
|
|
<nav class="navbar"><div class="nav-inner"><a href="/" class="nav-brand"><img src="/img/logo.svg" class="nav-logo" alt="Mek-Tech"></a><div style="display:flex;align-items:center;gap:.4rem"><a href="/" class="nav-icon-btn" title="Dashboard"><i data-lucide="layout-dashboard" style="width:15px;height:15px"></i> Dashboard</a><button class="theme-toggle" id="themeToggle" onclick="toggleTheme()"></button><a href="/auth/logout" class="nav-icon-btn" style="color:var(--red)"><i data-lucide="log-out" style="width:15px;height:15px"></i> Uitloggen</a></div></div></nav>
|
|||
|
|
|
|||
|
|
<div class="container">
|
|||
|
|
<a href="javascript:history.back()" class="back-link"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 18 9 12 15 6"/></svg> Terug</a>
|
|||
|
|
<div class="page-header">
|
|||
|
|
<div>
|
|||
|
|
<h1><%= client.name %></h1>
|
|||
|
|
</div>
|
|||
|
|
<div class="header-actions">
|
|||
|
|
<a href="/assess/<%= client.id %>" class="btn btn-accent">Nieuw Assessment</a>
|
|||
|
|
<a href="/engagements/new/<%= client.id %>" class="btn btn-primary">+ Engagement</a>
|
|||
|
|
<a href="/clients/<%= client.id %>/edit" class="btn btn-secondary">Bewerk</a>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="tabs" id="tabs">
|
|||
|
|
<button class="tab-btn active" data-tab="overview"><i data-lucide="eye"></i> Overzicht</button>
|
|||
|
|
<button class="tab-btn" data-tab="contact"><i data-lucide="phone"></i> Contact</button>
|
|||
|
|
<button class="tab-btn" data-tab="designs"><i data-lucide="file-text"></i> Designs (<%= diagrams.length %>)</button>
|
|||
|
|
<button class="tab-btn" data-tab="notes"><i data-lucide="edit-3"></i> Notities (<%= notes.length %>)</button>
|
|||
|
|
<button class="tab-btn" data-tab="files"><i data-lucide="folder"></i> Bestanden (<%= files.length %>)</button>
|
|||
|
|
<button class="tab-btn" data-tab="engagements"><i data-lucide="briefcase"></i> Engagements (<%= engagements.length %>)</button>
|
|||
|
|
<button class="tab-btn" data-tab="assessments"><i data-lucide="clipboard-list"></i> Assessments (<%= assessments.length %>)</button>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- OVERVIEW -->
|
|||
|
|
<div class="tab-panel active" id="panel-overview">
|
|||
|
|
<div class="detail-grid">
|
|||
|
|
<div class="detail-card">
|
|||
|
|
<h3>Bedrijfsgegevens</h3>
|
|||
|
|
<table class="info-table">
|
|||
|
|
<tr><td>Status</td><td><span class="status-badge <%= client.status %>"><%= client.status %></span></td></tr>
|
|||
|
|
<% if (client.industry) { %><tr><td>Sector</td><td><%= client.industry %></td></tr><% } %>
|
|||
|
|
<% if (client.website) { %><tr><td>Website</td><td><a href="<%= client.website %>" target="_blank" class="link"><%= client.website %></a></td></tr><% } %>
|
|||
|
|
<% if (client.source) { %><tr><td>Bron</td><td><%= client.source %></td></tr><% } %>
|
|||
|
|
<tr><td>Aangemaakt</td><td><%= new Date(client.created_at).toLocaleDateString('nl-NL') %></td></tr>
|
|||
|
|
<tr><td>Bijgewerkt</td><td><%= new Date(client.updated_at).toLocaleDateString('nl-NL') %></td></tr>
|
|||
|
|
</table>
|
|||
|
|
</div>
|
|||
|
|
<div class="detail-card" style="position:relative">
|
|||
|
|
<h3>Contact</h3>
|
|||
|
|
<table class="info-table">
|
|||
|
|
<% if (client.contact_name) { %><tr><td>Naam</td><td><%= client.contact_name %></td></tr><% } %>
|
|||
|
|
<% if (client.contact_email) { %><tr><td>Email</td><td><a href="#" onclick="openEmailModal();return false" class="link"><%= client.contact_email %></a></td></tr><% } %>
|
|||
|
|
<% if (client.contact_phone) { %><tr><td>Telefoon</td><td><a href="tel:<%= client.contact_phone %>" class="link"><%= client.contact_phone %></a></td></tr><% } %>
|
|||
|
|
</table>
|
|||
|
|
<% if (client.contact_email) { %>
|
|||
|
|
<div style="margin-top:.75rem;display:flex;gap:.4rem;flex-wrap:wrap">
|
|||
|
|
<a href="#" onclick="openEmailModal();return false" class="btn btn-accent" style="display:inline-flex;align-items:center;gap:.3rem;font-size:.75rem"><i data-lucide="send" style="width:14px;height:14px"></i> E-mail sturen</a>
|
|||
|
|
<a href="#" onclick="openEmailModal('template');return false" class="btn btn-secondary" style="display:inline-flex;align-items:center;gap:.3rem;font-size:.75rem"><i data-lucide="file-text" style="width:14px;height:14px"></i> Met template</a>
|
|||
|
|
</div>
|
|||
|
|
<% } %>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<% if (diagrams.length > 0) { %>
|
|||
|
|
<section class="section">
|
|||
|
|
<h3 class="section-title">Recente Designs</h3>
|
|||
|
|
<div class="diagram-grid">
|
|||
|
|
<% diagrams.slice(0, 4).forEach(function(d) { %>
|
|||
|
|
<a href="/architecture/<%= d.id %>" class="diagram-card">
|
|||
|
|
<div class="diagram-card-type <%= d.diagram_type %>"><%= d.diagram_type === 'data_architecture' ? 'DA' : d.diagram_type === 'network_topology' ? 'NT' : 'SA' %></div>
|
|||
|
|
<div class="diagram-card-body">
|
|||
|
|
<h4><%= d.name %></h4>
|
|||
|
|
<span style="font-size:.7rem;color:var(--text-muted)"><%= new Date(d.updated_at).toLocaleDateString('nl-NL') %></span>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- EMAIL MODAL -->
|
|||
|
|
<div class="modal-overlay" id="emailModal" style="position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.65);z-index:999;display:none;align-items:center;justify-content:center">
|
|||
|
|
<div class="modal-box" style="background:var(--bg-card);border:1px solid var(--border);border-radius:12px;padding:0;width:95%;max-width:680px;max-height:85vh;display:flex;flex-direction:column;overflow:hidden;animation:fadeInUp .25s ease">
|
|||
|
|
<div style="padding:.8rem 1rem;border-bottom:1px solid var(--border);display:flex;justify-content:space-between;align-items:center;background:var(--bg-nav)">
|
|||
|
|
<h3 style="font-size:.85rem;color:var(--text);font-weight:600;display:flex;align-items:center;gap:.4rem"><i data-lucide="send" style="color:var(--accent);width:16px;height:16px"></i> Email naar <%= client.name %></h3>
|
|||
|
|
<button onclick="closeEmailModal()" style="background:none;border:none;color:var(--text-dim);cursor:pointer;font-size:1.1rem;padding:.2rem">✕</button></div>
|
|||
|
|
<div style="overflow-y:auto;padding:1rem;flex:1">
|
|||
|
|
<form id="emailForm" method="POST" action="/clients/<%= client.id %>/email/send" enctype="multipart/form-data">
|
|||
|
|
<div style="margin-bottom:.6rem"><label style="font-size:.62rem;font-weight:700;color:var(--text-dim);text-transform:uppercase;letter-spacing:.3px">Aan</label><input type="email" name="to" id="emTo" value="<%= client.contact_email || '' %>" style="width:100%;padding:.4rem .55rem;background:var(--bg);border:1px solid var(--border);border-radius:6px;color:var(--text);font-size:.78rem;font-family:inherit"></div>
|
|||
|
|
<div style="display:flex;gap:.5rem;margin-bottom:.6rem"><div style="flex:1"><label style="font-size:.62rem;font-weight:700;color:var(--text-dim);text-transform:uppercase;letter-spacing:.3px">CC</label><input type="text" name="cc" placeholder="cc@email.nl" style="width:100%;padding:.4rem .55rem;background:var(--bg);border:1px solid var(--border);border-radius:6px;color:var(--text);font-size:.78rem;font-family:inherit"></div><div style="flex:1"><label style="font-size:.62rem;font-weight:700;color:var(--text-dim);text-transform:uppercase;letter-spacing:.3px">BCC</label><input type="text" name="bcc" placeholder="bcc@email.nl" style="width:100%;padding:.4rem .55rem;background:var(--bg);border:1px solid var(--border);border-radius:6px;color:var(--text);font-size:.78rem;font-family:inherit"></div></div>
|
|||
|
|
<div style="margin-bottom:.6rem"><label style="font-size:.62rem;font-weight:700;color:var(--text-dim);text-transform:uppercase;letter-spacing:.3px">Onderwerp</label><input type="text" name="subject" id="emSubject" value="Mek-Tech Consulting — <%= client.name %>" style="width:100%;padding:.4rem .55rem;background:var(--bg);border:1px solid var(--border);border-radius:6px;color:var(--text);font-size:.78rem;font-family:inherit"></div>
|
|||
|
|
<div style="margin-bottom:.6rem">
|
|||
|
|
<div style="display:flex;gap:.3rem;margin-bottom:.3rem;flex-wrap:wrap">
|
|||
|
|
<span style="font-size:.62rem;font-weight:700;color:var(--text-dim);text-transform:uppercase;letter-spacing:.3px">Bericht</span>
|
|||
|
|
<button type="button" onclick="formatText('bold')" title="Vet" style="background:var(--border-light);border:none;border-radius:4px;padding:.15rem .35rem;cursor:pointer;color:var(--text-muted);font-size:.65rem;font-weight:700">B</button>
|
|||
|
|
<button type="button" onclick="formatText('italic')" title="Cursief" style="background:var(--border-light);border:none;border-radius:4px;padding:.15rem .35rem;cursor:pointer;color:var(--text-muted);font-size:.65rem;font-style:italic">I</button>
|
|||
|
|
<button type="button" onclick="formatText('list')" title="Lijst" style="background:var(--border-light);border:none;border-radius:4px;padding:.15rem .35rem;cursor:pointer;color:var(--text-muted);font-size:.65rem">≡</button>
|
|||
|
|
<button type="button" onclick="formatText('link')" title="Link" style="background:var(--border-light);border:none;border-radius:4px;padding:.15rem .35rem;cursor:pointer;color:var(--text-muted);font-size:.65rem">🔗</button>
|
|||
|
|
</div>
|
|||
|
|
<textarea name="text" id="emText" rows="10" placeholder="Typ uw bericht..." style="width:100%;padding:.5rem;background:var(--bg);border:1px solid var(--border);border-radius:6px;color:var(--text);font-size:.78rem;font-family:inherit;line-height:1.6;resize:vertical;min-height:180px"></textarea>
|
|||
|
|
</div>
|
|||
|
|
<div style="margin-bottom:.75rem"><label style="font-size:.62rem;font-weight:700;color:var(--text-dim);text-transform:uppercase;letter-spacing:.3px">Bijlages</label><input type="file" name="attachments" multiple style="font-size:.72rem;color:var(--text-muted);width:100%"><div style="font-size:.6rem;color:var(--text-dim);margin-top:.15rem">Max 5 bestanden. Kies de bestanden die je wilt meesturen.</div></div>
|
|||
|
|
<div style="display:flex;gap:.4rem"><button type="submit" class="btn btn-accent" style="display:inline-flex;align-items:center;gap:.3rem;font-size:.72rem;padding:.4rem .85rem;border-radius:7px"><i data-lucide="send" style="width:14px;height:14px"></i> Versturen</button><button type="button" onclick="closeEmailModal()" class="btn btn-secondary" style="display:inline-flex;align-items:center;font-size:.72rem;padding:.4rem .85rem;border-radius:7px">Annuleren</button></div>
|
|||
|
|
</form></div></div></div>
|
|||
|
|
<style>.modal-overlay.open{display:flex!important}
|
|||
|
|
.modal-overlay.open .modal-box{animation:fadeInUp .3s ease}
|
|||
|
|
</style>
|
|||
|
|
</a>
|
|||
|
|
<% }) %>
|
|||
|
|
</div>
|
|||
|
|
<% if (diagrams.length > 4) { %>
|
|||
|
|
<p style="margin-top:.5rem"><a href="#" class="link" onclick="switchTab('designs');return false">Alle <%= diagrams.length %> designs bekijken →</a></p>
|
|||
|
|
<% } %>
|
|||
|
|
</section>
|
|||
|
|
<% } %>
|
|||
|
|
|
|||
|
|
<% if (advice.length > 0) { %>
|
|||
|
|
<section class="section">
|
|||
|
|
<h3 class="section-title">Advies</h3>
|
|||
|
|
<div class="advice-list">
|
|||
|
|
<% advice.forEach(function(a) { %>
|
|||
|
|
<div class="advice-card <%= a.priority %>">
|
|||
|
|
<div class="advice-prio <%= a.priority %>"><%= a.priority %></div>
|
|||
|
|
<div class="advice-body"><p><%= a.advice_text %></p></div>
|
|||
|
|
<form action="/clients/<%= client.id %>/advice/<%= a.id %>/dismiss" method="POST" style="margin-left:auto">
|
|||
|
|
<button class="btn-small" type="submit">×</button>
|
|||
|
|
</form>
|
|||
|
|
</div>
|
|||
|
|
<% }) %>
|
|||
|
|
</div>
|
|||
|
|
</section>
|
|||
|
|
<% } %>
|
|||
|
|
|
|||
|
|
<% if (notes.length > 0) { %>
|
|||
|
|
<section class="section">
|
|||
|
|
<h3 class="section-title">Recente Notities</h3>
|
|||
|
|
<div class="notes-list">
|
|||
|
|
<% notes.slice(0, 3).forEach(function(n) { %>
|
|||
|
|
<div class="note-item">
|
|||
|
|
<div class="note-meta"><%= new Date(n.created_at).toLocaleDateString('nl-NL', {hour:'2-digit',minute:'2-digit'}) %><% if (n.created_by) { %> · <%= n.created_by %><% } %></div>
|
|||
|
|
<div class="note-content"><%= n.content %></div>
|
|||
|
|
</div>
|
|||
|
|
<% }) %>
|
|||
|
|
</div>
|
|||
|
|
<% if (notes.length > 3) { %>
|
|||
|
|
<p style="margin-top:.5rem"><a href="#" class="link" onclick="switchTab('notes');return false">Alle <%= notes.length %> notities bekijken →</a></p>
|
|||
|
|
<% } %>
|
|||
|
|
</section>
|
|||
|
|
<% } %>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- CONTACT -->
|
|||
|
|
<div class="tab-panel" id="panel-contact">
|
|||
|
|
<div class="detail-card">
|
|||
|
|
<h3>Contactgegevens</h3>
|
|||
|
|
<table class="info-table">
|
|||
|
|
<% if (client.contact_name) { %><tr><td>Naam</td><td><%= client.contact_name %></td></tr><% } %>
|
|||
|
|
<% if (client.contact_email) { %>
|
|||
|
|
<tr><td>Email</td><td><a href="mailto:<%= client.contact_email %>" class="link"><%= client.contact_email %></a></td></tr>
|
|||
|
|
<% } %>
|
|||
|
|
<% if (client.contact_phone) { %><tr><td>Telefoon</td><td><a href="tel:<%= client.contact_phone %>" class="link"><%= client.contact_phone %></a></td></tr><% } %>
|
|||
|
|
<% if (client.website) { %><tr><td>Website</td><td><a href="<%= client.website %>" target="_blank" class="link"><%= client.website %></a></td></tr><% } %>
|
|||
|
|
</table>
|
|||
|
|
<% if (client.contact_email) { %>
|
|||
|
|
<div style="margin-top:1rem;display:flex;gap:.5rem;flex-wrap:wrap">
|
|||
|
|
<a href="mailto:<%= client.contact_email %>?subject=Mek-Tech Consulting - <%= client.name %>" class="btn btn-accent">✉ E-mail sturen</a>
|
|||
|
|
<a href="mailto:<%= client.contact_email %>?subject=Mek-Tech Consulting - <%= client.name %>&body=Geachte <%= client.contact_name || '' %>,%0D%0A%0D%0A" class="btn btn-secondary">✉ E-mail met template</a>
|
|||
|
|
</div>
|
|||
|
|
<% } %>
|
|||
|
|
</div>
|
|||
|
|
<% if (client.notes) { %>
|
|||
|
|
<div class="detail-card" style="margin-top:.75rem">
|
|||
|
|
<h3>Opgeslagen Notities bij Cliënt</h3>
|
|||
|
|
<p style="white-space:pre-wrap;font-size:.85rem"><%= client.notes %></p>
|
|||
|
|
</div>
|
|||
|
|
<% } %>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- DESIGNS -->
|
|||
|
|
<div class="tab-panel" id="panel-designs">
|
|||
|
|
<div class="section-header">
|
|||
|
|
<h3 class="section-title">Designs & Diagrammen</h3>
|
|||
|
|
<div style="display:flex;gap:.35rem">
|
|||
|
|
<a href="/architecture/new/<%= client.id %>" class="btn btn-accent btn-small">+ Nieuw Design</a>
|
|||
|
|
<a href="http://192.168.1.247:3001/python-editor/?client_id=<%= client.id %>" class="btn btn-secondary btn-small" target="_blank">Python Editor</a>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<% if (diagrams.length === 0) { %>
|
|||
|
|
<div class="empty-state"><p>Nog geen designs voor deze cliënt.</p></div>
|
|||
|
|
<% } else { %>
|
|||
|
|
<div class="diagram-grid">
|
|||
|
|
<% diagrams.forEach(function(d) { %>
|
|||
|
|
<a href="/architecture/<%= d.id %>" class="diagram-card">
|
|||
|
|
<div class="diagram-card-type <%= d.diagram_type %>"><%= d.diagram_type === 'data_architecture' ? 'DA' : d.diagram_type === 'network_topology' ? 'NT' : 'SA' %></div>
|
|||
|
|
<div class="diagram-card-body">
|
|||
|
|
<h4><%= d.name %></h4>
|
|||
|
|
<% if (d.description) { %><span style="font-size:.75rem;color:var(--text-muted)"><%= d.description %></span><% } %>
|
|||
|
|
<span style="font-size:.7rem;color:var(--text-dim);display:block;margin-top:.15rem"><%= new Date(d.updated_at).toLocaleDateString('nl-NL') %></span>
|
|||
|
|
</div>
|
|||
|
|
<a href="/architecture/report/<%= d.id %>" class="btn-small" style="position:absolute;bottom:.5rem;right:.5rem">Rapport</a>
|
|||
|
|
</a>
|
|||
|
|
<% }) %>
|
|||
|
|
</div>
|
|||
|
|
<% } %>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- NOTES -->
|
|||
|
|
<div class="tab-panel" id="panel-notes">
|
|||
|
|
<div class="section-header">
|
|||
|
|
<h3 class="section-title">Notities (<%= notes.length %>)</h3>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<form action="/clients/<%= client.id %>/notes" method="POST" class="form-card" style="margin-bottom:.75rem">
|
|||
|
|
<div class="field">
|
|||
|
|
<label for="note-content">Nieuwe notitie</label>
|
|||
|
|
<textarea name="content" id="note-content" rows="3" placeholder="Typ hier je notitie..." style="margin-top:.25rem"></textarea>
|
|||
|
|
</div>
|
|||
|
|
<button type="submit" class="btn btn-accent" style="margin-top:.5rem">Notitie toevoegen</button>
|
|||
|
|
</form>
|
|||
|
|
|
|||
|
|
<% if (notes.length === 0) { %>
|
|||
|
|
<div class="empty-state"><p>Nog geen notities.</p></div>
|
|||
|
|
<% } else { %>
|
|||
|
|
<div class="notes-list">
|
|||
|
|
<% notes.forEach(function(n) { %>
|
|||
|
|
<div class="note-item">
|
|||
|
|
<div style="display:flex;justify-content:space-between;align-items:center">
|
|||
|
|
<div class="note-meta"><%= new Date(n.created_at).toLocaleDateString('nl-NL', {hour:'2-digit',minute:'2-digit'}) %><% if (n.created_by) { %> · <%= n.created_by %><% } %></div>
|
|||
|
|
<form action="/clients/<%= client.id %>/notes/<%= n.id %>/delete" method="POST" class="inline-form">
|
|||
|
|
<button class="btn-small danger" type="submit">Verwijder</button>
|
|||
|
|
</form>
|
|||
|
|
</div>
|
|||
|
|
<div class="note-content"><%= n.content %></div>
|
|||
|
|
</div>
|
|||
|
|
<% }) %>
|
|||
|
|
</div>
|
|||
|
|
<% } %>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- FILES -->
|
|||
|
|
<div class="tab-panel" id="panel-files">
|
|||
|
|
<div class="section-header">
|
|||
|
|
<h3 class="section-title">Bestanden (<%= files.length %>)</h3>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<form action="/clients/<%= client.id %>/upload" method="POST" enctype="multipart/form-data">
|
|||
|
|
<div class="upload-zone" onclick="document.getElementById('file-input').click()">
|
|||
|
|
<p>Klik hier om bestanden te uploaden (max 100MB)</p>
|
|||
|
|
</div>
|
|||
|
|
<input type="file" name="file" id="file-input" style="display:none" onchange="this.form.submit()">
|
|||
|
|
</form>
|
|||
|
|
|
|||
|
|
<% if (files.length === 0) { %>
|
|||
|
|
<div class="empty-state"><p>Nog geen bestanden geüpload.</p></div>
|
|||
|
|
<% } else { %>
|
|||
|
|
<div class="files-grid">
|
|||
|
|
<% files.forEach(function(f) { %>
|
|||
|
|
<div class="file-item">
|
|||
|
|
<span class="file-icon"><%= f.mime_type.startsWith('image/') ? '🖼' : f.mime_type.includes('pdf') ? '📄' : f.mime_type.includes('spreadsheet') || f.mime_type.includes('excel') ? '📊' : f.mime_type.includes('zip') || f.mime_type.includes('tar') || f.mime_type.includes('gzip') ? '📦' : '📎' %></span>
|
|||
|
|
<div class="file-info">
|
|||
|
|
<div class="file-name"><%= f.original_name %></div>
|
|||
|
|
<div class="file-meta"><%= (f.file_size / 1024).toFixed(1) %> KB · <%= new Date(f.created_at).toLocaleDateString('nl-NL') %></div>
|
|||
|
|
</div>
|
|||
|
|
<% if (f.mime_type === 'application/pdf') { %><a href="/clients/<%= client.id %>/files/<%= f.id %>/view" class="btn-small">Bekijk</a><% } %>
|
|||
|
|
<a href="/clients/<%= client.id %>/files/<%= f.id %>/download" class="btn-small">Download</a>
|
|||
|
|
<form action="/clients/<%= client.id %>/files/<%= f.id %>/delete" method="POST" class="inline-form">
|
|||
|
|
<button class="btn-small danger" type="submit">×</button>
|
|||
|
|
</form>
|
|||
|
|
</div>
|
|||
|
|
<% }) %>
|
|||
|
|
</div>
|
|||
|
|
<% } %>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- ENGAGEMENTS -->
|
|||
|
|
<div class="tab-panel" id="panel-engagements">
|
|||
|
|
<div class="section-header">
|
|||
|
|
<h3 class="section-title">Engagements (<%= engagements.length %>)</h3>
|
|||
|
|
<a href="/engagements/new/<%= client.id %>" class="btn btn-primary btn-small">+ Nieuw</a>
|
|||
|
|
</div>
|
|||
|
|
<% if (engagements.length === 0) { %>
|
|||
|
|
<div class="empty-state"><p>Nog geen engagements. <a href="/engagements/new/<%= client.id %>" class="link">Start een engagement</a>.</p></div>
|
|||
|
|
<% } else { %>
|
|||
|
|
<div class="engagement-list">
|
|||
|
|
<% engagements.forEach(function(e) { %>
|
|||
|
|
<a href="/engagements/<%= e.id %>" class="engagement-row">
|
|||
|
|
<span class="engagement-type <%= e.type %>"><%= e.type %></span>
|
|||
|
|
<span class="engagement-title"><%= e.title %></span>
|
|||
|
|
<span class="status-badge <%= e.status %>"><%= e.status %></span>
|
|||
|
|
<span class="engagement-date"><%= e.start_date ? new Date(e.start_date).toLocaleDateString('nl-NL') : '' %></span>
|
|||
|
|
</a>
|
|||
|
|
<% }) %>
|
|||
|
|
</div>
|
|||
|
|
<% } %>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- ASSESSMENTS -->
|
|||
|
|
<div class="tab-panel" id="panel-assessments">
|
|||
|
|
<div class="section-header">
|
|||
|
|
<h3 class="section-title">Assessments (<%= assessments.length %>)</h3>
|
|||
|
|
<a href="/assess/<%= client.id %>" class="btn btn-accent btn-small">+ Nieuw</a>
|
|||
|
|
</div>
|
|||
|
|
<% if (assessments.length === 0) { %>
|
|||
|
|
<div class="empty-state"><p>Nog geen assessments uitgevoerd.</p></div>
|
|||
|
|
<% } else { %>
|
|||
|
|
<div class="assess-list">
|
|||
|
|
<% assessments.slice().reverse().forEach(function(a) { %>
|
|||
|
|
<div class="assess-item">
|
|||
|
|
<span class="assess-date"><%= new Date(a.created_at).toLocaleDateString('nl-NL') %></span>
|
|||
|
|
<span class="assess-id">Rapport #<%= a.id %></span>
|
|||
|
|
<a href="/assess/report/<%= a.id %>" class="btn-small">Bekijk</a>
|
|||
|
|
</div>
|
|||
|
|
<% }) %>
|
|||
|
|
</div>
|
|||
|
|
<% } %>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
function switchTab(name) {
|
|||
|
|
document.querySelectorAll('.tab-btn').forEach(function(b) { b.classList.remove('active'); });
|
|||
|
|
document.querySelectorAll('.tab-panel').forEach(function(p) { p.classList.remove('active'); });
|
|||
|
|
var btn = document.querySelector('.tab-btn[data-tab="' + name + '"]');
|
|||
|
|
var panel = document.getElementById('panel-' + name);
|
|||
|
|
if (btn) btn.classList.add('active');
|
|||
|
|
if (panel) panel.classList.add('active');
|
|||
|
|
}
|
|||
|
|
document.querySelectorAll('.tab-btn').forEach(function(btn) {
|
|||
|
|
btn.addEventListener('click', function() {
|
|||
|
|
switchTab(this.getAttribute('data-tab'));
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
function openEmailModal(type) {
|
|||
|
|
var m = document.getElementById('emailModal');
|
|||
|
|
m.classList.add('open');
|
|||
|
|
if (type === 'template') {
|
|||
|
|
var tmpl = 'Geachte ' + '<%= client.contact_name || '' %>'.trim().replace(/'/g,"\\'") + ',\n\nBedankt voor uw interesse in Mek-Tech Consulting.\n\n' +
|
|||
|
|
'Op basis van onze analyse zien wij kansen op het gebied van data-infrastructuur en AI-implementatie.\n\n' +
|
|||
|
|
'Ik stel voor om een kennismakingsgesprek in te plannen om de mogelijkheden te bespreken.\n\n' +
|
|||
|
|
'Met vriendelijke groet,\n<%= user.username %>\nMek-Tech Consulting';
|
|||
|
|
document.getElementById('emText').value = tmpl;
|
|||
|
|
document.getElementById('emSubject').value = 'Mek-Tech Consulting — Samenwerking met <%= client.name %>';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function closeEmailModal() { document.getElementById('emailModal').classList.remove('open'); }
|
|||
|
|
document.getElementById('emailModal').addEventListener('click', function(e) { if (e.target === this) closeEmailModal(); });
|
|||
|
|
function formatText(cmd) {
|
|||
|
|
var ta = document.getElementById('emText');
|
|||
|
|
var s = ta.selectionStart, e = ta.selectionEnd, t = ta.value;
|
|||
|
|
if (cmd === 'bold') { ta.value = t.slice(0,s) + '**' + t.slice(s,e) + '**' + t.slice(e); ta.selectionStart = s+2; ta.selectionEnd = e+2; }
|
|||
|
|
else if (cmd === 'italic') { ta.value = t.slice(0,s) + '_' + t.slice(s,e) + '_' + t.slice(e); ta.selectionStart = s+1; ta.selectionEnd = e+1; }
|
|||
|
|
else if (cmd === 'list') { ta.value = t.slice(0,s) + '\n- ' + t.slice(s,e).replace(/\n/g,'\n- ') + '\n' + t.slice(e); }
|
|||
|
|
else if (cmd === 'link') { var u = prompt('URL:'); if(u) ta.value = t.slice(0,s) + '[' + t.slice(s,e) + '](' + u + ')' + t.slice(e); }
|
|||
|
|
ta.focus();
|
|||
|
|
}
|
|||
|
|
document.getElementById('emailForm').addEventListener('submit', function(e) {
|
|||
|
|
var to = document.getElementById('emTo').value;
|
|||
|
|
if (!to) { e.preventDefault(); alert('Vul een ontvanger in'); }
|
|||
|
|
});
|
|||
|
|
lucide.createIcons();
|
|||
|
|
var hash = window.location.hash.replace('#', '');
|
|||
|
|
if (hash && document.getElementById('panel-' + hash)) { switchTab(hash); }
|
|||
|
|
<% if (typeof emailSent !== 'undefined' && emailSent) { %>
|
|||
|
|
alert('Email verzonden!');
|
|||
|
|
<% } %>
|
|||
|
|
</script>
|
|||
|
|
<script src="/js/theme.js"></script></body>
|
|||
|
|
</html>
|