Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/web/src/features/crm/CrmPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ export function CrmWorkspace() {
return <div className={`module-page-shell crm-page ${headerCollapsed ? 'is-header-collapsed' : ''}`}>
<div className="crm-topbar">
<header className="crm-header">
<div className="crm-heading-group"><div className="crm-module-mark" aria-hidden="true"><ContactRound size={29} strokeWidth={1.5} /></div><div><div className="crm-eyebrow">{t('客户工作台', 'RELATIONSHIP WORKSPACE')}<span>CRM</span></div><h1 className="type-page-title">{t('客户管理', 'Customers')}</h1><p>{mode === 'b2b' ? t('从第一次接触,到下一次合作。', 'From the first hello to the next partnership.') : t('记住每一份偏好,让关系更进一步。', 'Remember the little things. Build lasting relationships.')}</p></div></div>
<div className="crm-header-actions"><div className="crm-segmented" aria-label={t('客户模式', 'Customer mode')}>{(['b2b', 'b2c'] as const).map(m => <button key={m} disabled={!!editor || busy} aria-pressed={mode === m} onClick={() => { setParams({ mode: m }); setChecked([]); setFilter('all'); setQuery('') }}>{m === 'b2b' ? <Building2 size={15} /> : <Users size={15} />}{m === 'b2b' ? t('toB 企业', 'B2B · Companies') : t('toC 个人', 'B2C · People')}</button>)}</div><button className="crm-primary" disabled={!!editor || busy} onClick={() => setEditor({ kind: 'customer' })}><Plus size={16} />{t('新建客户', 'New customer')}</button><button className="crm-collapse-header" aria-expanded={!headerCollapsed} aria-controls="crm-overview" onClick={toggleHeader}>{headerCollapsed ? <ChevronDown size={15} /> : <ChevronUp size={15} />}{headerCollapsed ? t('展开顶栏', 'Expand header') : t('收起顶栏', 'Collapse header')}</button></div>
<div className="crm-heading-group"><ContactRound size={21} strokeWidth={1.6} aria-hidden="true" /><h1 className="type-page-title">{t('客户管理', 'Customers')}</h1></div>
<div className="crm-header-actions"><div className="crm-segmented" aria-label={t('客户模式', 'Customer mode')}>{(['b2b', 'b2c'] as const).map(m => <button key={m} disabled={!!editor || busy} aria-pressed={mode === m} onClick={() => { setParams({ mode: m }); setChecked([]); setFilter('all'); setQuery('') }}>{m === 'b2b' ? <Building2 size={15} /> : <Users size={15} />}{m === 'b2b' ? t('toB 企业', 'B2B · Companies') : t('toC 个人', 'B2C · People')}</button>)}</div><button className="crm-primary" disabled={!!editor || busy} onClick={() => setEditor({ kind: 'customer' })}><Plus size={16} />{t('新建客户', 'New customer')}</button><button className="crm-collapse-header" aria-expanded={!headerCollapsed} aria-controls="crm-overview" onClick={toggleHeader}>{headerCollapsed ? <ChevronDown size={15} /> : <ChevronUp size={15} />}{headerCollapsed ? t('展开概览', 'Show overview') : t('收起概览', 'Hide overview')}</button></div>
</header>
<div className="crm-summary" id="crm-overview" hidden={headerCollapsed}>
<div className="crm-agenda-summary"><span className="crm-summary-caption"><CalendarDays size={15} />{t('今日行动', 'TODAY’S AGENDA')}</span><div>
Expand Down
67 changes: 67 additions & 0 deletions apps/web/src/features/crm/crm.css
Original file line number Diff line number Diff line change
Expand Up @@ -338,3 +338,70 @@ html[data-motion="reduce"] .crm-page button.crm-deal-card:hover { transform: non
.crm-page.is-header-collapsed .crm-header-actions { justify-content: flex-start; gap: 8px; }
.crm-header button.crm-collapse-header { margin-left: auto; }
}

/* A compact working desk: customer records take priority over the overview. */
.focus-shell__route-layer:has(.crm-page) { padding: 12px; }
.crm-page { --crm-space: 0px; max-width: none; }
.crm-header,
.crm-page.is-header-collapsed .crm-header {
padding: 8px 4px 12px;
min-height: 52px;
gap: 16px;
margin-bottom: 0;
border-radius: 0;
background: transparent;
color: var(--ink-1);
}
.crm-heading-group { gap: 9px; }
.crm-heading-group > svg { color: var(--accent); flex-shrink: 0; }
.crm-header h1,
.crm-page.is-header-collapsed .crm-header h1 { color: var(--ink-1); font-size: 1.25rem; line-height: 1.4; white-space: nowrap; }
.crm-header-actions,
.crm-page.is-header-collapsed .crm-header-actions { gap: 8px; max-width: none; }
.crm-header .crm-segmented { padding: 3px; background: var(--paper-sunken); border-color: var(--rule); }
.crm-header .crm-segmented button { color: var(--ink-2); padding: 6px 9px; }
.crm-header .crm-segmented button[aria-pressed="true"],
.crm-header .crm-segmented button:hover { color: var(--accent); background: var(--paper-raised); }
.crm-header button.crm-primary { padding: 8px 12px; background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.crm-header button.crm-primary:hover:not(:disabled) { background: color-mix(in srgb, var(--accent) 88%, var(--ink-1)); color: var(--accent-ink); }
.crm-header button.crm-collapse-header { color: var(--ink-3); padding: 7px 8px; }
.crm-header button.crm-collapse-header:hover { color: var(--ink-1); background: var(--paper-sunken); }
.crm-summary { grid-template-columns: minmax(310px, 1.3fr) minmax(0, 1fr) minmax(0, 1fr); gap: 16px; padding: 0 4px 10px; }
.crm-agenda-summary { display: flex; align-items: center; gap: 14px; padding: 8px 12px; border-radius: 7px; }
.crm-agenda-summary > div { display: flex; gap: 12px; margin-top: 0; flex: 1; }
.crm-page .crm-agenda-summary button { align-items: center; gap: 6px; flex-wrap: wrap; }
.crm-agenda-summary button + button { padding-left: 12px; }
.crm-agenda-summary button > span { font-size: .75rem; }
.crm-summary strong { font-size: 1.125rem; line-height: 1.3; }
.crm-sales-summary, .crm-won-summary { flex-direction: row; align-items: center; justify-content: flex-start; gap: 12px; }
.crm-sales-summary { padding-right: 16px; }
.crm-summary .crm-summary-money { font-size: 1.125rem; }
.crm-view-nav { margin-bottom: 10px; }
.crm-view-nav > button { padding: 9px 12px; }
.crm-list-toolbar { padding: 9px 12px; }
.crm-detail-header { padding: 18px 22px 14px; }
.crm-detail-body { padding: 0 22px; }
@media (min-width: 701px) {
.crm-workspace { grid-template-columns: clamp(260px, 24%, 340px) minmax(0, 1fr); gap: 12px; }
.crm-workspace.is-pipeline.has-detail { grid-template-columns: minmax(280px, .8fr) minmax(0, 1.5fr); gap: 12px; }
}
@media (min-width: 701px) and (max-width: 1100px) {
.crm-summary { grid-template-columns: 1.5fr 1fr 1fr; gap: 12px; }
.crm-agenda-summary { gap: 8px; padding: 8px; }
.crm-agenda-summary > .crm-summary-caption { display: none; }
.crm-sales-summary, .crm-won-summary { flex-wrap: wrap; gap: 4px 10px; }
}
@media (max-width: 700px) {
.focus-shell__route-layer:has(.crm-page) { padding: 8px; }
.crm-header, .crm-page.is-header-collapsed .crm-header { flex-direction: column; align-items: stretch; padding: 4px 0 10px; gap: 8px; }
.crm-header-actions, .crm-page.is-header-collapsed .crm-header-actions { justify-content: flex-start; width: 100%; gap: 6px; }
.crm-header button.crm-collapse-header { margin-left: auto; font-size: .6875rem; padding-inline: 3px; }
.crm-header .crm-segmented button { font-size: .6875rem; padding-inline: 6px; }
.crm-summary { grid-template-columns: 1fr 1fr; gap: 10px; padding: 0 0 10px; }
.crm-agenda-summary { grid-column: 1 / -1; }
.crm-sales-summary, .crm-won-summary { flex-wrap: wrap; gap: 6px; }
.crm-sales-summary { padding-right: 8px; }
.crm-view-nav > button { padding: 9px 6px; }
.crm-detail-header { padding: 16px; }
.crm-detail-body { padding: 0 16px; }
}
Loading