// ui.jsx — shared UI primitives & layout chrome // ── Logo: monogram E+H + wordmark ─────────────────────────────── function Logo({ compact=false }) { return (
{/* Stylised E + H monogram */} {!compact && (
EnrollHub
W NAIL SCHOOL
)}
); } // ── Sidebar ───────────────────────────────────────────────────── const NAV_ITEMS = [ { id:'dashboard', label:'ダッシュボード', icon:'home', screen:'dashboard' }, { id:'students', label:'生徒(カルテ)', icon:'users', screen:'student' }, { id:'schedule', label:'予約・スケジュール', icon:'cal' }, { id:'msg', label:'メッセージ', icon:'msg', badge:7 }, { id:'kpi', label:'KPIレポート', icon:'chart', screen:'kpi' }, { id:'mobile', label:'スマホ表示', icon:'phone', screen:'mobile', spacer:true }, { id:'settings', label:'設定', icon:'cog' }, ]; function NavIcon({ name }) { const s = { stroke:'currentColor', fill:'none', strokeWidth:1.6, strokeLinecap:'round', strokeLinejoin:'round' }; switch (name) { case 'home': return ; case 'users': return ; case 'cal': return ; case 'msg': return ; case 'chart': return ; case 'phone': return ; case 'cog': return ; default: return null; } } function Sidebar({ current, onNav, mode='full' /* full|icons */ }) { const width = mode === 'icons' ? 64 : 220; return ( ); } // ── Top bar ───────────────────────────────────────────────────── function TopBar({ school, onSchool, searchPlaceholder='生徒名・LINE名・電話で検索', alerts=3, breadcrumb }) { return (
校舎
{breadcrumb && (
{breadcrumb}
)}
デモ校長
校長
); } // ── Status badge ──────────────────────────────────────────────── function StatusBadge({ s }) { const st = STATUS[s]; if (!st) return null; return ( {st.label} ); } // ── Initial avatar (school colour band) ───────────────────────── const SCHOOL_COLOURS = { umeda:'#D89AAA', kyobashi:'#B5728C', shinsai:'#C9A98C', namba:'#9A8EAA', kobe:'#7A9F7E', shinjuku:'#D6A172', kenshu:'#A89098', }; function Avatar({ name, school, size=36 }) { // Take first kanji of family + first kanji of given → 2 chars const parts = (name || '').split(' '); const init = (parts[0]?.[0] || '') + (parts[1]?.[0] || ''); const colour = SCHOOL_COLOURS[school] || '#C9A98C'; return (
{init || '?'}
); } // ── Section header ────────────────────────────────────────────── function SectionHeader({ title, sub, right, icon }) { return (
{icon &&
}

{title}

{sub && — {sub}}
{right}
); } // ── Small stat tile ───────────────────────────────────────────── function StatTile({ label, value, suffix, delta, tone='default', icon, sub }) { const toneMap = { default: { bg:'#fff', accent:'#D89AAA', text:'#5D3848' }, alert: { bg:'#FBE9EE', accent:'#C9536A', text:'#A23A55' }, ok: { bg:'#E8EEE6', accent:'#7A9F7E', text:'#4F7559' }, warn: { bg:'#FAEEDC', accent:'#D6A172', text:'#86592E' }, }; const T = toneMap[tone] || toneMap.default; return (
{label} {icon}
{value} {suffix && {suffix}}
{(delta || sub) && (
{delta && ( {delta} )} {sub && {sub}}
)}
); } Object.assign(window, { Logo, Sidebar, TopBar, StatusBadge, Avatar, SectionHeader, StatTile, NavIcon, NAV_ITEMS, SCHOOL_COLOURS });