Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM, PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source files covering clients, berths, interests/pipeline, documents/EOI, expenses/invoices, email, notifications, dashboard, admin, and client portal. CI/CD via Gitea Actions with Docker builds. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
596 lines
25 KiB
HTML
596 lines
25 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Port Nimara CRM — Mockup A: Dark Sidebar + Light Content</title>
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
<style>
|
|
:root {
|
|
--navy: #1e2844;
|
|
--navy-80: #474e66;
|
|
--navy-60: #71768a;
|
|
--navy-40: #9ea1af;
|
|
--navy-20: #cdcfd6;
|
|
--brand-blue: #3a7bc8;
|
|
--brand-blue-hover: #2f6ab5;
|
|
--brand-blue-80: #6196d3;
|
|
--brand-blue-60: #89b0de;
|
|
--brand-blue-20: #d8e5f4;
|
|
--teal: #83aab1;
|
|
--purple: #685aa3;
|
|
--mint: #add5b3;
|
|
--sage: #dae3c1;
|
|
--success: #2d8a4e;
|
|
--success-bg: #e8f5e9;
|
|
--warning: #e6a817;
|
|
--warning-bg: #fff8e1;
|
|
--error: #d32f2f;
|
|
--error-bg: #ffebee;
|
|
--sidebar-hover: #171f35;
|
|
--bg: #ffffff;
|
|
--bg-secondary: #f8f9fa;
|
|
--bg-tertiary: #f1f3f5;
|
|
--border: #cdcfd6;
|
|
--shadow-sm: 0 1px 2px rgba(30,40,68,0.06);
|
|
--shadow: 0 1px 3px rgba(30,40,68,0.10), 0 1px 2px rgba(30,40,68,0.06);
|
|
--shadow-md: 0 4px 6px rgba(30,40,68,0.07), 0 2px 4px rgba(30,40,68,0.06);
|
|
--shadow-lg: 0 10px 15px rgba(30,40,68,0.10), 0 4px 6px rgba(30,40,68,0.05);
|
|
--radius: 8px;
|
|
--radius-sm: 6px;
|
|
}
|
|
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
body { font-family: 'Inter', -apple-system, sans-serif; background: var(--bg-secondary); color: var(--navy); }
|
|
|
|
/* === LAYOUT === */
|
|
.app { display: flex; min-height: 100vh; }
|
|
|
|
/* === SIDEBAR === */
|
|
.sidebar {
|
|
width: 260px;
|
|
background: var(--navy);
|
|
color: var(--navy-20);
|
|
display: flex;
|
|
flex-direction: column;
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
bottom: 0;
|
|
z-index: 10;
|
|
}
|
|
.sidebar-logo {
|
|
padding: 24px 20px;
|
|
border-bottom: 1px solid var(--navy-80);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
}
|
|
.sidebar-logo .logo-mark {
|
|
width: 36px; height: 36px;
|
|
background: var(--brand-blue);
|
|
border-radius: 8px;
|
|
display: flex; align-items: center; justify-content: center;
|
|
font-weight: 700; font-size: 16px; color: #fff;
|
|
}
|
|
.sidebar-logo .logo-text {
|
|
font-size: 15px; font-weight: 600; color: #fff;
|
|
line-height: 1.2;
|
|
}
|
|
.sidebar-logo .logo-text span { display: block; font-size: 11px; font-weight: 400; color: var(--navy-40); }
|
|
.sidebar-nav { flex: 1; padding: 16px 12px; overflow-y: auto; }
|
|
.nav-section { margin-bottom: 24px; }
|
|
.nav-section-title {
|
|
font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 1.2px;
|
|
color: var(--navy-60); padding: 0 8px; margin-bottom: 8px;
|
|
}
|
|
.nav-item {
|
|
display: flex; align-items: center; gap: 10px;
|
|
padding: 9px 12px; border-radius: var(--radius-sm);
|
|
font-size: 13.5px; font-weight: 500; color: var(--navy-20);
|
|
cursor: pointer; transition: all 0.15s;
|
|
margin-bottom: 2px;
|
|
}
|
|
.nav-item:hover { background: var(--sidebar-hover); color: #fff; }
|
|
.nav-item.active {
|
|
background: rgba(58,123,200,0.12); color: #fff;
|
|
border-left: 3px solid var(--brand-blue);
|
|
padding-left: 9px;
|
|
}
|
|
.nav-item .icon { width: 18px; text-align: center; color: var(--teal); font-size: 14px; }
|
|
.nav-item.active .icon { color: var(--brand-blue); }
|
|
.nav-item .badge {
|
|
margin-left: auto; background: var(--brand-blue); color: #fff;
|
|
font-size: 10px; font-weight: 600; padding: 2px 7px; border-radius: 10px;
|
|
}
|
|
.sidebar-footer {
|
|
padding: 16px 20px; border-top: 1px solid var(--navy-80);
|
|
display: flex; align-items: center; gap: 10px;
|
|
}
|
|
.sidebar-footer .avatar {
|
|
width: 32px; height: 32px; border-radius: 50%; background: var(--brand-blue);
|
|
display: flex; align-items: center; justify-content: center;
|
|
font-size: 12px; font-weight: 600; color: #fff;
|
|
}
|
|
.sidebar-footer .user-info { font-size: 12px; }
|
|
.sidebar-footer .user-info .name { font-weight: 600; color: #fff; }
|
|
.sidebar-footer .user-info .role { color: var(--navy-40); }
|
|
|
|
/* === MAIN CONTENT === */
|
|
.main { flex: 1; margin-left: 260px; }
|
|
.topbar {
|
|
background: #fff; border-bottom: 1px solid var(--border);
|
|
padding: 16px 32px; display: flex; align-items: center; justify-content: space-between;
|
|
position: sticky; top: 0; z-index: 5;
|
|
}
|
|
.topbar h1 { font-size: 20px; font-weight: 700; color: var(--navy); }
|
|
.topbar-right { display: flex; align-items: center; gap: 16px; }
|
|
.search-box {
|
|
background: var(--bg-tertiary); border: 1px solid var(--border);
|
|
border-radius: var(--radius); padding: 8px 14px 8px 36px;
|
|
font-size: 13px; color: var(--navy); width: 260px;
|
|
outline: none; font-family: inherit;
|
|
}
|
|
.search-box:focus { border-color: var(--brand-blue); background: #fff; box-shadow: 0 0 0 3px rgba(58,123,200,0.1); }
|
|
.icon-btn {
|
|
width: 36px; height: 36px; border-radius: 50%; background: var(--bg-tertiary);
|
|
border: 1px solid var(--border); display: flex; align-items: center; justify-content: center;
|
|
cursor: pointer; color: var(--navy-60); font-size: 14px; transition: all 0.15s;
|
|
}
|
|
.icon-btn:hover { background: var(--navy); color: #fff; border-color: var(--navy); }
|
|
.icon-btn .dot {
|
|
position: absolute; top: -2px; right: -2px; width: 8px; height: 8px;
|
|
background: var(--error); border-radius: 50%; border: 2px solid #fff;
|
|
}
|
|
|
|
/* === DASHBOARD CONTENT === */
|
|
.content { padding: 28px 32px; }
|
|
|
|
/* Welcome banner */
|
|
.welcome-banner {
|
|
background: linear-gradient(135deg, var(--navy) 0%, #2a3a5e 100%);
|
|
border-radius: var(--radius); padding: 28px 32px;
|
|
color: #fff; margin-bottom: 28px; position: relative; overflow: hidden;
|
|
}
|
|
.welcome-banner::after {
|
|
content: ''; position: absolute; right: -30px; top: -30px;
|
|
width: 200px; height: 200px; border-radius: 50%;
|
|
background: rgba(58,123,200,0.15);
|
|
}
|
|
.welcome-banner h2 { font-size: 22px; font-weight: 700; margin-bottom: 6px; }
|
|
.welcome-banner p { font-size: 14px; color: var(--navy-20); max-width: 500px; }
|
|
|
|
/* KPI Cards */
|
|
.kpi-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; margin-bottom: 28px; }
|
|
.kpi-card {
|
|
background: #fff; border-radius: var(--radius); padding: 22px 24px;
|
|
border: 1px solid var(--border); box-shadow: var(--shadow-sm);
|
|
transition: all 0.2s;
|
|
}
|
|
.kpi-card:hover { box-shadow: var(--shadow-md); transform: translateY(-1px); }
|
|
.kpi-card .kpi-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
|
|
.kpi-card .kpi-icon {
|
|
width: 40px; height: 40px; border-radius: 10px;
|
|
display: flex; align-items: center; justify-content: center; font-size: 18px;
|
|
}
|
|
.kpi-card .kpi-trend { font-size: 12px; font-weight: 600; padding: 3px 8px; border-radius: 20px; }
|
|
.kpi-card .kpi-trend.up { background: var(--success-bg); color: var(--success); }
|
|
.kpi-card .kpi-trend.down { background: var(--error-bg); color: var(--error); }
|
|
.kpi-card .kpi-trend.neutral { background: var(--bg-tertiary); color: var(--navy-60); }
|
|
.kpi-card .kpi-value { font-size: 28px; font-weight: 700; color: var(--navy); margin-bottom: 4px; }
|
|
.kpi-card .kpi-label { font-size: 13px; color: var(--navy-60); }
|
|
|
|
.kpi-icon.blue { background: var(--brand-blue-20); color: var(--brand-blue); }
|
|
.kpi-icon.navy { background: rgba(30,40,68,0.08); color: var(--navy); }
|
|
.kpi-icon.teal { background: rgba(131,170,177,0.15); color: var(--teal); }
|
|
.kpi-icon.purple { background: rgba(104,90,163,0.12); color: var(--purple); }
|
|
|
|
/* Two-column layout */
|
|
.dashboard-grid { display: grid; grid-template-columns: 2fr 1fr; gap: 24px; margin-bottom: 28px; }
|
|
|
|
/* Card */
|
|
.card {
|
|
background: #fff; border-radius: var(--radius); border: 1px solid var(--border);
|
|
box-shadow: var(--shadow-sm); overflow: hidden;
|
|
}
|
|
.card-header {
|
|
padding: 18px 24px; border-bottom: 1px solid var(--border);
|
|
display: flex; align-items: center; justify-content: space-between;
|
|
}
|
|
.card-header h3 { font-size: 15px; font-weight: 600; color: var(--navy); }
|
|
.card-header .card-action {
|
|
font-size: 12px; font-weight: 500; color: var(--brand-blue); cursor: pointer;
|
|
text-decoration: none;
|
|
}
|
|
.card-header .card-action:hover { text-decoration: underline; }
|
|
.card-body { padding: 20px 24px; }
|
|
|
|
/* Chart area placeholder */
|
|
.chart-area {
|
|
height: 220px; border-radius: var(--radius-sm);
|
|
background: linear-gradient(180deg, var(--brand-blue-20) 0%, rgba(58,123,200,0.03) 100%);
|
|
display: flex; align-items: flex-end; justify-content: space-around;
|
|
padding: 0 16px 16px;
|
|
}
|
|
.chart-bar {
|
|
width: 28px; border-radius: 4px 4px 0 0; transition: all 0.3s;
|
|
position: relative;
|
|
}
|
|
.chart-bar:hover { opacity: 0.8; }
|
|
.chart-bar .chart-label {
|
|
position: absolute; bottom: -22px; left: 50%; transform: translateX(-50%);
|
|
font-size: 10px; color: var(--navy-60); white-space: nowrap;
|
|
}
|
|
|
|
/* Recent activity list */
|
|
.activity-list { list-style: none; }
|
|
.activity-item {
|
|
display: flex; align-items: flex-start; gap: 12px;
|
|
padding: 14px 0; border-bottom: 1px solid var(--bg-tertiary);
|
|
}
|
|
.activity-item:last-child { border-bottom: none; }
|
|
.activity-dot {
|
|
width: 8px; height: 8px; border-radius: 50%; margin-top: 5px; flex-shrink: 0;
|
|
}
|
|
.activity-dot.blue { background: var(--brand-blue); }
|
|
.activity-dot.green { background: var(--success); }
|
|
.activity-dot.orange { background: var(--warning); }
|
|
.activity-dot.purple { background: var(--purple); }
|
|
.activity-content { flex: 1; }
|
|
.activity-content .activity-text { font-size: 13px; color: var(--navy); line-height: 1.5; }
|
|
.activity-content .activity-text strong { font-weight: 600; }
|
|
.activity-content .activity-time { font-size: 11px; color: var(--navy-40); margin-top: 2px; }
|
|
|
|
/* Occupancy section */
|
|
.occupancy-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; }
|
|
.occupancy-card {
|
|
background: var(--bg-secondary); border-radius: var(--radius-sm); padding: 16px;
|
|
text-align: center;
|
|
}
|
|
.occupancy-card .occ-value { font-size: 24px; font-weight: 700; margin-bottom: 2px; }
|
|
.occupancy-card .occ-label { font-size: 11px; color: var(--navy-60); margin-bottom: 10px; }
|
|
.progress-bar { height: 6px; background: var(--bg-tertiary); border-radius: 3px; overflow: hidden; }
|
|
.progress-bar .fill { height: 100%; border-radius: 3px; }
|
|
|
|
/* Table */
|
|
.data-table { width: 100%; border-collapse: collapse; }
|
|
.data-table th {
|
|
text-align: left; font-size: 11px; font-weight: 600; text-transform: uppercase;
|
|
letter-spacing: 0.5px; color: var(--navy-60); padding: 10px 16px;
|
|
background: var(--bg-secondary); border-bottom: 1px solid var(--border);
|
|
}
|
|
.data-table td {
|
|
padding: 12px 16px; font-size: 13px; border-bottom: 1px solid var(--bg-tertiary);
|
|
color: var(--navy);
|
|
}
|
|
.data-table tr:hover td { background: rgba(58,123,200,0.03); }
|
|
.status-badge {
|
|
display: inline-block; padding: 3px 10px; border-radius: 20px;
|
|
font-size: 11px; font-weight: 600;
|
|
}
|
|
.status-badge.active { background: var(--success-bg); color: var(--success); }
|
|
.status-badge.pending { background: var(--warning-bg); color: var(--warning); }
|
|
.status-badge.overdue { background: var(--error-bg); color: var(--error); }
|
|
.status-badge.draft { background: var(--bg-tertiary); color: var(--navy-60); }
|
|
|
|
/* Berth map */
|
|
.berth-visual {
|
|
display: grid; grid-template-columns: repeat(8, 1fr); gap: 6px; padding: 4px 0;
|
|
}
|
|
.berth-slot {
|
|
aspect-ratio: 1; border-radius: 4px; display: flex; align-items: center; justify-content: center;
|
|
font-size: 9px; font-weight: 600; color: #fff; cursor: pointer; transition: all 0.15s;
|
|
}
|
|
.berth-slot:hover { transform: scale(1.08); }
|
|
.berth-slot.occupied { background: var(--brand-blue); }
|
|
.berth-slot.available { background: var(--mint); color: var(--navy); }
|
|
.berth-slot.reserved { background: var(--purple); }
|
|
.berth-slot.maintenance { background: var(--navy-40); }
|
|
.berth-legend {
|
|
display: flex; gap: 16px; margin-top: 12px; padding-top: 12px;
|
|
border-top: 1px solid var(--bg-tertiary);
|
|
}
|
|
.berth-legend-item { display: flex; align-items: center; gap: 6px; font-size: 11px; color: var(--navy-60); }
|
|
.berth-legend-item .dot { width: 10px; height: 10px; border-radius: 3px; }
|
|
|
|
/* Quick Actions */
|
|
.quick-actions { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
|
|
.quick-action-btn {
|
|
display: flex; align-items: center; gap: 10px;
|
|
padding: 12px 14px; border-radius: var(--radius-sm);
|
|
border: 1px solid var(--border); background: #fff;
|
|
font-size: 13px; font-weight: 500; color: var(--navy);
|
|
cursor: pointer; transition: all 0.15s;
|
|
}
|
|
.quick-action-btn:hover { border-color: var(--brand-blue); background: rgba(58,123,200,0.03); }
|
|
.quick-action-btn .qa-icon {
|
|
width: 32px; height: 32px; border-radius: 8px;
|
|
display: flex; align-items: center; justify-content: center;
|
|
font-size: 14px;
|
|
}
|
|
|
|
/* Bottom row */
|
|
.bottom-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
|
|
|
|
/* Style label */
|
|
.mockup-label {
|
|
position: fixed; bottom: 16px; right: 16px; z-index: 100;
|
|
background: var(--navy); color: #fff; padding: 8px 16px;
|
|
border-radius: var(--radius); font-size: 12px; font-weight: 600;
|
|
box-shadow: var(--shadow-lg);
|
|
}
|
|
.mockup-label span { color: var(--brand-blue-60); font-weight: 400; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="app">
|
|
|
|
<!-- SIDEBAR -->
|
|
<aside class="sidebar">
|
|
<div class="sidebar-logo">
|
|
<div class="logo-mark">PN</div>
|
|
<div class="logo-text">Port Nimara<span>Marina CRM</span></div>
|
|
</div>
|
|
<nav class="sidebar-nav">
|
|
<div class="nav-section">
|
|
<div class="nav-section-title">Main</div>
|
|
<div class="nav-item active">
|
|
<span class="icon">■</span> Dashboard
|
|
</div>
|
|
<div class="nav-item">
|
|
<span class="icon">♦</span> Clients
|
|
<span class="badge">248</span>
|
|
</div>
|
|
<div class="nav-item">
|
|
<span class="icon">⚓</span> Berths
|
|
</div>
|
|
<div class="nav-item">
|
|
<span class="icon">✉</span> Interests
|
|
<span class="badge">12</span>
|
|
</div>
|
|
</div>
|
|
<div class="nav-section">
|
|
<div class="nav-section-title">Operations</div>
|
|
<div class="nav-item">
|
|
<span class="icon">✎</span> Contracts
|
|
</div>
|
|
<div class="nav-item">
|
|
<span class="icon">★</span> Invoicing
|
|
</div>
|
|
<div class="nav-item">
|
|
<span class="icon">📄</span> Documents
|
|
</div>
|
|
<div class="nav-item">
|
|
<span class="icon">🔧</span> Maintenance
|
|
</div>
|
|
</div>
|
|
<div class="nav-section">
|
|
<div class="nav-section-title">Insights</div>
|
|
<div class="nav-item">
|
|
<span class="icon">📈</span> Reports
|
|
</div>
|
|
<div class="nav-item">
|
|
<span class="icon">⚙</span> Settings
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
<div class="sidebar-footer">
|
|
<div class="avatar">MC</div>
|
|
<div class="user-info">
|
|
<div class="name">Matt C.</div>
|
|
<div class="role">Administrator</div>
|
|
</div>
|
|
</div>
|
|
</aside>
|
|
|
|
<!-- MAIN -->
|
|
<div class="main">
|
|
<header class="topbar">
|
|
<h1>Dashboard</h1>
|
|
<div class="topbar-right">
|
|
<input class="search-box" type="text" placeholder="Search clients, berths, contracts...">
|
|
<div class="icon-btn" style="position:relative;">🔔<span class="dot" style="position:absolute;top:-1px;right:-1px;width:8px;height:8px;background:#d32f2f;border-radius:50%;border:2px solid #fff;"></span></div>
|
|
<div class="icon-btn">+</div>
|
|
</div>
|
|
</header>
|
|
|
|
<div class="content">
|
|
<!-- Welcome -->
|
|
<div class="welcome-banner">
|
|
<h2>Good morning, Matt</h2>
|
|
<p>You have 3 contracts awaiting signature and 2 berth inquiries pending review. Occupancy is trending up this quarter.</p>
|
|
</div>
|
|
|
|
<!-- KPI Row -->
|
|
<div class="kpi-grid">
|
|
<div class="kpi-card">
|
|
<div class="kpi-header">
|
|
<div class="kpi-icon blue">⚓</div>
|
|
<span class="kpi-trend up">▲ 4.2%</span>
|
|
</div>
|
|
<div class="kpi-value">87%</div>
|
|
<div class="kpi-label">Berth Occupancy</div>
|
|
</div>
|
|
<div class="kpi-card">
|
|
<div class="kpi-header">
|
|
<div class="kpi-icon navy">♦</div>
|
|
<span class="kpi-trend up">▲ 12</span>
|
|
</div>
|
|
<div class="kpi-value">248</div>
|
|
<div class="kpi-label">Active Clients</div>
|
|
</div>
|
|
<div class="kpi-card">
|
|
<div class="kpi-header">
|
|
<div class="kpi-icon teal">💰</div>
|
|
<span class="kpi-trend up">▲ 8.1%</span>
|
|
</div>
|
|
<div class="kpi-value">$2.4M</div>
|
|
<div class="kpi-label">Revenue YTD</div>
|
|
</div>
|
|
<div class="kpi-card">
|
|
<div class="kpi-header">
|
|
<div class="kpi-icon purple">✎</div>
|
|
<span class="kpi-trend neutral">— 0</span>
|
|
</div>
|
|
<div class="kpi-value">14</div>
|
|
<div class="kpi-label">Open Interests</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Chart + Activity -->
|
|
<div class="dashboard-grid">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h3>Monthly Revenue</h3>
|
|
<a class="card-action">View report →</a>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="chart-area">
|
|
<div class="chart-bar" style="height:45%;background:var(--brand-blue-60);"><span class="chart-label">Sep</span></div>
|
|
<div class="chart-bar" style="height:55%;background:var(--brand-blue-60);"><span class="chart-label">Oct</span></div>
|
|
<div class="chart-bar" style="height:50%;background:var(--brand-blue-60);"><span class="chart-label">Nov</span></div>
|
|
<div class="chart-bar" style="height:65%;background:var(--brand-blue-60);"><span class="chart-label">Dec</span></div>
|
|
<div class="chart-bar" style="height:75%;background:var(--brand-blue);"><span class="chart-label">Jan</span></div>
|
|
<div class="chart-bar" style="height:80%;background:var(--brand-blue);"><span class="chart-label">Feb</span></div>
|
|
<div class="chart-bar" style="height:90%;background:var(--brand-blue);"><span class="chart-label">Mar</span></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h3>Recent Activity</h3>
|
|
<a class="card-action">View all →</a>
|
|
</div>
|
|
<div class="card-body" style="padding-top:8px;">
|
|
<ul class="activity-list">
|
|
<li class="activity-item">
|
|
<span class="activity-dot green"></span>
|
|
<div class="activity-content">
|
|
<div class="activity-text"><strong>Marcus Thompson</strong> signed berth lease B-14</div>
|
|
<div class="activity-time">12 min ago</div>
|
|
</div>
|
|
</li>
|
|
<li class="activity-item">
|
|
<span class="activity-dot blue"></span>
|
|
<div class="activity-content">
|
|
<div class="activity-text">New interest from <strong>Alessandra Voss</strong> — 60ft vessel</div>
|
|
<div class="activity-time">1 hour ago</div>
|
|
</div>
|
|
</li>
|
|
<li class="activity-item">
|
|
<span class="activity-dot orange"></span>
|
|
<div class="activity-content">
|
|
<div class="activity-text">Invoice #1047 for <strong>Reef Holdings Ltd</strong> overdue</div>
|
|
<div class="activity-time">3 hours ago</div>
|
|
</div>
|
|
</li>
|
|
<li class="activity-item">
|
|
<span class="activity-dot purple"></span>
|
|
<div class="activity-content">
|
|
<div class="activity-text">Contract renewal reminder — <strong>J. Beaumont</strong></div>
|
|
<div class="activity-time">Yesterday</div>
|
|
</div>
|
|
</li>
|
|
<li class="activity-item">
|
|
<span class="activity-dot green"></span>
|
|
<div class="activity-content">
|
|
<div class="activity-text">Payment received from <strong>Windward Capital</strong> — $42,500</div>
|
|
<div class="activity-time">Yesterday</div>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Berths + Quick Actions -->
|
|
<div class="dashboard-grid">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h3>Berth Map — Marina A</h3>
|
|
<a class="card-action">Full map →</a>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="berth-visual">
|
|
<div class="berth-slot occupied">A1</div>
|
|
<div class="berth-slot occupied">A2</div>
|
|
<div class="berth-slot available">A3</div>
|
|
<div class="berth-slot occupied">A4</div>
|
|
<div class="berth-slot reserved">A5</div>
|
|
<div class="berth-slot occupied">A6</div>
|
|
<div class="berth-slot occupied">A7</div>
|
|
<div class="berth-slot maintenance">A8</div>
|
|
<div class="berth-slot occupied">B1</div>
|
|
<div class="berth-slot available">B2</div>
|
|
<div class="berth-slot occupied">B3</div>
|
|
<div class="berth-slot occupied">B4</div>
|
|
<div class="berth-slot occupied">B5</div>
|
|
<div class="berth-slot reserved">B6</div>
|
|
<div class="berth-slot available">B7</div>
|
|
<div class="berth-slot occupied">B8</div>
|
|
<div class="berth-slot occupied">C1</div>
|
|
<div class="berth-slot occupied">C2</div>
|
|
<div class="berth-slot occupied">C3</div>
|
|
<div class="berth-slot available">C4</div>
|
|
<div class="berth-slot occupied">C5</div>
|
|
<div class="berth-slot occupied">C6</div>
|
|
<div class="berth-slot maintenance">C7</div>
|
|
<div class="berth-slot occupied">C8</div>
|
|
</div>
|
|
<div class="berth-legend">
|
|
<div class="berth-legend-item"><div class="dot" style="background:var(--brand-blue);"></div> Occupied</div>
|
|
<div class="berth-legend-item"><div class="dot" style="background:var(--mint);"></div> Available</div>
|
|
<div class="berth-legend-item"><div class="dot" style="background:var(--purple);"></div> Reserved</div>
|
|
<div class="berth-legend-item"><div class="dot" style="background:var(--navy-40);"></div> Maintenance</div>
|
|
</div>
|
|
<div class="occupancy-grid" style="margin-top:16px;">
|
|
<div class="occupancy-card">
|
|
<div class="occ-value" style="color:var(--brand-blue);">17</div>
|
|
<div class="occ-label">Occupied</div>
|
|
<div class="progress-bar"><div class="fill" style="width:71%;background:var(--brand-blue);"></div></div>
|
|
</div>
|
|
<div class="occupancy-card">
|
|
<div class="occ-value" style="color:var(--success);">4</div>
|
|
<div class="occ-label">Available</div>
|
|
<div class="progress-bar"><div class="fill" style="width:17%;background:var(--success);"></div></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="display:flex;flex-direction:column;gap:24px;">
|
|
<div class="card">
|
|
<div class="card-header"><h3>Quick Actions</h3></div>
|
|
<div class="card-body">
|
|
<div class="quick-actions">
|
|
<div class="quick-action-btn"><div class="qa-icon" style="background:var(--brand-blue-20);color:var(--brand-blue);">+</div> New Client</div>
|
|
<div class="quick-action-btn"><div class="qa-icon" style="background:rgba(104,90,163,0.12);color:var(--purple);">✎</div> New Contract</div>
|
|
<div class="quick-action-btn"><div class="qa-icon" style="background:var(--success-bg);color:var(--success);">$</div> New Invoice</div>
|
|
<div class="quick-action-btn"><div class="qa-icon" style="background:rgba(131,170,177,0.15);color:var(--teal);">⚓</div> Berth Assign</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="card">
|
|
<div class="card-header"><h3>Upcoming Renewals</h3></div>
|
|
<div class="card-body" style="padding:0;">
|
|
<table class="data-table">
|
|
<thead><tr><th>Client</th><th>Expires</th><th>Status</th></tr></thead>
|
|
<tbody>
|
|
<tr><td><strong>J. Beaumont</strong></td><td>Mar 28</td><td><span class="status-badge pending">Due soon</span></td></tr>
|
|
<tr><td><strong>Reef Holdings</strong></td><td>Apr 05</td><td><span class="status-badge active">Sent</span></td></tr>
|
|
<tr><td><strong>K. Nakamura</strong></td><td>Apr 12</td><td><span class="status-badge draft">Draft</span></td></tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mockup-label">Mockup A <span>— Dark Sidebar + Light Content</span></div>
|
|
</body>
|
|
</html>
|