refactor: rebrand project to HartOMat

This commit is contained in:
2026-04-06 12:45:47 +02:00
parent fa7093307a
commit b795f0e6d6
95 changed files with 608 additions and 497 deletions
+2 -2
View File
@@ -2,9 +2,9 @@
<html lang="en" class="" data-accent="green">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/schaeffler.svg" />
<link rel="icon" type="image/svg+xml" href="/hartomat.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Hart.O.Mat — Hartomatisierung</title>
<title>HartOMat</title>
<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" />
+2 -2
View File
@@ -1,11 +1,11 @@
{
"name": "schaefflerautomat-frontend",
"name": "hartomat-frontend",
"version": "0.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "schaefflerautomat-frontend",
"name": "hartomat-frontend",
"version": "0.1.0",
"dependencies": {
"@react-three/drei": "^9.102.3",
+1 -1
View File
@@ -1,5 +1,5 @@
{
"name": "schaefflerautomat-frontend",
"name": "hartomat-frontend",
"private": true,
"version": "0.1.0",
"type": "module",
+5
View File
@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" role="img" aria-labelledby="title">
<title>HartOMat</title>
<rect width="128" height="128" rx="28" fill="#0b3d2e"/>
<path d="M28 32h18v24h36V32h18v64H82V72H46v24H28z" fill="#f3efe2"/>
</svg>

After

Width:  |  Height:  |  Size: 259 B

+1 -1
View File
@@ -9,7 +9,7 @@ const api = axios.create({
api.interceptors.request.use((config) => {
const token = useAuthStore.getState().token
if (token) config.headers.Authorization = `Bearer ${token}`
const tenantId = localStorage.getItem('schaeffler_tenant_id')
const tenantId = localStorage.getItem('hartomat_tenant_id')
if (tenantId) config.headers['X-Tenant-ID'] = tenantId
return config
})
+5 -5
View File
@@ -5,7 +5,7 @@ export interface Material {
name: string
description: string | null
source: string
schaeffler_code: number | null
hartomat_code: number | null
created_by_name: string | null
aliases: string[]
created_at: string
@@ -27,7 +27,7 @@ export async function createMaterial(data: {
name: string
description?: string
source?: string
schaeffler_code?: number | null
hartomat_code?: number | null
}) {
const res = await api.post<Material>('/materials', data)
return res.data
@@ -54,8 +54,8 @@ export async function saveCadPartMaterials(
return res.data
}
export async function seedSchaefflerMaterials() {
const res = await api.post<{ inserted: number; total: number }>('/materials/seed-schaeffler')
export async function seedHartOMatMaterials() {
const res = await api.post<{ inserted: number; total: number }>('/materials/seed-hartomat')
return res.data
}
@@ -93,7 +93,7 @@ export async function seedAliases(): Promise<{ inserted: number; total: number }
export interface MaterialSuggestion {
id: string
name: string
schaeffler_code: string
hartomat_code: string
}
export interface UnmappedMaterial {
+5 -5
View File
@@ -98,10 +98,10 @@ export default function MaterialWizard({ open, onClose, onCreated }: Props) {
.replace(/^-|-$/g, '')
const fullMaterialName = fullCode && sanitizedName
? `SCHAEFFLER_${fullCode}_${sanitizedName}`
? `HARTOMAT_${fullCode}_${sanitizedName}`
: null
const schaefflerCodeInt = fullCode ? parseInt(fullCode, 10) : null
const hartomatCodeInt = fullCode ? parseInt(fullCode, 10) : null
const createMut = useMutation({
mutationFn: () =>
@@ -109,7 +109,7 @@ export default function MaterialWizard({ open, onClose, onCreated }: Props) {
name: fullMaterialName!,
description: description.trim() || undefined,
source: 'manual',
schaeffler_code: schaefflerCodeInt,
hartomat_code: hartomatCodeInt,
}),
onSuccess: () => {
toast.success('Material created')
@@ -133,7 +133,7 @@ export default function MaterialWizard({ open, onClose, onCreated }: Props) {
{/* Header */}
<div className="flex items-center justify-between px-6 py-4 border-b border-border-default">
<div>
<h2 className="text-lg font-semibold text-content">Schaeffler Material Wizard</h2>
<h2 className="text-lg font-semibold text-content">HartOMat Material Wizard</h2>
<p className="text-xs text-content-muted mt-0.5">Step {step} of 3</p>
</div>
<button onClick={onClose} className="text-content-muted hover:text-content-secondary">
@@ -267,7 +267,7 @@ export default function MaterialWizard({ open, onClose, onCreated }: Props) {
<p className="font-mono text-sm font-semibold text-content truncate">
{fullMaterialName || (
<span className="text-content-muted">
SCHAEFFLER_{typeCode || 'XX'}{effectiveSubType || 'YY'}{consecutive !== null ? String(consecutive).padStart(2, '0') : 'ZZ'}_{sanitizedName || 'Name'}
HARTOMAT_{typeCode || 'XX'}{effectiveSubType || 'YY'}{consecutive !== null ? String(consecutive).padStart(2, '0') : 'ZZ'}_{sanitizedName || 'Name'}
</span>
)}
</p>
@@ -47,7 +47,7 @@ export default function OutputTypeTable() {
queryKey: ['materials'],
queryFn: listMaterials,
})
const libraryMaterials = (allMaterials ?? []).filter((m: Material) => m.schaeffler_code !== null).sort((a: Material, b: Material) => a.name.localeCompare(b.name))
const libraryMaterials = (allMaterials ?? []).filter((m: Material) => m.hartomat_code !== null).sort((a: Material, b: Material) => a.name.localeCompare(b.name))
const { data: workflows } = useQuery({
queryKey: ['workflows'],
@@ -856,7 +856,7 @@ export default function OutputTypeTable() {
<td className="px-4 py-2">
{ot.material_override ? (
<span className="text-xs px-1.5 py-0.5 rounded bg-amber-50 text-amber-700 font-mono truncate block max-w-[140px]" title={ot.material_override}>
{ot.material_override.replace('SCHAEFFLER_', '').replace(/_/g, ' ')}
{ot.material_override.replace('HARTOMAT_', '').replace(/_/g, ' ')}
</span>
) : (
<span className="text-xs text-content-muted"></span>
@@ -15,7 +15,7 @@ export interface MaterialOut {
id: string
name: string
description: string | null
schaeffler_code: number | null
hartomat_code: number | null
source: string
}
+1 -1
View File
@@ -159,7 +159,7 @@ export function pbrColorHex(pbr: MaterialPBR): string {
/**
* Get a preview hex color for a material entry, using PBR data when available.
* Replaces the old hardcoded SCHAEFFLER_COLORS lookup.
* Replaces the old hardcoded HARTOMAT_COLORS lookup.
*/
export function previewColorForEntry(
entry: PartMaterialEntry,
+3 -3
View File
@@ -23,7 +23,7 @@ export default function ChatPanel({ open, onClose, contextType, contextId }: Cha
const [messages, setMessages] = useState<ChatMessage[]>([])
const [sessionId, setSessionId] = useState<string | undefined>(() => {
// Restore last session from localStorage
try { return localStorage.getItem('schaeffler-chat-session') || undefined } catch { return undefined }
try { return localStorage.getItem('hartomat-chat-session') || undefined } catch { return undefined }
})
const [input, setInput] = useState('')
const [showSessions, setShowSessions] = useState(false)
@@ -31,8 +31,8 @@ export default function ChatPanel({ open, onClose, contextType, contextId }: Cha
// Persist sessionId to localStorage
useEffect(() => {
try {
if (sessionId) localStorage.setItem('schaeffler-chat-session', sessionId)
else localStorage.removeItem('schaeffler-chat-session')
if (sessionId) localStorage.setItem('hartomat-chat-session', sessionId)
else localStorage.removeItem('hartomat-chat-session')
} catch { /* ignore */ }
}, [sessionId])
const messagesEndRef = useRef<HTMLDivElement>(null)
@@ -27,7 +27,7 @@ export default function UnmappedMaterialsDialog({ unmapped, onResolved, onCancel
})
const libraryMaterials = (allMaterials ?? []).filter(
(m: Material) => m.schaeffler_code !== null
(m: Material) => m.hartomat_code !== null
)
const allMapped = unmapped.every((u) => mappings[u.raw_name])
@@ -11,14 +11,14 @@ const TYPE_GROUPS: Record<string, { label: string; color: string }> = {
}
function getTypeCode(mat: Material): string | null {
if (mat.schaeffler_code == null) return null
const s = String(mat.schaeffler_code).padStart(6, '0')
if (mat.hartomat_code == null) return null
const s = String(mat.hartomat_code).padStart(6, '0')
return s.slice(0, 2)
}
/** Extract the human-readable short name after the last underscore: SCHAEFFLER_010101_Steel-Bare -> Steel-Bare */
/** Extract the human-readable short name after the last underscore: HARTOMAT_010101_Steel-Bare -> Steel-Bare */
function shortName(name: string): string {
const match = name.match(/^SCHAEFFLER_\d{6}_(.+)$/)
const match = name.match(/^HARTOMAT_\d{6}_(.+)$/)
return match ? match[1].replace(/-/g, ' ') : name
}
@@ -52,7 +52,7 @@ export default function MaterialInput({ value, onChange, library, missing, onOpe
buckets.get(tc)!.push(m)
}
// Sorted type codes first, then non-schaeffler
// Sorted type codes first, then non-hartomat
const sortedKeys = [...buckets.keys()].sort((a, b) => {
if (a === null) return 1
if (b === null) return -1
+2 -2
View File
@@ -50,7 +50,7 @@ export const HELP_TEXTS: Record<string, HelpText> = {
},
'action.seed_aliases': {
title: 'Seed Material Aliases',
body: 'Loads the default Schaeffler material alias mappings (Steel→SCHAEFFLER_010101_Steel-Bare, etc). Safe to run multiple times — existing aliases are not overwritten.',
body: 'Loads the default HartOMat material alias mappings (Steel→HARTOMAT_010101_Steel-Bare, etc). Safe to run multiple times — existing aliases are not overwritten.',
},
// Template fields
'template.lighting_only': {
@@ -64,7 +64,7 @@ export const HELP_TEXTS: Record<string, HelpText> = {
},
'template.material_replace_enabled': {
title: 'Material Replacement',
body: 'When enabled, Blender will replace part materials with the mapped Schaeffler library materials. When disabled, the original .blend materials are used.',
body: 'When enabled, Blender will replace part materials with the mapped HartOMat library materials. When disabled, the original .blend materials are used.',
},
// Wizard fields
'wizard.output_type': {
+1 -1
View File
@@ -7,7 +7,7 @@
Applied via data-accent="<key>" on <html>
============================================================ */
/* Default / Schaeffler Green */
/* Default / HartOMat Green */
:root,
[data-accent="green"] {
--color-accent: #00893d;
+1 -1
View File
@@ -12,7 +12,7 @@ import { useThemeStore, applyTheme, resolveTheme, type ThemeMode, type AccentKey
--------------------------------------------------------------- */
;(function () {
try {
const raw = localStorage.getItem('schaeffler-theme')
const raw = localStorage.getItem('hartomat-theme')
if (raw) {
const { state } = JSON.parse(raw) as { state: { mode: ThemeMode; accent: AccentKey; customHex?: string } }
applyTheme(state.mode ?? 'light', state.accent ?? 'green', state.customHex)
+1 -1
View File
@@ -1549,7 +1549,7 @@ export default function AdminPage() {
type="email"
value={smtp.smtp_from_address ?? ''}
onChange={(e) => setSmtpDraft(d => ({ ...d, smtp_from_address: e.target.value }))}
placeholder="noreply@schaeffler.com"
placeholder="noreply@hartomat.com"
className="w-full px-3 py-1.5 rounded-md border border-border-default text-sm bg-surface text-content focus:outline-none focus:ring-2 focus:ring-accent"
/>
</div>
+1 -1
View File
@@ -55,7 +55,7 @@ function UploadModal({ onClose }: { onClose: () => void }) {
</label>
<input
className="input-base"
placeholder="e.g. Schaeffler Materials v2"
placeholder="e.g. HartOMat Materials v2"
value={name}
onChange={(e) => setName(e.target.value)}
/>
+2 -2
View File
@@ -36,7 +36,7 @@ export default function LoginPage() {
<div className="w-16 h-16 bg-accent rounded-full flex items-center justify-center mx-auto mb-4">
<span className="text-white text-2xl font-bold">S</span>
</div>
<h1 className="text-2xl font-bold text-content">Schaeffler Automat</h1>
<h1 className="text-2xl font-bold text-content">HartOMat</h1>
<p className="text-content-muted text-sm mt-1">Media Creation Pipeline</p>
</div>
@@ -49,7 +49,7 @@ export default function LoginPage() {
onChange={(e) => setEmail(e.target.value)}
required
className="input-base w-full"
placeholder="admin@schaeffler.com"
placeholder="admin@hartomat.com"
/>
</div>
<div>
+18 -18
View File
@@ -8,7 +8,7 @@ import {
} from 'lucide-react'
import {
listMaterials, createMaterial, updateMaterial, deleteMaterial,
seedSchaefflerMaterials, addAlias, deleteAlias, seedAliases,
seedHartOMatMaterials, addAlias, deleteAlias, seedAliases,
batchCreateAliases,
} from '../api/materials'
import type { Material } from '../api/materials'
@@ -24,8 +24,8 @@ const TYPE_GROUPS = [
] as const
function getTypeCode(mat: Material): string | null {
if (mat.schaeffler_code == null) return null
return String(mat.schaeffler_code).padStart(6, '0').slice(0, 2)
if (mat.hartomat_code == null) return null
return String(mat.hartomat_code).padStart(6, '0').slice(0, 2)
}
interface MaterialGroup {
@@ -90,12 +90,12 @@ export default function MaterialsPage() {
})
const seedMut = useMutation({
mutationFn: seedSchaefflerMaterials,
mutationFn: seedHartOMatMaterials,
onSuccess: (data) => {
if (data.inserted > 0) {
toast.success(`Imported ${data.inserted} of ${data.total} Schaeffler standard materials`)
toast.success(`Imported ${data.inserted} of ${data.total} HartOMat standard materials`)
} else {
toast.info('All Schaeffler standard materials already exist')
toast.info('All HartOMat standard materials already exist')
}
qc.invalidateQueries({ queryKey: ['materials'] })
},
@@ -147,9 +147,9 @@ export default function MaterialsPage() {
onError: (e: any) => toast.error(e.response?.data?.detail || 'Failed to create alias'),
})
// Library materials (have schaeffler_code) for quick-map dropdown
// Library materials (have hartomat_code) for quick-map dropdown
const libraryMaterials = useMemo(
() => materials.filter((m) => m.schaeffler_code !== null).sort((a, b) => a.name.localeCompare(b.name)),
() => materials.filter((m) => m.hartomat_code !== null).sort((a, b) => a.name.localeCompare(b.name)),
[materials]
)
@@ -203,7 +203,7 @@ export default function MaterialsPage() {
buckets.delete(tg.code)
}
}
// Custom / non-schaeffler materials
// Custom / non-hartomat materials
const custom = buckets.get(null)
if (custom && custom.length > 0) {
result.push({ code: null, label: 'Custom', icon: Plus, bg: 'bg-surface-alt', border: 'border-border-default', text: 'text-content-secondary', items: custom })
@@ -239,7 +239,7 @@ export default function MaterialsPage() {
setConfirmState({
open: true,
title: 'Import Standard Materials',
message: 'Import 35 Schaeffler standard materials? Existing entries will be skipped.',
message: 'Import 35 HartOMat standard materials? Existing entries will be skipped.',
onConfirm: () => {
seedMut.mutate()
setConfirmState((s) => ({ ...s, open: false }))
@@ -248,7 +248,7 @@ export default function MaterialsPage() {
}}
disabled={seedMut.isPending}
className="btn-secondary text-sm flex items-center gap-1.5"
title="Import the 35 standard Schaeffler SCHAEFFLER_... materials used in Blender material libraries. Existing entries are skipped."
title="Import the 35 standard HartOMat HARTOMAT_... materials used in Blender material libraries. Existing entries are skipped."
>
<Download size={14} /> {seedMut.isPending ? 'Importing...' : 'Import Standards'}
</button>
@@ -266,16 +266,16 @@ export default function MaterialsPage() {
}}
disabled={seedAliasMut.isPending}
className="btn-secondary text-sm flex items-center gap-1.5"
title="Seed ~100 material aliases from the Schaeffler naming scheme (German descriptions, intermediate codes → SCHAEFFLER_... library names). Existing aliases are skipped."
title="Seed ~100 material aliases from the HartOMat naming scheme (German descriptions, intermediate codes → HARTOMAT_... library names). Existing aliases are skipped."
>
<Tag size={14} /> {seedAliasMut.isPending ? 'Seeding...' : 'Seed Aliases'}
</button>
<button
onClick={() => setShowWizard(true)}
className="btn-secondary text-sm flex items-center gap-1.5"
title="Open the Schaeffler Wizard — guided tool to set up SCHAEFFLER_... materials and aliases from the standard naming scheme"
title="Open the HartOMat Wizard — guided tool to set up HARTOMAT_... materials and aliases from the standard naming scheme"
>
<Wand2 size={14} /> Schaeffler Wizard
<Wand2 size={14} /> HartOMat Wizard
</button>
<button onClick={() => setShowAdd(!showAdd)} className="btn-primary">
<Plus size={16} /> Add Material
@@ -407,10 +407,10 @@ export default function MaterialsPage() {
<>
<div className="min-w-0">
<p className="text-sm font-medium text-content truncate">{mat.name}</p>
{mat.schaeffler_code != null && (
<p className="text-xs text-content-muted font-mono">Nr: {mat.schaeffler_code}</p>
{mat.hartomat_code != null && (
<p className="text-xs text-content-muted font-mono">Nr: {mat.hartomat_code}</p>
)}
{mat.schaeffler_code == null && mat.aliases.length === 0 && (
{mat.hartomat_code == null && mat.aliases.length === 0 && (
<div className="flex items-center gap-1.5 mt-1">
<span className="inline-flex items-center gap-1 text-[10px] font-medium text-amber-600 bg-amber-50 px-1.5 py-0.5 rounded">
<AlertTriangle size={10} /> No alias
@@ -614,7 +614,7 @@ function AliasPill({
}
function SourceBadge({ source }: { source: string }) {
if (source === 'schaeffler_standard') {
if (source === 'hartomat_standard') {
return (
<span className="inline-flex items-center gap-1 text-xs font-medium bg-status-success-bg text-status-success-text px-2 py-0.5 rounded-full">
Standard
+3 -3
View File
@@ -81,7 +81,7 @@ export default function NewProductOrderPage() {
queryFn: listMaterials,
enabled: step >= 3,
})
const libMaterials = (allMaterials ?? []).filter((m: Material) => m.schaeffler_code !== null).sort((a: Material, b: Material) => a.name.localeCompare(b.name))
const libMaterials = (allMaterials ?? []).filter((m: Material) => m.hartomat_code !== null).sort((a: Material, b: Material) => a.name.localeCompare(b.name))
function initPositionsForProduct(product: Product, globals: GlobalRenderPosition[] = []) {
// Pre-select all per-product positions (if any)
@@ -822,10 +822,10 @@ export default function NewProductOrderPage() {
value={lineOverrides[line.key] ?? ''}
onChange={(e) => setLineOverrides((prev) => ({ ...prev, [line.key]: e.target.value }))}
>
<option value="">{materialOverride ? `Global: ${materialOverride.replace('SCHAEFFLER_', '').replace(/_/g, ' ')}` : 'No override'}</option>
<option value="">{materialOverride ? `Global: ${materialOverride.replace('HARTOMAT_', '').replace(/_/g, ' ')}` : 'No override'}</option>
{materialOverride && <option value="__none__"> No override (clear) </option>}
{libMaterials.map((m: Material) => (
<option key={m.id} value={m.name}>{m.name.replace('SCHAEFFLER_', '').replace(/_/g, ' ')}</option>
<option key={m.id} value={m.name}>{m.name.replace('HARTOMAT_', '').replace(/_/g, ' ')}</option>
))}
</select>
</td>
+6 -6
View File
@@ -140,7 +140,7 @@ export default function OrderDetailPage() {
}
const { data: matList } = useQuery({ queryKey: ['materials'], queryFn: listMaterials })
const orderLibMats = (matList ?? []).filter((m: Material) => m.schaeffler_code !== null).sort((a: Material, b: Material) => a.name.localeCompare(b.name))
const orderLibMats = (matList ?? []).filter((m: Material) => m.hartomat_code !== null).sort((a: Material, b: Material) => a.name.localeCompare(b.name))
const batchOverrideMut = useMutation({
mutationFn: (val: string | null) => batchMaterialOverride(id!, val),
@@ -660,7 +660,7 @@ export default function OrderDetailPage() {
<option value="">Apply to all lines</option>
<option value="__clear__"> Clear all overrides </option>
{orderLibMats.map((m: Material) => (
<option key={m.id} value={m.name}>{m.name.replace('SCHAEFFLER_', '').replace(/_/g, ' ')}</option>
<option key={m.id} value={m.name}>{m.name.replace('HARTOMAT_', '').replace(/_/g, ' ')}</option>
))}
</select>
{batchOverrideMut.isPending && <Loader2 size={14} className="animate-spin text-accent" />}
@@ -1017,7 +1017,7 @@ function OrderLineRow({
})
const { data: allMats } = useQuery({ queryKey: ['materials'], queryFn: listMaterials })
const libMats = (allMats ?? []).filter((m: Material) => m.schaeffler_code !== null).sort((a: Material, b: Material) => a.name.localeCompare(b.name))
const libMats = (allMats ?? []).filter((m: Material) => m.hartomat_code !== null).sort((a: Material, b: Material) => a.name.localeCompare(b.name))
const overrideMut = useMutation({
mutationFn: (val: string | null) => patchOrderLine(orderId, line.id, { material_override: val }),
@@ -1112,7 +1112,7 @@ function OrderLineRow({
onClick={() => setShowOverride(!showOverride)}
title="Click to change material override"
>
{line.material_override.replace('SCHAEFFLER_', '').replace(/_/g, ' ')}
{line.material_override.replace('HARTOMAT_', '').replace(/_/g, ' ')}
</span>
<button
onClick={() => overrideMut.mutate(null)}
@@ -1131,7 +1131,7 @@ function OrderLineRow({
>
<option value="">No material override</option>
{libMats.map((m: Material) => (
<option key={m.id} value={m.name}>{m.name.replace('SCHAEFFLER_', '').replace(/_/g, ' ')}</option>
<option key={m.id} value={m.name}>{m.name.replace('HARTOMAT_', '').replace(/_/g, ' ')}</option>
))}
</select>
)}
@@ -1147,7 +1147,7 @@ function OrderLineRow({
>
<option value="">No material override</option>
{libMats.map((m: Material) => (
<option key={m.id} value={m.name}>{m.name.replace('SCHAEFFLER_', '').replace(/_/g, ' ')}</option>
<option key={m.id} value={m.name}>{m.name.replace('HARTOMAT_', '').replace(/_/g, ' ')}</option>
))}
</select>
) : (
+1 -1
View File
@@ -14,7 +14,7 @@ export default function PreferencesPage() {
return (
<div className="p-8 max-w-2xl">
<h1 className="text-2xl font-bold text-content mb-1">Preferences</h1>
<p className="text-sm text-content-muted mb-8">Customize your Schaeffler Automat experience.</p>
<p className="text-sm text-content-muted mb-8">Customize your HartOMat experience.</p>
{/* Appearance */}
<section className="card p-6 space-y-6">
+4 -4
View File
@@ -11,7 +11,7 @@ import {
} from '../api/tenants'
import type { Tenant, TenantCreate, TenantUpdate, TenantAIConfig, TenantAIConfigUpdate } from '../api/tenants'
const TENANT_CONTEXT_KEY = 'schaeffler_tenant_id'
const TENANT_CONTEXT_KEY = 'hartomat_tenant_id'
function slugify(name: string): string {
return name
@@ -392,7 +392,7 @@ export default function TenantsPage() {
type="text"
value={createForm.name}
onChange={(e) => handleCreateNameChange(e.target.value)}
placeholder="e.g. Schaeffler GmbH"
placeholder="e.g. HartOMat GmbH"
className="w-full px-3 py-2 rounded-md border border-border-default bg-surface text-content text-sm focus:outline-none focus:ring-2 focus:ring-accent/50"
/>
</div>
@@ -406,7 +406,7 @@ export default function TenantsPage() {
type="text"
value={createForm.slug}
onChange={(e) => handleCreateSlugChange(e.target.value)}
placeholder="e.g. schaeffler-gmbh"
placeholder="e.g. hartomat-gmbh"
className="w-full px-3 py-2 rounded-md border border-border-default bg-surface text-content text-sm font-mono focus:outline-none focus:ring-2 focus:ring-accent/50"
/>
</div>
@@ -677,7 +677,7 @@ export default function TenantsPage() {
rows={4}
value={aiForm.ai_validation_prompt ?? ''}
onChange={(e) => setAIForm((prev) => ({ ...prev, ai_validation_prompt: e.target.value || null }))}
placeholder="Optional: override the default Schaeffler bearing analysis prompt"
placeholder="Optional: override the default HartOMat bearing analysis prompt"
className="w-full px-3 py-2 rounded-md border border-border-default bg-surface text-content text-sm resize-y focus:outline-none focus:ring-2 focus:ring-accent/50"
/>
</div>
+1 -1
View File
@@ -32,6 +32,6 @@ export const useAuthStore = create<AuthState>()(
setAuth: (token, user) => set({ token, user }),
logout: () => set({ token: null, user: null }),
}),
{ name: 'schaeffler-auth' },
{ name: 'hartomat-auth' },
),
)
+2 -2
View File
@@ -5,7 +5,7 @@ export type ThemeMode = 'light' | 'dark' | 'system'
export type AccentKey = 'green' | 'blue' | 'purple' | 'amber' | 'teal' | 'custom'
export const ACCENT_PRESETS: { key: AccentKey; label: string; hex: string }[] = [
{ key: 'green', label: 'Schaeffler Green', hex: '#00893d' },
{ key: 'green', label: 'HartOMat Green', hex: '#00893d' },
{ key: 'blue', label: 'Blue', hex: '#2563eb' },
{ key: 'purple', label: 'Purple', hex: '#7c3aed' },
{ key: 'amber', label: 'Amber', hex: '#d97706' },
@@ -115,6 +115,6 @@ export const useThemeStore = create<ThemeState>()(
applyTheme(get().mode, 'custom', hex)
},
}),
{ name: 'schaeffler-theme' },
{ name: 'hartomat-theme' },
),
)