gentelella
Version:
Gentelella v4 — free admin template. 60 pages, 20 chart variants, fully interactive inbox & kanban, live theme generator, component playground, PWA-ready. Vite 8, vanilla JS, no Bootstrap, no jQuery.
97 lines (88 loc) • 4.86 kB
HTML
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Projects | Gentelella 2026 v4</title>
<link rel="icon" href="../images/favicon.svg" type="image/svg+xml">
<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=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<script type="module" src="/src/main-v4.js"></script>
</head>
<body data-shell="admin" data-page="projects" data-breadcrumb="Home > Projects">
<main class="main">
<div class="page-wrapper">
<div class="page-header">
<div class="page-header-row">
<div>
<div class="page-pretitle">Workspace</div>
<h1 class="page-title">Projects</h1>
</div>
<div class="page-actions">
<button class="btn btn-outline">Filters</button>
<button class="btn btn-primary">
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 8h8M8 4v8"/></svg>
New project
</button>
</div>
</div>
</div>
<div class="row col-3" id="projects-grid"></div>
</div>
</main>
<script type="module">
const projects = [
['Acme Website Redesign', 'Acme Corp', 'On track', 'green', 'Refresh of the public marketing site with new brand identity.', 78, 'Apr 30', ['SK','MR','EW']],
['Mobile App v2', 'Globex Inc', 'At risk', 'yellow', 'Major rewrite of the iOS/Android app on shared React Native core.', 42, 'Jun 15', ['MK','LP','DR','YT']],
['Internal Dashboard', 'Initech', 'On track', 'green', 'New analytics dashboard replacing the legacy Tableau setup.', 91, 'May 12', ['TH','MR']],
['Q2 Marketing Campaign', 'Acme Corp', 'On track', 'green', 'Cross-channel campaign for the new product line launch.', 33, 'May 28', ['LP','EW','SK']],
['Payment Migration', 'Stark Ind.', 'Blocked', 'red', 'Move from legacy gateway to new processor with zero downtime.', 18, 'Jul 02', ['DR','MK']],
['Design System v3', 'Internal', 'On track', 'green', 'Tokens, components, and Figma library refresh for v4 era.', 64, 'May 20', ['SK','EW','LP','TH']],
['Help Center Rewrite', 'Umbrella Co', 'On hold', 'yellow', 'Migration to new docs platform with full content audit.', 5, 'TBD', ['YT','MR']],
['SOC 2 Compliance', 'Internal', 'On track', 'green', 'Type II audit prep with controls, evidence, and policies.', 72, 'Jun 30', ['DR','TH']],
['Pricing Experiment', 'Tyrell Corp', 'On track', 'green', 'A/B test of three new pricing tiers across funnel.', 50, 'May 05', ['LP','MK']]
];
const colorMap = { primary:'var(--primary)', azure:'var(--azure)', purple:'var(--purple)', yellow:'var(--yellow)', red:'var(--red)', green:'var(--green)', blue:'var(--blue)' };
const memberColors = { SK:'azure', MR:'purple', EW:'yellow', MK:'red', LP:'green', DR:'blue', YT:'primary', TH:'purple' };
const statusCls = { green:'status-green', yellow:'status-yellow', red:'status-red' };
const grid = document.getElementById('projects-grid');
grid.innerHTML = projects.map(([title, client, status, sCls, desc, pct, due, members], idx) => `
<button type="button" class="project-card" data-idx="${idx}">
<div class="top">
<div>
<div class="title">${title}</div>
<div class="client">${client}</div>
</div>
<span class="status ${statusCls[sCls]}">${status}</span>
</div>
<div class="desc">${desc}</div>
<div>
<div style="display:flex;justify-content:space-between;font-size:11.5px;color:var(--text-muted);margin-bottom:4px">
<span>Progress</span><span class="cell-strong">${pct}%</span>
</div>
<div class="progress-thin"><div class="bar" style="width:${pct}%;background:var(--${sCls === 'red' ? 'red' : sCls === 'yellow' ? 'yellow' : 'primary'})"></div></div>
</div>
<div class="footer-row">
<div class="avatars">
${members.map((m) => `<div class="av" style="background:${colorMap[memberColors[m] || 'primary']}">${m}</div>`).join('')}
</div>
<span>Due ${due}</span>
</div>
</button>
`).join('');
// Wire card clicks → detail modal.
import('/src/v4/details.js').then(({ openProjectModal }) => {
grid.addEventListener('click', (e) => {
const card = e.target.closest('.project-card');
if (!card) return;
const idx = parseInt(card.dataset.idx, 10);
const p = projects[idx];
if (!p) return;
const [title, client, status, sCls, desc, pct, due, members] = p;
openProjectModal({ title, client, status, sCls, desc, pct, due, members });
});
});
</script>
</body>
</html>