medicodeapp / frontend /src /app /features /docs /docs.component.ts
Denisijcu's picture
upload files
c98875e
import { Component, signal } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterLink } from '@angular/router';
import { FormsModule } from '@angular/forms';
interface DocSection {
id: string;
icon: string;
title: string;
description: string;
articles: { title: string; badge?: string; badgeColor?: string }[];
}
@Component({
selector: 'app-docs',
standalone: true,
imports: [CommonModule, RouterLink, FormsModule],
template: `
<div class="docs-page">
<!-- Hero -->
<div class="docs-hero">
<div class="hero-content">
<span class="hero-eyebrow">Documentation</span>
<h1>Everything you need to get started</h1>
<p>Guides, references, and tutorials for the MediCode platform.</p>
<!-- Search bar -->
<div class="docs-search">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/>
</svg>
<input
type="text"
placeholder="Search documentation…"
[(ngModel)]="searchQuery"
/>
<kbd>⌘K</kbd>
</div>
</div>
<div class="hero-graphic">
<div class="graphic-badge badge-icd">ICD-10</div>
<div class="graphic-badge badge-cpt">CPT</div>
<div class="graphic-badge badge-api">REST API</div>
<div class="graphic-ring"></div>
</div>
</div>
<!-- Quick links -->
<div class="quick-links">
@for (q of quickLinks; track q.title) {
<div class="quick-card" [class]="'quick-' + q.color">
<div class="quick-icon" [innerHTML]="q.icon"></div>
<div>
<div class="quick-title">{{ q.title }}</div>
<div class="quick-sub">{{ q.sub }}</div>
</div>
<svg class="quick-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M5 12h14M12 5l7 7-7 7"/>
</svg>
</div>
}
</div>
<!-- Main content -->
<div class="docs-body">
<!-- Sidebar TOC -->
<aside class="docs-toc">
<div class="toc-title">On this page</div>
@for (s of sections; track s.id) {
<a
class="toc-link"
[class.active]="activeSection() === s.id"
(click)="scrollTo(s.id)"
>
{{ s.title }}
</a>
}
</aside>
<!-- Sections -->
<div class="docs-content">
@for (s of sections; track s.id) {
<section [id]="s.id" class="doc-section">
<div class="section-header">
<div class="section-icon" [innerHTML]="s.icon"></div>
<div>
<h2>{{ s.title }}</h2>
<p>{{ s.description }}</p>
</div>
</div>
<div class="articles-grid">
@for (a of s.articles; track a.title) {
<div class="article-card">
<div class="article-top">
<span class="article-title">{{ a.title }}</span>
@if (a.badge) {
<span class="article-badge" [class]="'badge-' + a.badgeColor">{{ a.badge }}</span>
}
</div>
<svg class="article-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M5 12h14M12 5l7 7-7 7"/>
</svg>
</div>
}
</div>
</section>
}
</div>
</div>
<!-- Help banner -->
<div class="help-banner">
<div class="help-text">
<h3>Can't find what you're looking for?</h3>
<p>Our support team is available Monday–Friday, 9am–6pm EST.</p>
</div>
<div class="help-actions">
<a href="mailto:support@medicode.io" class="btn-outline">✉️ Email Support</a>
<a routerLink="/api" class="btn-primary">View API Docs</a>
</div>
</div>
</div>
`,
styles: [`
.docs-page {
padding: 0;
max-width: 1400px;
margin: 0 auto;
font-family: 'Inter', system-ui, sans-serif;
}
/* ── Hero ──────────────────────────────────────── */
.docs-hero {
display: flex;
align-items: center;
justify-content: space-between;
padding: 3rem 2rem 2.5rem;
background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%);
border-bottom: 1px solid #bae6fd;
position: relative;
overflow: hidden;
}
.hero-content { max-width: 540px; }
.hero-eyebrow {
font-size: 0.75rem;
font-weight: 700;
color: #0EA5E9;
text-transform: uppercase;
letter-spacing: 0.1em;
display: block;
margin-bottom: 0.75rem;
}
.docs-hero h1 {
font-size: 2rem;
font-weight: 800;
color: #0f172a;
margin: 0 0 0.75rem;
line-height: 1.2;
letter-spacing: -0.02em;
}
.docs-hero p {
color: #475569;
margin: 0 0 1.5rem;
font-size: 1rem;
}
.docs-search {
display: flex;
align-items: center;
gap: 0.75rem;
background: white;
border: 1.5px solid #bae6fd;
border-radius: 10px;
padding: 0.75rem 1rem;
max-width: 420px;
box-shadow: 0 1px 3px rgba(0,0,0,0.06);
}
.docs-search svg { width: 18px; height: 18px; color: #94a3b8; flex-shrink: 0; }
.docs-search input {
flex: 1;
border: none;
outline: none;
font-size: 0.9rem;
color: #0f172a;
background: transparent;
}
.docs-search input::placeholder { color: #94a3b8; }
.docs-search kbd {
background: #f1f5f9;
border: 1px solid #e2e8f0;
border-radius: 5px;
font-size: 0.7rem;
color: #64748b;
padding: 0.15rem 0.4rem;
}
/* Decorative graphic */
.hero-graphic {
position: relative;
width: 200px;
height: 200px;
flex-shrink: 0;
display: none;
}
@media (min-width: 900px) { .hero-graphic { display: block; } }
.graphic-ring {
width: 160px;
height: 160px;
border-radius: 50%;
border: 2px dashed #bae6fd;
position: absolute;
top: 20px;
left: 20px;
animation: spin 20s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.graphic-badge {
position: absolute;
font-size: 0.7rem;
font-weight: 700;
padding: 0.35rem 0.75rem;
border-radius: 99px;
letter-spacing: 0.04em;
}
.badge-icd { background: #eff6ff; color: #1d4ed8; border: 1px solid #bfdbfe; top: 20px; left: 30px; }
.badge-cpt { background: #f0fdf4; color: #15803d; border: 1px solid #bbf7d0; bottom: 30px; left: 10px; }
.badge-api { background: #faf5ff; color: #7c3aed; border: 1px solid #ddd6fe; top: 50%; right: 0; transform: translateY(-50%); }
/* ── Quick links ───────────────────────────────── */
.quick-links {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
gap: 1rem;
padding: 2rem 2rem 0;
}
.quick-card {
display: flex;
align-items: center;
gap: 1rem;
padding: 1.1rem 1.25rem;
border-radius: 12px;
border: 1px solid #e2e8f0;
background: white;
cursor: pointer;
transition: all 0.15s;
}
.quick-card:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,0.08); }
.quick-icon {
width: 38px;
height: 38px;
border-radius: 9px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.quick-icon :deep(svg) { width: 20px; height: 20px; }
.quick-blue .quick-icon { background: #eff6ff; color: #3b82f6; }
.quick-green .quick-icon { background: #f0fdf4; color: #10b981; }
.quick-purple .quick-icon { background: #faf5ff; color: #8b5cf6; }
.quick-sky .quick-icon { background: #f0f9ff; color: #0EA5E9; }
.quick-title { font-size: 0.9rem; font-weight: 600; color: #0f172a; }
.quick-sub { font-size: 0.78rem; color: #64748b; margin-top: 0.15rem; }
.quick-arrow { width: 16px; height: 16px; color: #94a3b8; margin-left: auto; flex-shrink: 0; }
/* ── Body layout ───────────────────────────────── */
.docs-body {
display: grid;
grid-template-columns: 220px 1fr;
gap: 2rem;
padding: 2rem;
align-items: start;
}
/* TOC */
.docs-toc {
position: sticky;
top: 1.5rem;
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.toc-title {
font-size: 0.7rem;
font-weight: 700;
color: #94a3b8;
text-transform: uppercase;
letter-spacing: 0.1em;
margin-bottom: 0.5rem;
}
.toc-link {
font-size: 0.85rem;
color: #64748b;
cursor: pointer;
padding: 0.35rem 0.75rem;
border-radius: 6px;
border-left: 2px solid transparent;
transition: all 0.12s;
}
.toc-link:hover { color: #0EA5E9; background: #f0f9ff; }
.toc-link.active { color: #0EA5E9; border-left-color: #0EA5E9; background: #f0f9ff; font-weight: 600; }
/* Sections */
.docs-content { display: flex; flex-direction: column; gap: 2.5rem; }
.doc-section { scroll-margin-top: 1.5rem; }
.section-header {
display: flex;
align-items: flex-start;
gap: 1rem;
margin-bottom: 1.25rem;
}
.section-icon {
width: 44px;
height: 44px;
border-radius: 10px;
background: #f0f9ff;
color: #0EA5E9;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.section-icon :deep(svg) { width: 22px; height: 22px; }
.section-header h2 {
font-size: 1.1rem;
font-weight: 700;
color: #0f172a;
margin: 0 0 0.25rem;
}
.section-header p {
font-size: 0.85rem;
color: #64748b;
margin: 0;
}
.articles-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 0.75rem;
}
.article-card {
background: white;
border: 1px solid #e2e8f0;
border-radius: 10px;
padding: 1rem 1.1rem;
cursor: pointer;
transition: all 0.15s;
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.75rem;
}
.article-card:hover {
border-color: #0EA5E9;
box-shadow: 0 0 0 3px rgba(14,165,233,0.08);
}
.article-top { display: flex; flex-direction: column; gap: 0.35rem; }
.article-title { font-size: 0.875rem; font-weight: 600; color: #1e293b; }
.article-badge {
font-size: 0.65rem;
font-weight: 700;
padding: 0.15rem 0.45rem;
border-radius: 99px;
width: fit-content;
}
.badge-green { background: #f0fdf4; color: #15803d; border: 1px solid #bbf7d0; }
.badge-blue { background: #eff6ff; color: #1d4ed8; border: 1px solid #bfdbfe; }
.badge-sky { background: #f0f9ff; color: #0369a1; border: 1px solid #bae6fd; }
.badge-purple{ background: #faf5ff; color: #7c3aed; border: 1px solid #ddd6fe; }
.article-arrow { width: 15px; height: 15px; color: #cbd5e1; flex-shrink: 0; transition: color 0.15s; }
.article-card:hover .article-arrow { color: #0EA5E9; }
/* ── Help banner ───────────────────────────────── */
.help-banner {
margin: 0 2rem 2rem;
background: linear-gradient(135deg, #0f172a 0%, #1e3a5f 100%);
border-radius: 14px;
padding: 2rem 2.5rem;
display: flex;
align-items: center;
justify-content: space-between;
gap: 2rem;
flex-wrap: wrap;
}
.help-banner h3 { font-size: 1.1rem; font-weight: 700; color: #f8fafc; margin: 0 0 0.35rem; }
.help-banner p { font-size: 0.875rem; color: #94a3b8; margin: 0; }
.help-actions { display: flex; gap: 0.75rem; flex-wrap: wrap; }
.btn-primary {
padding: 0.65rem 1.25rem;
background: #0EA5E9;
color: white;
border-radius: 8px;
font-weight: 600;
font-size: 0.875rem;
text-decoration: none;
transition: background 0.15s;
}
.btn-primary:hover { background: #0284c7; }
.btn-outline {
padding: 0.65rem 1.25rem;
background: transparent;
color: #cbd5e1;
border: 1px solid #334155;
border-radius: 8px;
font-weight: 600;
font-size: 0.875rem;
text-decoration: none;
transition: all 0.15s;
}
.btn-outline:hover { border-color: #94a3b8; color: #f1f5f9; }
@media (max-width: 900px) {
.docs-body { grid-template-columns: 1fr; }
.docs-toc { display: none; }
}
`],
})
export class DocsComponent {
searchQuery = '';
activeSection = signal('getting-started');
scrollTo(id: string) {
this.activeSection.set(id);
document.getElementById(id)?.scrollIntoView({ behavior: 'smooth' });
}
quickLinks = [
{
title: 'Getting Started',
sub: '5-minute setup guide',
color: 'blue',
icon: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/></svg>`,
},
{
title: 'ICD-10 Reference',
sub: 'Diagnostic code lookup',
color: 'green',
icon: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>`,
},
{
title: 'CPT Codes',
sub: 'Procedure coding guide',
color: 'purple',
icon: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></svg>`,
},
{
title: 'API Reference',
sub: 'REST endpoints & auth',
color: 'sky',
icon: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>`,
},
];
sections: DocSection[] = [
{
id: 'getting-started',
title: 'Getting Started',
description: 'Everything you need to set up and configure MediCode for your practice.',
icon: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/></svg>`,
articles: [
{ title: 'Platform Overview', badge: 'Start here', badgeColor: 'green' },
{ title: 'Creating Your Account' },
{ title: 'Roles & Permissions', badge: 'Admin', badgeColor: 'purple' },
{ title: 'Onboarding Checklist' },
],
},
{
id: 'patients',
title: 'Patient Management',
description: 'How to create, update, and manage patient records and encounters.',
icon: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/></svg>`,
articles: [
{ title: 'Adding a New Patient' },
{ title: 'Encounter Workflow', badge: 'Core', badgeColor: 'blue' },
{ title: 'Attaching ICD-10 Codes' },
{ title: 'Attaching CPT Codes' },
{ title: 'Billing Status Lifecycle' },
{ title: 'Exporting Patient Data' },
],
},
{
id: 'coding',
title: 'Medical Coding',
description: 'Reference guides for ICD-10-CM diagnostic codes and CPT procedure codes.',
icon: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>`,
articles: [
{ title: 'ICD-10-CM Structure', badge: 'ICD-10', badgeColor: 'blue' },
{ title: 'CPT Code Categories', badge: 'CPT', badgeColor: 'green' },
{ title: 'Code Search Tips' },
{ title: 'Modifier Usage' },
],
},
{
id: 'reports',
title: 'Reports & Analytics',
description: 'Generate, filter, and export reports for your coding activity.',
icon: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 3v18h18"/><path d="m19 9-5 5-4-4-3 3"/></svg>`,
articles: [
{ title: 'Encounters by Month' },
{ title: 'Top Diagnoses Report' },
{ title: 'Export to PDF', badge: 'PDF', badgeColor: 'sky' },
{ title: 'Export to Excel', badge: 'Excel', badgeColor: 'green' },
],
},
{
id: 'api',
title: 'API Integration',
description: 'Integrate MediCode with your existing systems via our REST API.',
icon: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>`,
articles: [
{ title: 'Authentication & JWT', badge: 'Auth', badgeColor: 'purple' },
{ title: 'Patients Endpoints' },
{ title: 'Codes Endpoints' },
{ title: 'Webhooks' },
],
},
];
}