fix: replace hardcoded text-white with DS variables, fix label/value layout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import type { Column } from '@cameleer/design-system';
|
|||||||
import { useAllTenants } from '../api/hooks';
|
import { useAllTenants } from '../api/hooks';
|
||||||
import { useOrgStore } from '../auth/useOrganization';
|
import { useOrgStore } from '../auth/useOrganization';
|
||||||
import type { TenantResponse } from '../types/api';
|
import type { TenantResponse } from '../types/api';
|
||||||
|
import styles from '../styles/platform.module.css';
|
||||||
|
|
||||||
const columns: Column<TenantResponse>[] = [
|
const columns: Column<TenantResponse>[] = [
|
||||||
{ key: 'name', header: 'Name' },
|
{ key: 'name', header: 'Name' },
|
||||||
@@ -59,7 +60,7 @@ export function AdminTenantsPage() {
|
|||||||
return (
|
return (
|
||||||
<div className="space-y-6 p-6">
|
<div className="space-y-6 p-6">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<h1 className="text-2xl font-semibold text-white">All Tenants</h1>
|
<h1 className={styles.heading}>All Tenants</h1>
|
||||||
<Badge label="Platform Admin" color="warning" />
|
<Badge label="Platform Admin" color="warning" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
} from '@cameleer/design-system';
|
} from '@cameleer/design-system';
|
||||||
import { useAuth } from '../auth/useAuth';
|
import { useAuth } from '../auth/useAuth';
|
||||||
import { useTenant, useLicense } from '../api/hooks';
|
import { useTenant, useLicense } from '../api/hooks';
|
||||||
|
import styles from '../styles/platform.module.css';
|
||||||
|
|
||||||
function tierColor(tier: string): 'primary' | 'success' | 'warning' | 'error' {
|
function tierColor(tier: string): 'primary' | 'success' | 'warning' | 'error' {
|
||||||
switch (tier?.toLowerCase()) {
|
switch (tier?.toLowerCase()) {
|
||||||
@@ -68,7 +69,7 @@ export function DashboardPage() {
|
|||||||
{/* Tenant Header */}
|
{/* Tenant Header */}
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<h1 className="text-2xl font-semibold text-white">
|
<h1 className={styles.heading}>
|
||||||
{tenant?.name ?? tenantId}
|
{tenant?.name ?? tenantId}
|
||||||
</h1>
|
</h1>
|
||||||
{tenant?.tier && (
|
{tenant?.tier && (
|
||||||
@@ -92,28 +93,28 @@ export function DashboardPage() {
|
|||||||
|
|
||||||
{/* Tenant Info */}
|
{/* Tenant Info */}
|
||||||
<Card title="Tenant Information">
|
<Card title="Tenant Information">
|
||||||
<div className="space-y-2 text-sm">
|
<div className="space-y-2">
|
||||||
<div className="flex justify-between text-white/80">
|
<div className={styles.kvRow}>
|
||||||
<span>Slug</span>
|
<span className={styles.kvLabel}>Slug</span>
|
||||||
<span className="font-mono">{tenant?.slug ?? '-'}</span>
|
<span className={styles.kvValueMono}>{tenant?.slug ?? '-'}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between text-white/80">
|
<div className={styles.kvRow}>
|
||||||
<span>Status</span>
|
<span className={styles.kvLabel}>Status</span>
|
||||||
<Badge
|
<Badge
|
||||||
label={tenant?.status ?? 'UNKNOWN'}
|
label={tenant?.status ?? 'UNKNOWN'}
|
||||||
color={tenant?.status === 'ACTIVE' ? 'success' : 'warning'}
|
color={tenant?.status === 'ACTIVE' ? 'success' : 'warning'}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between text-white/80">
|
<div className={styles.kvRow}>
|
||||||
<span>Created</span>
|
<span className={styles.kvLabel}>Created</span>
|
||||||
<span>{tenant?.createdAt ? new Date(tenant.createdAt).toLocaleDateString() : '-'}</span>
|
<span className={styles.kvValue}>{tenant?.createdAt ? new Date(tenant.createdAt).toLocaleDateString() : '-'}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
{/* Server Dashboard Link */}
|
{/* Server Dashboard Link */}
|
||||||
<Card title="Server Management">
|
<Card title="Server Management">
|
||||||
<p className="text-sm text-white/60 mb-3">
|
<p className={`${styles.description} mb-3`}>
|
||||||
Environments, applications, and deployments are managed through the server dashboard.
|
Environments, applications, and deployments are managed through the server dashboard.
|
||||||
</p>
|
</p>
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
} from '@cameleer/design-system';
|
} from '@cameleer/design-system';
|
||||||
import { useAuth } from '../auth/useAuth';
|
import { useAuth } from '../auth/useAuth';
|
||||||
import { useLicense } from '../api/hooks';
|
import { useLicense } from '../api/hooks';
|
||||||
|
import styles from '../styles/platform.module.css';
|
||||||
|
|
||||||
const FEATURE_LABELS: Record<string, string> = {
|
const FEATURE_LABELS: Record<string, string> = {
|
||||||
topology: 'Topology',
|
topology: 'Topology',
|
||||||
@@ -82,7 +83,7 @@ export function LicensePage() {
|
|||||||
<div className="space-y-6 p-6">
|
<div className="space-y-6 p-6">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<h1 className="text-2xl font-semibold text-white">License</h1>
|
<h1 className={styles.heading}>License</h1>
|
||||||
<Badge
|
<Badge
|
||||||
label={license.tier.toUpperCase()}
|
label={license.tier.toUpperCase()}
|
||||||
color={tierColor(license.tier)}
|
color={tierColor(license.tier)}
|
||||||
@@ -91,10 +92,10 @@ export function LicensePage() {
|
|||||||
|
|
||||||
{/* Expiry info */}
|
{/* Expiry info */}
|
||||||
<Card title="Validity">
|
<Card title="Validity">
|
||||||
<div className="flex flex-col gap-2 text-sm">
|
<div className="flex flex-col gap-2">
|
||||||
<div className="flex items-center justify-between">
|
<div className={styles.kvRow}>
|
||||||
<span className="text-white/60">Issued</span>
|
<span className={styles.kvLabel}>Issued</span>
|
||||||
<span className="text-white">
|
<span className={styles.kvValue}>
|
||||||
{new Date(license.issuedAt).toLocaleDateString(undefined, {
|
{new Date(license.issuedAt).toLocaleDateString(undefined, {
|
||||||
year: 'numeric',
|
year: 'numeric',
|
||||||
month: 'long',
|
month: 'long',
|
||||||
@@ -102,12 +103,12 @@ export function LicensePage() {
|
|||||||
})}
|
})}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center justify-between">
|
<div className={styles.kvRow}>
|
||||||
<span className="text-white/60">Expires</span>
|
<span className={styles.kvLabel}>Expires</span>
|
||||||
<span className="text-white">{expDate}</span>
|
<span className={styles.kvValue}>{expDate}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center justify-between">
|
<div className={styles.kvRow}>
|
||||||
<span className="text-white/60">Days remaining</span>
|
<span className={styles.kvLabel}>Days remaining</span>
|
||||||
<Badge
|
<Badge
|
||||||
label={isExpired ? 'Expired' : `${days} days`}
|
label={isExpired ? 'Expired' : `${days} days`}
|
||||||
color={isExpired ? 'error' : isExpiringSoon ? 'warning' : 'success'}
|
color={isExpired ? 'error' : isExpiringSoon ? 'warning' : 'success'}
|
||||||
@@ -118,15 +119,12 @@ export function LicensePage() {
|
|||||||
|
|
||||||
{/* Feature matrix */}
|
{/* Feature matrix */}
|
||||||
<Card title="Features">
|
<Card title="Features">
|
||||||
<div className="divide-y divide-white/10">
|
<div className={styles.dividerList}>
|
||||||
{Object.entries(FEATURE_LABELS).map(([key, label]) => {
|
{Object.entries(FEATURE_LABELS).map(([key, label]) => {
|
||||||
const enabled = license.features[key] ?? false;
|
const enabled = license.features[key] ?? false;
|
||||||
return (
|
return (
|
||||||
<div
|
<div key={key} className={styles.dividerRow}>
|
||||||
key={key}
|
<span className={styles.kvLabel}>{label}</span>
|
||||||
className="flex items-center justify-between py-3 first:pt-0 last:pb-0"
|
|
||||||
>
|
|
||||||
<span className="text-sm text-white">{label}</span>
|
|
||||||
<Badge
|
<Badge
|
||||||
label={enabled ? 'Enabled' : 'Not included'}
|
label={enabled ? 'Enabled' : 'Not included'}
|
||||||
color={enabled ? 'success' : 'auto'}
|
color={enabled ? 'success' : 'auto'}
|
||||||
@@ -139,16 +137,13 @@ export function LicensePage() {
|
|||||||
|
|
||||||
{/* Limits */}
|
{/* Limits */}
|
||||||
<Card title="Limits">
|
<Card title="Limits">
|
||||||
<div className="divide-y divide-white/10">
|
<div className={styles.dividerList}>
|
||||||
{Object.entries(LIMIT_LABELS).map(([key, label]) => {
|
{Object.entries(LIMIT_LABELS).map(([key, label]) => {
|
||||||
const value = license.limits[key];
|
const value = license.limits[key];
|
||||||
return (
|
return (
|
||||||
<div
|
<div key={key} className={styles.dividerRow}>
|
||||||
key={key}
|
<span className={styles.kvLabel}>{label}</span>
|
||||||
className="flex items-center justify-between py-3 first:pt-0 last:pb-0"
|
<span className={styles.kvValueMono}>
|
||||||
>
|
|
||||||
<span className="text-sm text-white/60">{label}</span>
|
|
||||||
<span className="text-sm font-mono text-white">
|
|
||||||
{value !== undefined ? value : '—'}
|
{value !== undefined ? value : '—'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -160,7 +155,7 @@ export function LicensePage() {
|
|||||||
{/* License token */}
|
{/* License token */}
|
||||||
<Card title="License Token">
|
<Card title="License Token">
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<p className="text-sm text-white/60">
|
<p className={styles.description}>
|
||||||
Use this token when registering Cameleer agents with your tenant.
|
Use this token when registering Cameleer agents with your tenant.
|
||||||
</p>
|
</p>
|
||||||
<button
|
<button
|
||||||
@@ -171,8 +166,8 @@ export function LicensePage() {
|
|||||||
{tokenExpanded ? 'Hide token' : 'Show token'}
|
{tokenExpanded ? 'Hide token' : 'Show token'}
|
||||||
</button>
|
</button>
|
||||||
{tokenExpanded && (
|
{tokenExpanded && (
|
||||||
<div className="mt-2 rounded bg-white/5 border border-white/10 p-3 overflow-x-auto">
|
<div className={styles.tokenBlock}>
|
||||||
<code className="text-xs font-mono text-white/80 break-all">
|
<code className={styles.tokenCode}>
|
||||||
{license.token}
|
{license.token}
|
||||||
</code>
|
</code>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
20
ui/src/styles/platform.module.css
Normal file
20
ui/src/styles/platform.module.css
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
.heading { font-size: 1.5rem; font-weight: 600; color: var(--text-primary); }
|
||||||
|
.textPrimary { color: var(--text-primary); }
|
||||||
|
.textMuted { color: var(--text-muted); }
|
||||||
|
.mono { font-family: var(--font-mono); }
|
||||||
|
|
||||||
|
.kvRow { display: flex; align-items: center; justify-content: space-between; width: 100%; }
|
||||||
|
.kvLabel { font-size: 0.875rem; color: var(--text-muted); }
|
||||||
|
.kvValue { font-size: 0.875rem; color: var(--text-primary); }
|
||||||
|
.kvValueMono { font-size: 0.875rem; color: var(--text-primary); font-family: var(--font-mono); }
|
||||||
|
|
||||||
|
.dividerList { display: flex; flex-direction: column; }
|
||||||
|
.dividerList > * + * { border-top: 1px solid var(--border-subtle); }
|
||||||
|
.dividerRow { display: flex; align-items: center; justify-content: space-between; padding: 0.75rem 0; }
|
||||||
|
.dividerRow:first-child { padding-top: 0; }
|
||||||
|
.dividerRow:last-child { padding-bottom: 0; }
|
||||||
|
|
||||||
|
.description { font-size: 0.875rem; color: var(--text-muted); }
|
||||||
|
|
||||||
|
.tokenBlock { margin-top: 0.5rem; border-radius: var(--radius-sm); background: var(--bg-inset); border: 1px solid var(--border-subtle); padding: 0.75rem; overflow-x: auto; }
|
||||||
|
.tokenCode { font-size: 0.75rem; font-family: var(--font-mono); color: var(--text-secondary); word-break: break-all; }
|
||||||
Reference in New Issue
Block a user