style: Dark/Light mode contrast audit
- Boost text contrast in both themes - Strengthen border visibility (subtle borders now visible) - Convert 39 files from hardcoded dark:/light: to CSS vars - Tertiary text now more readable on both backgrounds
This commit is contained in:
parent
15a6b08e0f
commit
47de301f77
39 changed files with 179 additions and 179 deletions
|
|
@ -55,8 +55,8 @@ export default function BatchTransitionModal({ batch, onClose, onSuccess }: Tran
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm animate-fade-in">
|
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm animate-fade-in">
|
||||||
<div className="bg-white dark:bg-slate-800 w-full max-w-md rounded-2xl shadow-2xl overflow-hidden animate-scale-in">
|
<div className="bg-[var(--color-bg-elevated)] w-full max-w-md rounded-2xl shadow-2xl overflow-hidden animate-scale-in">
|
||||||
<div className="p-6 border-b border-slate-200 dark:border-slate-700 flex justify-between items-center">
|
<div className="p-6 border-b border-[var(--color-border-default)] flex justify-between items-center">
|
||||||
<h2 className="text-xl font-bold dark:text-white">Transition Batch</h2>
|
<h2 className="text-xl font-bold dark:text-white">Transition Batch</h2>
|
||||||
<button onClick={onClose} className="text-[var(--color-text-tertiary)] hover:text-slate-700 dark:hover:text-slate-300">
|
<button onClick={onClose} className="text-[var(--color-text-tertiary)] hover:text-slate-700 dark:hover:text-slate-300">
|
||||||
<X size={24} />
|
<X size={24} />
|
||||||
|
|
@ -64,7 +64,7 @@ export default function BatchTransitionModal({ batch, onClose, onSuccess }: Tran
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form onSubmit={handleSubmit} className="p-6 space-y-6">
|
<form onSubmit={handleSubmit} className="p-6 space-y-6">
|
||||||
<div className="bg-[var(--color-bg-tertiary)] p-4 rounded-xl border border-slate-200 dark:border-slate-700">
|
<div className="bg-[var(--color-bg-tertiary)] p-4 rounded-xl border border-[var(--color-border-default)]">
|
||||||
<div className="flex items-center gap-3 mb-2">
|
<div className="flex items-center gap-3 mb-2">
|
||||||
<Sprout className="text-[var(--color-primary)] dark:text-emerald-400" size={20} />
|
<Sprout className="text-[var(--color-primary)] dark:text-emerald-400" size={20} />
|
||||||
<span className="font-semibold text-[var(--color-text-primary)]">{batch.name}</span>
|
<span className="font-semibold text-[var(--color-text-primary)]">{batch.name}</span>
|
||||||
|
|
@ -77,11 +77,11 @@ export default function BatchTransitionModal({ batch, onClose, onSuccess }: Tran
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">New Stage</label>
|
<label className="block text-sm font-medium text-[var(--color-text-secondary)] mb-2">New Stage</label>
|
||||||
<select
|
<select
|
||||||
value={targetStage}
|
value={targetStage}
|
||||||
onChange={(e) => setTargetStage(e.target.value as any)}
|
onChange={(e) => setTargetStage(e.target.value as any)}
|
||||||
className="w-full p-3 rounded-lg bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 dark:text-white"
|
className="w-full p-3 rounded-lg bg-[var(--color-bg-elevated)] border border-[var(--color-border-default)] dark:text-white"
|
||||||
>
|
>
|
||||||
{STAGES.map(stage => (
|
{STAGES.map(stage => (
|
||||||
<option key={stage.id} value={stage.id}>{stage.label}</option>
|
<option key={stage.id} value={stage.id}>{stage.label}</option>
|
||||||
|
|
@ -90,7 +90,7 @@ export default function BatchTransitionModal({ batch, onClose, onSuccess }: Tran
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">
|
<label className="block text-sm font-medium text-[var(--color-text-secondary)] mb-2">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Home size={16} />
|
<Home size={16} />
|
||||||
Move to Room
|
Move to Room
|
||||||
|
|
@ -99,7 +99,7 @@ export default function BatchTransitionModal({ batch, onClose, onSuccess }: Tran
|
||||||
<select
|
<select
|
||||||
value={targetRoomId}
|
value={targetRoomId}
|
||||||
onChange={(e) => setTargetRoomId(e.target.value)}
|
onChange={(e) => setTargetRoomId(e.target.value)}
|
||||||
className="w-full p-3 rounded-lg bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 dark:text-white"
|
className="w-full p-3 rounded-lg bg-[var(--color-bg-elevated)] border border-[var(--color-border-default)] dark:text-white"
|
||||||
>
|
>
|
||||||
<option value="">Keep current room ({batch.room?.name || 'Unassigned'})</option>
|
<option value="">Keep current room ({batch.room?.name || 'Unassigned'})</option>
|
||||||
{rooms.map(room => (
|
{rooms.map(room => (
|
||||||
|
|
@ -110,12 +110,12 @@ export default function BatchTransitionModal({ batch, onClose, onSuccess }: Tran
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Plant Count</label>
|
<label className="block text-sm font-medium text-[var(--color-text-secondary)] mb-2">Plant Count</label>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
value={metadata.plantCount}
|
value={metadata.plantCount}
|
||||||
onChange={(e) => setMetadata({ ...metadata, plantCount: parseInt(e.target.value) || 0 })}
|
onChange={(e) => setMetadata({ ...metadata, plantCount: parseInt(e.target.value) || 0 })}
|
||||||
className="w-full p-3 rounded-lg bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 dark:text-white"
|
className="w-full p-3 rounded-lg bg-[var(--color-bg-elevated)] border border-[var(--color-border-default)] dark:text-white"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ export class ErrorBoundary extends Component<Props, State> {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-[var(--color-bg-tertiary)] flex items-center justify-center p-6">
|
<div className="min-h-screen bg-[var(--color-bg-tertiary)] flex items-center justify-center p-6">
|
||||||
<div className="max-w-md w-full bg-white dark:bg-slate-800 rounded-2xl shadow-xl p-8 text-center">
|
<div className="max-w-md w-full bg-[var(--color-bg-elevated)] rounded-2xl shadow-xl p-8 text-center">
|
||||||
<div className="w-16 h-16 mx-auto bg-red-100 dark:bg-red-900/30 rounded-full flex items-center justify-center mb-6">
|
<div className="w-16 h-16 mx-auto bg-red-100 dark:bg-red-900/30 rounded-full flex items-center justify-center mb-6">
|
||||||
<AlertTriangle size={32} className="text-red-600 dark:text-red-400" />
|
<AlertTriangle size={32} className="text-red-600 dark:text-red-400" />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -68,7 +68,7 @@ export class ErrorBoundary extends Component<Props, State> {
|
||||||
<summary className="cursor-pointer text-sm text-[var(--color-text-tertiary)] hover:text-slate-700 dark:hover:text-slate-300">
|
<summary className="cursor-pointer text-sm text-[var(--color-text-tertiary)] hover:text-slate-700 dark:hover:text-slate-300">
|
||||||
Technical Details
|
Technical Details
|
||||||
</summary>
|
</summary>
|
||||||
<pre className="mt-2 p-3 bg-slate-100 dark:bg-slate-700 rounded-lg text-xs text-red-600 dark:text-red-400 overflow-auto max-h-32">
|
<pre className="mt-2 p-3 bg-[var(--color-bg-tertiary)] rounded-lg text-xs text-red-600 dark:text-red-400 overflow-auto max-h-32">
|
||||||
{this.state.error.toString()}
|
{this.state.error.toString()}
|
||||||
{this.state.errorInfo?.componentStack}
|
{this.state.errorInfo?.componentStack}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
@ -85,7 +85,7 @@ export class ErrorBoundary extends Component<Props, State> {
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={this.handleGoHome}
|
onClick={this.handleGoHome}
|
||||||
className="flex-1 flex items-center justify-center gap-2 px-4 py-3 bg-slate-200 dark:bg-slate-700 hover:bg-slate-300 dark:hover:bg-slate-600 text-slate-700 dark:text-slate-200 font-medium rounded-xl transition-colors"
|
className="flex-1 flex items-center justify-center gap-2 px-4 py-3 bg-slate-200 dark:bg-slate-700 hover:bg-slate-300 dark:hover:bg-slate-600 text-[var(--color-text-secondary)]late-200 font-medium rounded-xl transition-colors"
|
||||||
>
|
>
|
||||||
<Home size={18} />
|
<Home size={18} />
|
||||||
Go Home
|
Go Home
|
||||||
|
|
|
||||||
|
|
@ -50,8 +50,8 @@ export default function TaskTemplateModal({ template, onClose, onSuccess }: Task
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm animate-fade-in">
|
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm animate-fade-in">
|
||||||
<div className="bg-white dark:bg-slate-800 w-full max-w-lg rounded-2xl shadow-2xl overflow-hidden animate-scale-in flex flex-col max-h-[90vh]">
|
<div className="bg-[var(--color-bg-elevated)] w-full max-w-lg rounded-2xl shadow-2xl overflow-hidden animate-scale-in flex flex-col max-h-[90vh]">
|
||||||
<div className="p-6 border-b border-slate-200 dark:border-slate-700 flex justify-between items-center">
|
<div className="p-6 border-b border-[var(--color-border-default)] flex justify-between items-center">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<FileText className="text-[var(--color-primary)] dark:text-emerald-400" size={24} />
|
<FileText className="text-[var(--color-primary)] dark:text-emerald-400" size={24} />
|
||||||
<h2 className="text-xl font-bold dark:text-white">
|
<h2 className="text-xl font-bold dark:text-white">
|
||||||
|
|
@ -65,12 +65,12 @@ export default function TaskTemplateModal({ template, onClose, onSuccess }: Task
|
||||||
|
|
||||||
<form onSubmit={handleSubmit} className="p-6 space-y-6 overflow-y-auto flex-1">
|
<form onSubmit={handleSubmit} className="p-6 space-y-6 overflow-y-auto flex-1">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Title</label>
|
<label className="block text-sm font-medium text-[var(--color-text-secondary)] mb-2">Title</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.title}
|
value={formData.title}
|
||||||
onChange={(e) => setFormData({ ...formData, title: e.target.value })}
|
onChange={(e) => setFormData({ ...formData, title: e.target.value })}
|
||||||
className="w-full p-3 rounded-lg bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 dark:text-white"
|
className="w-full p-3 rounded-lg bg-[var(--color-bg-elevated)] border border-[var(--color-border-default)] dark:text-white"
|
||||||
placeholder="e.g. Daily Veg Watering"
|
placeholder="e.g. Daily Veg Watering"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
|
|
@ -78,11 +78,11 @@ export default function TaskTemplateModal({ template, onClose, onSuccess }: Task
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Room Type</label>
|
<label className="block text-sm font-medium text-[var(--color-text-secondary)] mb-2">Room Type</label>
|
||||||
<select
|
<select
|
||||||
value={formData.roomType}
|
value={formData.roomType}
|
||||||
onChange={(e) => setFormData({ ...formData, roomType: e.target.value })}
|
onChange={(e) => setFormData({ ...formData, roomType: e.target.value })}
|
||||||
className="w-full p-3 rounded-lg bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 dark:text-white"
|
className="w-full p-3 rounded-lg bg-[var(--color-bg-elevated)] border border-[var(--color-border-default)] dark:text-white"
|
||||||
>
|
>
|
||||||
{ROOM_TYPES.map(type => (
|
{ROOM_TYPES.map(type => (
|
||||||
<option key={type} value={type}>{type}</option>
|
<option key={type} value={type}>{type}</option>
|
||||||
|
|
@ -90,39 +90,39 @@ export default function TaskTemplateModal({ template, onClose, onSuccess }: Task
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Est. Minutes</label>
|
<label className="block text-sm font-medium text-[var(--color-text-secondary)] mb-2">Est. Minutes</label>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
value={formData.estimatedMinutes}
|
value={formData.estimatedMinutes}
|
||||||
onChange={(e) => setFormData({ ...formData, estimatedMinutes: parseInt(e.target.value) || 0 })}
|
onChange={(e) => setFormData({ ...formData, estimatedMinutes: parseInt(e.target.value) || 0 })}
|
||||||
className="w-full p-3 rounded-lg bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 dark:text-white"
|
className="w-full p-3 rounded-lg bg-[var(--color-bg-elevated)] border border-[var(--color-border-default)] dark:text-white"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Description / Instructions</label>
|
<label className="block text-sm font-medium text-[var(--color-text-secondary)] mb-2">Description / Instructions</label>
|
||||||
<textarea
|
<textarea
|
||||||
value={formData.description}
|
value={formData.description}
|
||||||
onChange={(e) => setFormData({ ...formData, description: e.target.value })}
|
onChange={(e) => setFormData({ ...formData, description: e.target.value })}
|
||||||
className="w-full p-3 rounded-lg bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 dark:text-white h-32 resize-none"
|
className="w-full p-3 rounded-lg bg-[var(--color-bg-elevated)] border border-[var(--color-border-default)] dark:text-white h-32 resize-none"
|
||||||
placeholder="Detailed SOP instructions..."
|
placeholder="Detailed SOP instructions..."
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Materials (comma separated)</label>
|
<label className="block text-sm font-medium text-[var(--color-text-secondary)] mb-2">Materials (comma separated)</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={materialsInput}
|
value={materialsInput}
|
||||||
onChange={(e) => setMaterialsInput(e.target.value)}
|
onChange={(e) => setMaterialsInput(e.target.value)}
|
||||||
className="w-full p-3 rounded-lg bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 dark:text-white"
|
className="w-full p-3 rounded-lg bg-[var(--color-bg-elevated)] border border-[var(--color-border-default)] dark:text-white"
|
||||||
placeholder="e.g. 5gal buckets, bamboo stakes, twist ties"
|
placeholder="e.g. 5gal buckets, bamboo stakes, twist ties"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div className="p-6 border-t border-slate-200 dark:border-slate-700 bg-[var(--color-bg-tertiary)]/50">
|
<div className="p-6 border-t border-[var(--color-border-default)] bg-[var(--color-bg-tertiary)]/50">
|
||||||
<button
|
<button
|
||||||
onClick={handleSubmit}
|
onClick={handleSubmit}
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,8 @@ export default function WeightLogModal({ batch, onClose, onSuccess }: WeightLogM
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm animate-fade-in">
|
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm animate-fade-in">
|
||||||
<div className="bg-white dark:bg-slate-800 w-full max-w-md rounded-2xl shadow-2xl overflow-hidden animate-scale-in">
|
<div className="bg-[var(--color-bg-elevated)] w-full max-w-md rounded-2xl shadow-2xl overflow-hidden animate-scale-in">
|
||||||
<div className="p-6 border-b border-slate-200 dark:border-slate-700 flex justify-between items-center">
|
<div className="p-6 border-b border-[var(--color-border-default)] flex justify-between items-center">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Scale className="text-[var(--color-primary)] dark:text-emerald-400" size={24} />
|
<Scale className="text-[var(--color-primary)] dark:text-emerald-400" size={24} />
|
||||||
<h2 className="text-xl font-bold dark:text-white">Log Weight</h2>
|
<h2 className="text-xl font-bold dark:text-white">Log Weight</h2>
|
||||||
|
|
@ -57,17 +57,17 @@ export default function WeightLogModal({ batch, onClose, onSuccess }: WeightLogM
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form onSubmit={handleSubmit} className="p-6 space-y-6">
|
<form onSubmit={handleSubmit} className="p-6 space-y-6">
|
||||||
<div className="bg-[var(--color-bg-tertiary)] p-4 rounded-xl border border-slate-200 dark:border-slate-700">
|
<div className="bg-[var(--color-bg-tertiary)] p-4 rounded-xl border border-[var(--color-border-default)]">
|
||||||
<h3 className="font-semibold text-[var(--color-text-primary)]">{batch.name}</h3>
|
<h3 className="font-semibold text-[var(--color-text-primary)]">{batch.name}</h3>
|
||||||
<p className="text-sm text-[var(--color-text-tertiary)]">{batch.strain}</p>
|
<p className="text-sm text-[var(--color-text-tertiary)]">{batch.strain}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Weight Type</label>
|
<label className="block text-sm font-medium text-[var(--color-text-secondary)] mb-2">Weight Type</label>
|
||||||
<select
|
<select
|
||||||
value={weightType}
|
value={weightType}
|
||||||
onChange={(e) => setWeightType(e.target.value)}
|
onChange={(e) => setWeightType(e.target.value)}
|
||||||
className="w-full p-3 rounded-lg bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 dark:text-white"
|
className="w-full p-3 rounded-lg bg-[var(--color-bg-elevated)] border border-[var(--color-border-default)] dark:text-white"
|
||||||
>
|
>
|
||||||
{WEIGHT_TYPES.map(type => (
|
{WEIGHT_TYPES.map(type => (
|
||||||
<option key={type.id} value={type.id}>{type.label}</option>
|
<option key={type.id} value={type.id}>{type.label}</option>
|
||||||
|
|
@ -77,23 +77,23 @@ export default function WeightLogModal({ batch, onClose, onSuccess }: WeightLogM
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Weight</label>
|
<label className="block text-sm font-medium text-[var(--color-text-secondary)] mb-2">Weight</label>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
step="0.01"
|
step="0.01"
|
||||||
value={weight}
|
value={weight}
|
||||||
onChange={(e) => setWeight(e.target.value)}
|
onChange={(e) => setWeight(e.target.value)}
|
||||||
className="w-full p-3 rounded-lg bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 dark:text-white"
|
className="w-full p-3 rounded-lg bg-[var(--color-bg-elevated)] border border-[var(--color-border-default)] dark:text-white"
|
||||||
placeholder="0.00"
|
placeholder="0.00"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Unit</label>
|
<label className="block text-sm font-medium text-[var(--color-text-secondary)] mb-2">Unit</label>
|
||||||
<select
|
<select
|
||||||
value={unit}
|
value={unit}
|
||||||
onChange={(e) => setUnit(e.target.value)}
|
onChange={(e) => setUnit(e.target.value)}
|
||||||
className="w-full p-3 rounded-lg bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 dark:text-white"
|
className="w-full p-3 rounded-lg bg-[var(--color-bg-elevated)] border border-[var(--color-border-default)] dark:text-white"
|
||||||
>
|
>
|
||||||
<option value="lbs">lbs</option>
|
<option value="lbs">lbs</option>
|
||||||
<option value="g">grams</option>
|
<option value="g">grams</option>
|
||||||
|
|
@ -104,11 +104,11 @@ export default function WeightLogModal({ batch, onClose, onSuccess }: WeightLogM
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Notes</label>
|
<label className="block text-sm font-medium text-[var(--color-text-secondary)] mb-2">Notes</label>
|
||||||
<textarea
|
<textarea
|
||||||
value={notes}
|
value={notes}
|
||||||
onChange={(e) => setNotes(e.target.value)}
|
onChange={(e) => setNotes(e.target.value)}
|
||||||
className="w-full p-3 rounded-lg bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 dark:text-white h-24 resize-none"
|
className="w-full p-3 rounded-lg bg-[var(--color-bg-elevated)] border border-[var(--color-border-default)] dark:text-white h-24 resize-none"
|
||||||
placeholder="Optional notes..."
|
placeholder="Optional notes..."
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ export function Navbar({ onOpenMobileMenu }: NavbarProps) {
|
||||||
{/* Search Mock */}
|
{/* Search Mock */}
|
||||||
<button
|
<button
|
||||||
onClick={() => dispatchEvent(new KeyboardEvent('keydown', { key: 'k', metaKey: true }))}
|
onClick={() => dispatchEvent(new KeyboardEvent('keydown', { key: 'k', metaKey: true }))}
|
||||||
className="hidden md:flex items-center gap-3 px-4 py-2 text-xs font-bold text-[var(--color-text-tertiary)] bg-slate-100/50 hover:bg-white dark:bg-slate-900/50 dark:hover:bg-slate-800 transition-all rounded-full border border-slate-200/50 dark:border-slate-800 group"
|
className="hidden md:flex items-center gap-3 px-4 py-2 text-xs font-bold text-[var(--color-text-tertiary)] bg-slate-100/50 hover:bg-[var(--color-bg-elevated)]/50 dark:hover:bg-slate-800 transition-all rounded-full border border-slate-200/50 dark:border-slate-800 group"
|
||||||
>
|
>
|
||||||
<Search size={12} className="group-hover:text-indigo-500 transition-colors" />
|
<Search size={12} className="group-hover:text-indigo-500 transition-colors" />
|
||||||
<span className="uppercase tracking-widest">Search...</span>
|
<span className="uppercase tracking-widest">Search...</span>
|
||||||
|
|
@ -152,7 +152,7 @@ function UserDropdown() {
|
||||||
transition={{ duration: 0.1 }}
|
transition={{ duration: 0.1 }}
|
||||||
className="absolute top-full right-0 mt-3 w-64 p-3 bg-white/95 dark:bg-slate-900/95 backdrop-blur-2xl border border-[var(--color-border-subtle)] rounded-2xl shadow-2xl z-50 ring-1 ring-black/5"
|
className="absolute top-full right-0 mt-3 w-64 p-3 bg-white/95 dark:bg-slate-900/95 backdrop-blur-2xl border border-[var(--color-border-subtle)] rounded-2xl shadow-2xl z-50 ring-1 ring-black/5"
|
||||||
>
|
>
|
||||||
<div className="px-3 py-3 border-b border-slate-100 dark:border-slate-800 mb-2">
|
<div className="px-3 py-3 border-b border-[var(--color-border-subtle)] mb-2">
|
||||||
<p className="text-xs font-bold text-[var(--color-text-tertiary)] uppercase tracking-widest mb-1">Authenticated</p>
|
<p className="text-xs font-bold text-[var(--color-text-tertiary)] uppercase tracking-widest mb-1">Authenticated</p>
|
||||||
<p className="text-sm font-bold text-[var(--color-text-primary)] truncate">
|
<p className="text-sm font-bold text-[var(--color-text-primary)] truncate">
|
||||||
{user?.name || 'Administrator'}
|
{user?.name || 'Administrator'}
|
||||||
|
|
|
||||||
|
|
@ -94,16 +94,16 @@ export function RoomStatusCard({ name, phase, status, metrics, tasks, strains }:
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Footer / Tasks */}
|
{/* Footer / Tasks */}
|
||||||
<div className="pt-4 border-t border-slate-100 dark:border-slate-800/50 flex items-center justify-between">
|
<div className="pt-4 border-t border-[var(--color-border-subtle)]/50 flex items-center justify-between">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<div className="flex items-center gap-1.5 text-xs text-[var(--color-text-tertiary)]">
|
<div className="flex items-center gap-1.5 text-xs text-[var(--color-text-tertiary)]">
|
||||||
<Clock size={12} />
|
<Clock size={12} />
|
||||||
<span className="font-bold text-slate-700 dark:text-slate-300">{tasks.due}</span>
|
<span className="font-bold text-[var(--color-text-secondary)]">{tasks.due}</span>
|
||||||
<span>Pending</span>
|
<span>Pending</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-1.5 text-xs text-[var(--color-text-tertiary)]">
|
<div className="flex items-center gap-1.5 text-xs text-[var(--color-text-tertiary)]">
|
||||||
<CheckCircle2 size={12} className="text-[var(--color-primary)]" />
|
<CheckCircle2 size={12} className="text-[var(--color-primary)]" />
|
||||||
<span className="font-bold text-slate-700 dark:text-slate-300">{tasks.completed}</span>
|
<span className="font-bold text-[var(--color-text-secondary)]">{tasks.completed}</span>
|
||||||
<span>Done</span>
|
<span>Done</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -126,7 +126,7 @@ export function RoomStatusCard({ name, phase, status, metrics, tasks, strains }:
|
||||||
|
|
||||||
function MetricItem({ icon, label, value, status }: { icon: React.ReactNode, label: string, value: string, status: 'ok' | 'warning' | 'critical' }) {
|
function MetricItem({ icon, label, value, status }: { icon: React.ReactNode, label: string, value: string, status: 'ok' | 'warning' | 'critical' }) {
|
||||||
return (
|
return (
|
||||||
<div className="bg-[var(--color-bg-tertiary)]/50 p-2.5 rounded-xl border border-slate-100 dark:border-slate-800/50">
|
<div className="bg-[var(--color-bg-tertiary)]/50 p-2.5 rounded-xl border border-[var(--color-border-subtle)]/50">
|
||||||
<div className="flex items-center gap-1.5 mb-1">
|
<div className="flex items-center gap-1.5 mb-1">
|
||||||
{icon}
|
{icon}
|
||||||
<span className="text-[10px] font-bold text-[var(--color-text-tertiary)] uppercase tracking-widest">{label}</span>
|
<span className="text-[10px] font-bold text-[var(--color-text-tertiary)] uppercase tracking-widest">{label}</span>
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ export function DevTools() {
|
||||||
|
|
||||||
{/* Panel */}
|
{/* Panel */}
|
||||||
{isOpen && (
|
{isOpen && (
|
||||||
<div className="absolute bottom-14 right-0 w-72 bg-white dark:bg-slate-800 rounded-xl shadow-2xl border border-slate-200 dark:border-slate-700 overflow-hidden animate-scale-in">
|
<div className="absolute bottom-14 right-0 w-72 bg-[var(--color-bg-elevated)] rounded-xl shadow-2xl border border-[var(--color-border-default)] overflow-hidden animate-scale-in">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="bg-[var(--color-warning)] text-white px-4 py-3 flex items-center justify-between">
|
<div className="bg-[var(--color-warning)] text-white px-4 py-3 flex items-center justify-between">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
|
|
@ -113,7 +113,7 @@ export function DevTools() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Current User */}
|
{/* Current User */}
|
||||||
<div className="px-4 py-3 border-b border-slate-200 dark:border-slate-700">
|
<div className="px-4 py-3 border-b border-[var(--color-border-default)]">
|
||||||
<p className="text-[10px] uppercase text-[var(--color-text-tertiary)] font-semibold mb-1">Current User</p>
|
<p className="text-[10px] uppercase text-[var(--color-text-tertiary)] font-semibold mb-1">Current User</p>
|
||||||
{user ? (
|
{user ? (
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
|
|
@ -169,7 +169,7 @@ export function DevTools() {
|
||||||
|
|
||||||
{/* Demo Actions */}
|
{/* Demo Actions */}
|
||||||
{user && ['OWNER', 'ADMIN'].includes(user.role) && (
|
{user && ['OWNER', 'ADMIN'].includes(user.role) && (
|
||||||
<div className="px-4 py-3 border-t border-slate-200 dark:border-slate-700">
|
<div className="px-4 py-3 border-t border-[var(--color-border-default)]">
|
||||||
<p className="text-[10px] uppercase text-[var(--color-text-tertiary)] font-semibold mb-2">Demo Actions</p>
|
<p className="text-[10px] uppercase text-[var(--color-text-tertiary)] font-semibold mb-2">Demo Actions</p>
|
||||||
<button
|
<button
|
||||||
onClick={handleReseedPlants}
|
onClick={handleReseedPlants}
|
||||||
|
|
@ -199,7 +199,7 @@ export function DevTools() {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Footer */}
|
{/* Footer */}
|
||||||
<div className="px-4 py-2 bg-[var(--color-bg-tertiary)] border-t border-slate-200 dark:border-slate-700">
|
<div className="px-4 py-2 bg-[var(--color-bg-tertiary)] border-t border-[var(--color-border-default)]">
|
||||||
<p className="text-[10px] text-[var(--color-text-tertiary)] text-center">
|
<p className="text-[10px] text-[var(--color-text-tertiary)] text-center">
|
||||||
🚧 Testing Environment Only
|
🚧 Testing Environment Only
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ export default function BedTooltip({ bed, position, onClose }: BedTooltipProps)
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={tooltipRef}
|
ref={tooltipRef}
|
||||||
className="fixed z-50 bg-white dark:bg-slate-800 rounded-lg shadow-2xl border border-slate-200 dark:border-slate-700 p-4 min-w-[280px]"
|
className="fixed z-50 bg-[var(--color-bg-elevated)] rounded-lg shadow-2xl border border-[var(--color-border-default)] p-4 min-w-[280px]"
|
||||||
style={{
|
style={{
|
||||||
left: position.x + 10,
|
left: position.x + 10,
|
||||||
top: position.y + 10,
|
top: position.y + 10,
|
||||||
|
|
@ -134,7 +134,7 @@ export default function BedTooltip({ bed, position, onClose }: BedTooltipProps)
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Actions */}
|
{/* Actions */}
|
||||||
<div className="mt-3 pt-3 border-t border-slate-200 dark:border-slate-700">
|
<div className="mt-3 pt-3 border-t border-[var(--color-border-default)]">
|
||||||
<button className="text-sm text-[var(--color-primary)] dark:text-emerald-400 hover:underline">
|
<button className="text-sm text-[var(--color-primary)] dark:text-emerald-400 hover:underline">
|
||||||
View Details →
|
View Details →
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@ export default function GrowRoomHeatmap({ roomId }: GrowRoomHeatmapProps) {
|
||||||
<HealthLegend />
|
<HealthLegend />
|
||||||
|
|
||||||
{/* Grid */}
|
{/* Grid */}
|
||||||
<div className="bg-white dark:bg-slate-800 rounded-xl shadow-lg p-6">
|
<div className="bg-[var(--color-bg-elevated)] rounded-xl shadow-lg p-6">
|
||||||
<FloorGrid
|
<FloorGrid
|
||||||
floor={currentFloor}
|
floor={currentFloor}
|
||||||
rows={layout.grid.rows}
|
rows={layout.grid.rows}
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@ export default function HealthLegend() {
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-white dark:bg-slate-800 rounded-lg shadow p-4">
|
<div className="bg-[var(--color-bg-elevated)] rounded-lg shadow p-4">
|
||||||
<h3 className="text-sm font-semibold text-slate-700 dark:text-slate-300 mb-3">
|
<h3 className="text-sm font-semibold text-[var(--color-text-secondary)] mb-3">
|
||||||
Health Score Legend
|
Health Score Legend
|
||||||
</h3>
|
</h3>
|
||||||
<div className="flex flex-wrap gap-3">
|
<div className="flex flex-wrap gap-3">
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,8 @@ export default function BatchHealthHistoryModal({ batch, onClose }: BatchHealthH
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm animate-fade-in">
|
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm animate-fade-in">
|
||||||
<div className="bg-white dark:bg-slate-900 w-full max-w-2xl rounded-2xl shadow-2xl overflow-hidden animate-scale-in flex flex-col max-h-[90vh]">
|
<div className="bg-[var(--color-bg-elevated)] w-full max-w-2xl rounded-2xl shadow-2xl overflow-hidden animate-scale-in flex flex-col max-h-[90vh]">
|
||||||
<div className="p-6 border-b border-slate-200 dark:border-slate-700 flex justify-between items-center shrink-0">
|
<div className="p-6 border-b border-[var(--color-border-default)] flex justify-between items-center shrink-0">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<History className="text-[var(--color-text-tertiary)]" size={24} />
|
<History className="text-[var(--color-text-tertiary)]" size={24} />
|
||||||
<h2 className="text-xl font-bold dark:text-white">Batch Health History</h2>
|
<h2 className="text-xl font-bold dark:text-white">Batch Health History</h2>
|
||||||
|
|
@ -48,7 +48,7 @@ export default function BatchHealthHistoryModal({ batch, onClose }: BatchHealthH
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="p-4 bg-slate-50 dark:bg-slate-800 border-b border-slate-200 dark:border-slate-700 shrink-0">
|
<div className="p-4 bg-[var(--color-bg-tertiary)] border-b border-[var(--color-border-default)] shrink-0">
|
||||||
<h3 className="font-bold text-[var(--color-text-primary)]">{batch.name}</h3>
|
<h3 className="font-bold text-[var(--color-text-primary)]">{batch.name}</h3>
|
||||||
<p className="text-sm text-[var(--color-text-tertiary)]">{batch.strain} • {batch.room?.name || 'No Room'}</p>
|
<p className="text-sm text-[var(--color-text-tertiary)]">{batch.strain} • {batch.room?.name || 'No Room'}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -59,14 +59,14 @@ export default function BatchHealthHistoryModal({ batch, onClose }: BatchHealthH
|
||||||
) : history.length === 0 ? (
|
) : history.length === 0 ? (
|
||||||
<div className="text-center text-[var(--color-text-tertiary)] py-10 italic">No health or maintenance records found.</div>
|
<div className="text-center text-[var(--color-text-tertiary)] py-10 italic">No health or maintenance records found.</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="relative border-l-2 border-slate-200 dark:border-slate-700 ml-4 space-y-8">
|
<div className="relative border-l-2 border-[var(--color-border-default)] ml-4 space-y-8">
|
||||||
{history.map((record) => (
|
{history.map((record) => (
|
||||||
<div key={record.id} className="relative pl-8">
|
<div key={record.id} className="relative pl-8">
|
||||||
<div className={`absolute -left-[9px] top-0 w-4 h-4 rounded-full border-2 border-white dark:border-slate-900 ${record.issuesObserved ? 'bg-red-500' :
|
<div className={`absolute -left-[9px] top-0 w-4 h-4 rounded-full border-2 border-white dark:border-slate-900 ${record.issuesObserved ? 'bg-red-500' :
|
||||||
record.type === 'IPM' ? 'bg-orange-400' : 'bg-slate-300 dark:bg-slate-600'
|
record.type === 'IPM' ? 'bg-orange-400' : 'bg-slate-300 dark:bg-slate-600'
|
||||||
}`} />
|
}`} />
|
||||||
|
|
||||||
<div className="bg-white dark:bg-slate-800 p-4 rounded-xl border border-slate-100 dark:border-slate-700 shadow-sm">
|
<div className="bg-[var(--color-bg-elevated)] p-4 rounded-xl border border-slate-100 dark:border-slate-700 shadow-sm">
|
||||||
<div className="flex justify-between items-start mb-2">
|
<div className="flex justify-between items-start mb-2">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
{getIcon(record.type, record.issuesObserved)}
|
{getIcon(record.type, record.issuesObserved)}
|
||||||
|
|
@ -98,7 +98,7 @@ export default function BatchHealthHistoryModal({ batch, onClose }: BatchHealthH
|
||||||
ISSUE DETECTED
|
ISSUE DETECTED
|
||||||
</span>
|
</span>
|
||||||
{record.issueType && (
|
{record.issueType && (
|
||||||
<span className="text-xs bg-slate-100 dark:bg-slate-700 text-slate-600 dark:text-slate-300 px-2 py-1 rounded">
|
<span className="text-xs bg-[var(--color-bg-tertiary)] text-slate-600 dark:text-slate-300 px-2 py-1 rounded">
|
||||||
{record.issueType}
|
{record.issueType}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ export function MobileNav({ onMoreClick }: MobileNavProps) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav
|
<nav
|
||||||
className="md:hidden fixed bottom-0 left-0 right-0 bg-white dark:bg-slate-800 border-t border-slate-200 dark:border-slate-700 z-50"
|
className="md:hidden fixed bottom-0 left-0 right-0 bg-[var(--color-bg-elevated)] border-t border-[var(--color-border-default)] z-50"
|
||||||
style={{ paddingBottom: 'env(safe-area-inset-bottom)' }}
|
style={{ paddingBottom: 'env(safe-area-inset-bottom)' }}
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-around px-2 py-1">
|
<div className="flex items-center justify-around px-2 py-1">
|
||||||
|
|
|
||||||
|
|
@ -94,8 +94,8 @@ export function PageHeaderButton({
|
||||||
}) {
|
}) {
|
||||||
const variants = {
|
const variants = {
|
||||||
primary: 'bg-[var(--color-primary)] hover:bg-[var(--color-primary-hover)] text-white shadow-sm',
|
primary: 'bg-[var(--color-primary)] hover:bg-[var(--color-primary-hover)] text-white shadow-sm',
|
||||||
secondary: 'bg-slate-100 dark:bg-slate-700 hover:bg-slate-200 dark:hover:bg-slate-600 text-[var(--color-text-primary)]',
|
secondary: 'bg-[var(--color-bg-tertiary)] hover:bg-slate-200 dark:hover:bg-slate-600 text-[var(--color-text-primary)]',
|
||||||
ghost: 'hover:bg-slate-100 dark:hover:bg-slate-700 text-slate-700 dark:text-slate-300'
|
ghost: 'hover:bg-slate-100 dark:hover:bg-slate-700 text-[var(--color-text-secondary)]'
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ interface ShiftNotesWidgetProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
const IMPORTANCE_CONFIG: Record<string, { color: string; bgColor: string; label: string }> = {
|
const IMPORTANCE_CONFIG: Record<string, { color: string; bgColor: string; label: string }> = {
|
||||||
LOW: { color: 'text-[var(--color-text-tertiary)]', bgColor: 'bg-slate-100 dark:bg-slate-700', label: 'Low' },
|
LOW: { color: 'text-[var(--color-text-tertiary)]', bgColor: 'bg-[var(--color-bg-tertiary)]', label: 'Low' },
|
||||||
NORMAL: { color: 'text-[var(--color-accent)]', bgColor: 'bg-blue-50 dark:bg-blue-900/30', label: 'Normal' },
|
NORMAL: { color: 'text-[var(--color-accent)]', bgColor: 'bg-blue-50 dark:bg-blue-900/30', label: 'Normal' },
|
||||||
HIGH: { color: 'text-[var(--color-warning)]', bgColor: 'bg-amber-50 dark:bg-amber-900/30', label: 'High' },
|
HIGH: { color: 'text-[var(--color-warning)]', bgColor: 'bg-amber-50 dark:bg-amber-900/30', label: 'High' },
|
||||||
URGENT: { color: 'text-red-500', bgColor: 'bg-red-50 dark:bg-red-900/30', label: 'Urgent' }
|
URGENT: { color: 'text-red-500', bgColor: 'bg-red-50 dark:bg-red-900/30', label: 'Urgent' }
|
||||||
|
|
@ -100,10 +100,10 @@ export default function ShiftNotesWidget({
|
||||||
const urgentNotes = notes.filter(n => n.importance === 'URGENT' || n.importance === 'HIGH');
|
const urgentNotes = notes.filter(n => n.importance === 'URGENT' || n.importance === 'HIGH');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-700 overflow-hidden ${className}`}>
|
<div className={`bg-[var(--color-bg-elevated)] rounded-xl border border-[var(--color-border-default)] overflow-hidden ${className}`}>
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div
|
<div
|
||||||
className="p-4 border-b border-slate-200 dark:border-slate-700 flex items-center justify-between cursor-pointer"
|
className="p-4 border-b border-[var(--color-border-default)] flex items-center justify-between cursor-pointer"
|
||||||
onClick={() => compact && setExpanded(!expanded)}
|
onClick={() => compact && setExpanded(!expanded)}
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
|
|
@ -143,14 +143,14 @@ export default function ShiftNotesWidget({
|
||||||
|
|
||||||
{/* Create Form */}
|
{/* Create Form */}
|
||||||
{showCreate && expanded && (
|
{showCreate && expanded && (
|
||||||
<form onSubmit={handleSubmit} className="p-4 bg-[var(--color-bg-tertiary)]/50 border-b border-slate-200 dark:border-slate-700">
|
<form onSubmit={handleSubmit} className="p-4 bg-[var(--color-bg-tertiary)]/50 border-b border-[var(--color-border-default)]">
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<textarea
|
<textarea
|
||||||
value={newNote.content}
|
value={newNote.content}
|
||||||
onChange={(e) => setNewNote({ ...newNote, content: e.target.value })}
|
onChange={(e) => setNewNote({ ...newNote, content: e.target.value })}
|
||||||
placeholder="Add a note for the next shift..."
|
placeholder="Add a note for the next shift..."
|
||||||
rows={3}
|
rows={3}
|
||||||
className="w-full px-3 py-2 rounded-lg border border-slate-200 dark:border-slate-600 bg-white dark:bg-slate-800 text-sm resize-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent"
|
className="w-full px-3 py-2 rounded-lg border border-slate-200 dark:border-slate-600 bg-[var(--color-bg-elevated)] text-sm resize-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent"
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
|
|
@ -223,7 +223,7 @@ export default function ShiftNotesWidget({
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0">
|
||||||
<p className="text-sm text-slate-700 dark:text-slate-200 whitespace-pre-wrap">
|
<p className="text-sm text-[var(--color-text-secondary)]late-200 whitespace-pre-wrap">
|
||||||
{note.content}
|
{note.content}
|
||||||
</p>
|
</p>
|
||||||
<div className="flex items-center gap-3 mt-2 text-xs text-[var(--color-text-tertiary)]">
|
<div className="flex items-center gap-3 mt-2 text-xs text-[var(--color-text-tertiary)]">
|
||||||
|
|
@ -259,7 +259,7 @@ export default function ShiftNotesWidget({
|
||||||
|
|
||||||
{/* View All Link */}
|
{/* View All Link */}
|
||||||
{expanded && notes.length > 0 && (
|
{expanded && notes.length > 0 && (
|
||||||
<div className="p-3 border-t border-slate-200 dark:border-slate-700 text-center">
|
<div className="p-3 border-t border-[var(--color-border-default)] text-center">
|
||||||
<button className="text-sm text-indigo-600 hover:text-indigo-700 font-medium">
|
<button className="text-sm text-indigo-600 hover:text-indigo-700 font-medium">
|
||||||
View All Notes
|
View All Notes
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,8 @@ export default function CompleteTaskModal({ task, onClose, onSuccess }: Complete
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm animate-fade-in">
|
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm animate-fade-in">
|
||||||
<div className="bg-white dark:bg-slate-900 w-full max-w-md rounded-2xl shadow-2xl overflow-hidden animate-scale-in">
|
<div className="bg-[var(--color-bg-elevated)] w-full max-w-md rounded-2xl shadow-2xl overflow-hidden animate-scale-in">
|
||||||
<div className="p-6 border-b border-slate-200 dark:border-slate-700 flex justify-between items-center">
|
<div className="p-6 border-b border-[var(--color-border-default)] flex justify-between items-center">
|
||||||
<h2 className="text-xl font-bold dark:text-white flex items-center gap-2">
|
<h2 className="text-xl font-bold dark:text-white flex items-center gap-2">
|
||||||
<CheckCircle className="text-[var(--color-primary)]" />
|
<CheckCircle className="text-[var(--color-primary)]" />
|
||||||
Complete Task
|
Complete Task
|
||||||
|
|
@ -40,7 +40,7 @@ export default function CompleteTaskModal({ task, onClose, onSuccess }: Complete
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form onSubmit={handleSubmit} className="p-6 space-y-4">
|
<form onSubmit={handleSubmit} className="p-6 space-y-4">
|
||||||
<div className="bg-slate-50 dark:bg-slate-800 p-4 rounded-xl border border-slate-200 dark:border-slate-700">
|
<div className="bg-[var(--color-bg-tertiary)] p-4 rounded-xl border border-[var(--color-border-default)]">
|
||||||
<h3 className="font-bold text-[var(--color-text-primary)]">{task.title}</h3>
|
<h3 className="font-bold text-[var(--color-text-primary)]">{task.title}</h3>
|
||||||
{task.description && (
|
{task.description && (
|
||||||
<p className="text-sm text-[var(--color-text-tertiary)] mt-1">{task.description}</p>
|
<p className="text-sm text-[var(--color-text-tertiary)] mt-1">{task.description}</p>
|
||||||
|
|
@ -48,13 +48,13 @@ export default function CompleteTaskModal({ task, onClose, onSuccess }: Complete
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">
|
<label className="block text-sm font-medium text-[var(--color-text-secondary)] mb-2">
|
||||||
Completion Notes (Optional)
|
Completion Notes (Optional)
|
||||||
</label>
|
</label>
|
||||||
<textarea
|
<textarea
|
||||||
value={notes}
|
value={notes}
|
||||||
onChange={(e) => setNotes(e.target.value)}
|
onChange={(e) => setNotes(e.target.value)}
|
||||||
className="w-full p-3 rounded-lg bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 dark:text-white h-32 resize-none"
|
className="w-full p-3 rounded-lg bg-[var(--color-bg-elevated)] border border-[var(--color-border-default)] dark:text-white h-32 resize-none"
|
||||||
placeholder="e.g. Used 50gal instead of 40gal..."
|
placeholder="e.g. Used 50gal instead of 40gal..."
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -115,9 +115,9 @@ export default function CreateTaskModal({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm animate-in fade-in duration-200">
|
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm animate-in fade-in duration-200">
|
||||||
<div className="bg-white dark:bg-slate-900 w-full max-w-lg rounded-2xl shadow-xl overflow-hidden flex flex-col max-h-[90vh]">
|
<div className="bg-[var(--color-bg-elevated)] w-full max-w-lg rounded-2xl shadow-xl overflow-hidden flex flex-col max-h-[90vh]">
|
||||||
|
|
||||||
<div className="p-4 border-b border-slate-100 dark:border-slate-800 flex justify-between items-center">
|
<div className="p-4 border-b border-[var(--color-border-subtle)] flex justify-between items-center">
|
||||||
<h2 className="text-xl font-bold text-[var(--color-text-primary)]">New Task</h2>
|
<h2 className="text-xl font-bold text-[var(--color-text-primary)]">New Task</h2>
|
||||||
<button onClick={onClose} className="p-2 hover:bg-slate-100 dark:hover:bg-slate-800 rounded-full">
|
<button onClick={onClose} className="p-2 hover:bg-slate-100 dark:hover:bg-slate-800 rounded-full">
|
||||||
<X size={20} className="text-[var(--color-text-tertiary)]" />
|
<X size={20} className="text-[var(--color-text-tertiary)]" />
|
||||||
|
|
@ -127,14 +127,14 @@ export default function CreateTaskModal({
|
||||||
<form onSubmit={handleSubmit} className="flex-1 overflow-y-auto p-4 space-y-4">
|
<form onSubmit={handleSubmit} className="flex-1 overflow-y-auto p-4 space-y-4">
|
||||||
|
|
||||||
{/* Template Selection */}
|
{/* Template Selection */}
|
||||||
<div className="bg-slate-50 dark:bg-slate-800/50 p-3 rounded-xl border border-dashed border-slate-300 dark:border-slate-700">
|
<div className="bg-[var(--color-bg-tertiary)]/50 p-3 rounded-xl border border-dashed border-slate-300 dark:border-slate-700">
|
||||||
<label className="block text-xs font-bold text-[var(--color-text-tertiary)] uppercase tracking-wider mb-2 flex items-center gap-2">
|
<label className="block text-xs font-bold text-[var(--color-text-tertiary)] uppercase tracking-wider mb-2 flex items-center gap-2">
|
||||||
<FileText size={14} /> Quick Fill from Template
|
<FileText size={14} /> Quick Fill from Template
|
||||||
</label>
|
</label>
|
||||||
<select
|
<select
|
||||||
value={selectedTemplateId}
|
value={selectedTemplateId}
|
||||||
onChange={(e) => handleTemplateChange(e.target.value)}
|
onChange={(e) => handleTemplateChange(e.target.value)}
|
||||||
className="w-full p-2 bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg text-sm text-[var(--color-text-primary)]"
|
className="w-full p-2 bg-[var(--color-bg-elevated)] border border-[var(--color-border-default)] rounded-lg text-sm text-[var(--color-text-primary)]"
|
||||||
>
|
>
|
||||||
<option value="">-- Start Blank --</option>
|
<option value="">-- Start Blank --</option>
|
||||||
{templates.map(t => (
|
{templates.map(t => (
|
||||||
|
|
@ -144,23 +144,23 @@ export default function CreateTaskModal({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-bold text-slate-700 dark:text-slate-300 mb-1">Task Title *</label>
|
<label className="block text-sm font-bold text-[var(--color-text-secondary)] mb-1">Task Title *</label>
|
||||||
<input
|
<input
|
||||||
required
|
required
|
||||||
value={title}
|
value={title}
|
||||||
onChange={e => setTitle(e.target.value)}
|
onChange={e => setTitle(e.target.value)}
|
||||||
placeholder="e.g. Water Room A"
|
placeholder="e.g. Water Room A"
|
||||||
className="w-full p-3 bg-slate-50 dark:bg-slate-800 border-none rounded-xl text-[var(--color-text-primary)] focus:ring-2 focus:ring-emerald-500"
|
className="w-full p-3 bg-[var(--color-bg-tertiary)] border-none rounded-xl text-[var(--color-text-primary)] focus:ring-2 focus:ring-emerald-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Priority</label>
|
<label className="block text-sm font-medium text-[var(--color-text-secondary)] mb-1">Priority</label>
|
||||||
<select
|
<select
|
||||||
value={priority}
|
value={priority}
|
||||||
onChange={e => setPriority(e.target.value)}
|
onChange={e => setPriority(e.target.value)}
|
||||||
className="w-full p-3 bg-slate-50 dark:bg-slate-800 border-none rounded-xl text-[var(--color-text-primary)]"
|
className="w-full p-3 bg-[var(--color-bg-tertiary)] border-none rounded-xl text-[var(--color-text-primary)]"
|
||||||
>
|
>
|
||||||
<option value="LOW">Low</option>
|
<option value="LOW">Low</option>
|
||||||
<option value="MEDIUM">Medium</option>
|
<option value="MEDIUM">Medium</option>
|
||||||
|
|
@ -169,25 +169,25 @@ export default function CreateTaskModal({
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Due Date</label>
|
<label className="block text-sm font-medium text-[var(--color-text-secondary)] mb-1">Due Date</label>
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
required
|
required
|
||||||
value={dueDate}
|
value={dueDate}
|
||||||
onChange={e => setDueDate(e.target.value)}
|
onChange={e => setDueDate(e.target.value)}
|
||||||
className="w-full p-3 bg-slate-50 dark:bg-slate-800 border-none rounded-xl text-[var(--color-text-primary)]"
|
className="w-full p-3 bg-[var(--color-bg-tertiary)] border-none rounded-xl text-[var(--color-text-primary)]"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1 flex items-center gap-2">
|
<label className="block text-sm font-medium text-[var(--color-text-secondary)] mb-1 flex items-center gap-2">
|
||||||
<User size={16} /> Assign To
|
<User size={16} /> Assign To
|
||||||
</label>
|
</label>
|
||||||
<select
|
<select
|
||||||
value={assigneeId}
|
value={assigneeId}
|
||||||
onChange={e => setAssigneeId(e.target.value)}
|
onChange={e => setAssigneeId(e.target.value)}
|
||||||
className="w-full p-3 bg-slate-50 dark:bg-slate-800 border-none rounded-xl text-[var(--color-text-primary)]"
|
className="w-full p-3 bg-[var(--color-bg-tertiary)] border-none rounded-xl text-[var(--color-text-primary)]"
|
||||||
>
|
>
|
||||||
<option value="">-- Unassigned --</option>
|
<option value="">-- Unassigned --</option>
|
||||||
{users.map(u => (
|
{users.map(u => (
|
||||||
|
|
@ -198,13 +198,13 @@ export default function CreateTaskModal({
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1 flex items-center gap-2">
|
<label className="block text-sm font-medium text-[var(--color-text-secondary)] mb-1 flex items-center gap-2">
|
||||||
<MapPin size={16} /> Room (Optional)
|
<MapPin size={16} /> Room (Optional)
|
||||||
</label>
|
</label>
|
||||||
<select
|
<select
|
||||||
value={roomId}
|
value={roomId}
|
||||||
onChange={e => setRoomId(e.target.value)}
|
onChange={e => setRoomId(e.target.value)}
|
||||||
className="w-full p-3 bg-slate-50 dark:bg-slate-800 border-none rounded-xl text-[var(--color-text-primary)]"
|
className="w-full p-3 bg-[var(--color-bg-tertiary)] border-none rounded-xl text-[var(--color-text-primary)]"
|
||||||
>
|
>
|
||||||
<option value="">-- None --</option>
|
<option value="">-- None --</option>
|
||||||
{rooms.map(r => (
|
{rooms.map(r => (
|
||||||
|
|
@ -213,13 +213,13 @@ export default function CreateTaskModal({
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1 flex items-center gap-2">
|
<label className="block text-sm font-medium text-[var(--color-text-secondary)] mb-1 flex items-center gap-2">
|
||||||
<Box size={16} /> Batch (Optional)
|
<Box size={16} /> Batch (Optional)
|
||||||
</label>
|
</label>
|
||||||
<select
|
<select
|
||||||
value={batchId}
|
value={batchId}
|
||||||
onChange={e => setBatchId(e.target.value)}
|
onChange={e => setBatchId(e.target.value)}
|
||||||
className="w-full p-3 bg-slate-50 dark:bg-slate-800 border-none rounded-xl text-[var(--color-text-primary)]"
|
className="w-full p-3 bg-[var(--color-bg-tertiary)] border-none rounded-xl text-[var(--color-text-primary)]"
|
||||||
>
|
>
|
||||||
<option value="">-- None --</option>
|
<option value="">-- None --</option>
|
||||||
{batches.map(b => (
|
{batches.map(b => (
|
||||||
|
|
@ -230,13 +230,13 @@ export default function CreateTaskModal({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Description / Notes</label>
|
<label className="block text-sm font-medium text-[var(--color-text-secondary)] mb-1">Description / Notes</label>
|
||||||
<textarea
|
<textarea
|
||||||
value={description}
|
value={description}
|
||||||
onChange={e => setDescription(e.target.value)}
|
onChange={e => setDescription(e.target.value)}
|
||||||
rows={3}
|
rows={3}
|
||||||
placeholder="Details about the task..."
|
placeholder="Details about the task..."
|
||||||
className="w-full p-3 bg-slate-50 dark:bg-slate-800 border-none rounded-xl text-[var(--color-text-primary)] resize-none"
|
className="w-full p-3 bg-[var(--color-bg-tertiary)] border-none rounded-xl text-[var(--color-text-primary)] resize-none"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ export default function TasksDueTodayWidget({ userId }: TasksDueTodayWidgetProps
|
||||||
if (tasks.length === 0) return null;
|
if (tasks.length === 0) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-white dark:bg-slate-800 rounded-2xl shadow-sm border border-slate-200 dark:border-slate-700 p-6">
|
<div className="bg-[var(--color-bg-elevated)] rounded-2xl shadow-sm border border-[var(--color-border-default)] p-6">
|
||||||
<div className="flex justify-between items-center mb-4">
|
<div className="flex justify-between items-center mb-4">
|
||||||
<h3 className="text-lg font-bold text-[var(--color-text-primary)] flex items-center gap-2">
|
<h3 className="text-lg font-bold text-[var(--color-text-primary)] flex items-center gap-2">
|
||||||
<List className="text-[var(--color-primary)]" />
|
<List className="text-[var(--color-primary)]" />
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ export function QuickLogBar({ batchId, batchName, onSuccess, compact = false }:
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-1 bg-slate-100 dark:bg-slate-700 rounded-lg p-1">
|
<div className="flex items-center gap-1 bg-[var(--color-bg-tertiary)] rounded-lg p-1">
|
||||||
{QUICK_ACTIONS.map(action => {
|
{QUICK_ACTIONS.map(action => {
|
||||||
const Icon = action.icon;
|
const Icon = action.icon;
|
||||||
const isLoading = loading === action.type;
|
const isLoading = loading === action.type;
|
||||||
|
|
|
||||||
|
|
@ -70,10 +70,10 @@ export default function TouchPointModal({ isOpen, onClose, preselectedBatchId, o
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm animate-in fade-in duration-200">
|
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm animate-in fade-in duration-200">
|
||||||
<div className="bg-white dark:bg-slate-900 w-full max-w-md rounded-2xl shadow-xl overflow-hidden flex flex-col max-h-[90vh]">
|
<div className="bg-[var(--color-bg-elevated)] w-full max-w-md rounded-2xl shadow-xl overflow-hidden flex flex-col max-h-[90vh]">
|
||||||
|
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="p-4 border-b border-slate-100 dark:border-slate-800 flex justify-between items-center">
|
<div className="p-4 border-b border-[var(--color-border-subtle)] flex justify-between items-center">
|
||||||
<h2 className="text-xl font-bold text-[var(--color-text-primary)]">Log Plant Touch</h2>
|
<h2 className="text-xl font-bold text-[var(--color-text-primary)]">Log Plant Touch</h2>
|
||||||
<button onClick={onClose} className="p-2 hover:bg-slate-100 dark:hover:bg-slate-800 rounded-full">
|
<button onClick={onClose} className="p-2 hover:bg-slate-100 dark:hover:bg-slate-800 rounded-full">
|
||||||
<X size={20} className="text-[var(--color-text-tertiary)]" />
|
<X size={20} className="text-[var(--color-text-tertiary)]" />
|
||||||
|
|
@ -86,13 +86,13 @@ export default function TouchPointModal({ isOpen, onClose, preselectedBatchId, o
|
||||||
{/* Batch Selection (if not preselected) */}
|
{/* Batch Selection (if not preselected) */}
|
||||||
{!preselectedBatchId && (
|
{!preselectedBatchId && (
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">
|
<label className="block text-sm font-medium text-[var(--color-text-secondary)] mb-2">
|
||||||
Select Batch
|
Select Batch
|
||||||
</label>
|
</label>
|
||||||
<select
|
<select
|
||||||
value={selectedBatchId}
|
value={selectedBatchId}
|
||||||
onChange={(e) => setSelectedBatchId(e.target.value)}
|
onChange={(e) => setSelectedBatchId(e.target.value)}
|
||||||
className="w-full p-3 bg-slate-50 dark:bg-slate-800 border-none rounded-xl text-[var(--color-text-primary)] focus:ring-2 focus:ring-emerald-500"
|
className="w-full p-3 bg-[var(--color-bg-tertiary)] border-none rounded-xl text-[var(--color-text-primary)] focus:ring-2 focus:ring-emerald-500"
|
||||||
>
|
>
|
||||||
<option value="">-- Select Batch --</option>
|
<option value="">-- Select Batch --</option>
|
||||||
{batches.map(b => (
|
{batches.map(b => (
|
||||||
|
|
@ -104,7 +104,7 @@ export default function TouchPointModal({ isOpen, onClose, preselectedBatchId, o
|
||||||
|
|
||||||
{/* Touch Type Grid */}
|
{/* Touch Type Grid */}
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">
|
<label className="block text-sm font-medium text-[var(--color-text-secondary)] mb-2">
|
||||||
Action Type
|
Action Type
|
||||||
</label>
|
</label>
|
||||||
<div className="grid grid-cols-3 gap-3">
|
<div className="grid grid-cols-3 gap-3">
|
||||||
|
|
@ -113,8 +113,8 @@ export default function TouchPointModal({ isOpen, onClose, preselectedBatchId, o
|
||||||
key={type}
|
key={type}
|
||||||
onClick={() => setSelectedType(type)}
|
onClick={() => setSelectedType(type)}
|
||||||
className={`flex flex-col items-center justify-center p-3 rounded-xl gap-2 transition-all ${selectedType === type
|
className={`flex flex-col items-center justify-center p-3 rounded-xl gap-2 transition-all ${selectedType === type
|
||||||
? 'ring-2 ring-emerald-500 ring-offset-2 dark:ring-offset-slate-900 bg-slate-50 dark:bg-slate-800'
|
? 'ring-2 ring-emerald-500 ring-offset-2 ring-offset-[var(--color-bg-primary)] bg-[var(--color-bg-tertiary)]'
|
||||||
: 'hover:bg-slate-50 dark:hover:bg-slate-800 border border-slate-100 dark:border-slate-800'
|
: 'hover:bg-[var(--color-bg-tertiary)] border border-[var(--color-border-subtle)]'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div className={`p-2 rounded-full ${color}`}>
|
<div className={`p-2 rounded-full ${color}`}>
|
||||||
|
|
@ -128,19 +128,19 @@ export default function TouchPointModal({ isOpen, onClose, preselectedBatchId, o
|
||||||
|
|
||||||
{/* Notes */}
|
{/* Notes */}
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">
|
<label className="block text-sm font-medium text-[var(--color-text-secondary)] mb-2">
|
||||||
Notes
|
Notes
|
||||||
</label>
|
</label>
|
||||||
<textarea
|
<textarea
|
||||||
value={notes}
|
value={notes}
|
||||||
onChange={(e) => setNotes(e.target.value)}
|
onChange={(e) => setNotes(e.target.value)}
|
||||||
placeholder="Details about the action..."
|
placeholder="Details about the action..."
|
||||||
className="w-full p-3 bg-slate-50 dark:bg-slate-800 border-none rounded-xl text-[var(--color-text-primary)] focus:ring-2 focus:ring-emerald-500 min-h-[100px] resize-none"
|
className="w-full p-3 bg-[var(--color-bg-tertiary)] border-none rounded-xl text-[var(--color-text-primary)] focus:ring-2 focus:ring-emerald-500 min-h-[100px] resize-none"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Photo Placeholder */}
|
{/* Photo Placeholder */}
|
||||||
<button className="w-full p-4 border-2 border-dashed border-slate-200 dark:border-slate-700 rounded-xl text-[var(--color-text-tertiary)] hover:bg-slate-50 dark:hover:bg-slate-800 flex items-center justify-center gap-2">
|
<button className="w-full p-4 border-2 border-dashed border-[var(--color-border-default)] rounded-xl text-[var(--color-text-tertiary)] hover:bg-[var(--color-bg-tertiary)] flex items-center justify-center gap-2">
|
||||||
<Camera size={20} />
|
<Camera size={20} />
|
||||||
<span>Add Photo (Optional)</span>
|
<span>Add Photo (Optional)</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -148,7 +148,7 @@ export default function TouchPointModal({ isOpen, onClose, preselectedBatchId, o
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Footer */}
|
{/* Footer */}
|
||||||
<div className="p-4 border-t border-slate-100 dark:border-slate-800">
|
<div className="p-4 border-t border-[var(--color-border-subtle)]">
|
||||||
<button
|
<button
|
||||||
onClick={handleSubmit}
|
onClick={handleSubmit}
|
||||||
disabled={!selectedBatchId || !selectedType || isLoading}
|
disabled={!selectedBatchId || !selectedType || isLoading}
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ export function BottomSheet({ isOpen, onClose, title, children, height = 'auto'
|
||||||
{/* Sheet */}
|
{/* Sheet */}
|
||||||
<div
|
<div
|
||||||
ref={sheetRef}
|
ref={sheetRef}
|
||||||
className={`absolute bottom-0 left-0 right-0 bg-white dark:bg-slate-800 rounded-t-2xl shadow-xl transition-transform duration-200 ${heightClasses[height]} ${isClosing ? 'translate-y-full' : 'translate-y-0'}`}
|
className={`absolute bottom-0 left-0 right-0 bg-[var(--color-bg-elevated)] rounded-t-2xl shadow-xl transition-transform duration-200 ${heightClasses[height]} ${isClosing ? 'translate-y-full' : 'translate-y-0'}`}
|
||||||
style={{ transform: isClosing ? 'translateY(100%)' : `translateY(${dragOffset}px)` }}
|
style={{ transform: isClosing ? 'translateY(100%)' : `translateY(${dragOffset}px)` }}
|
||||||
>
|
>
|
||||||
{/* Drag Handle */}
|
{/* Drag Handle */}
|
||||||
|
|
@ -91,7 +91,7 @@ export function BottomSheet({ isOpen, onClose, title, children, height = 'auto'
|
||||||
|
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
{title && (
|
{title && (
|
||||||
<div className="flex items-center justify-between px-4 pb-4 border-b border-slate-200 dark:border-slate-700">
|
<div className="flex items-center justify-between px-4 pb-4 border-b border-[var(--color-border-default)]">
|
||||||
<h3 className="text-lg font-bold text-[var(--color-text-primary)]">{title}</h3>
|
<h3 className="text-lg font-bold text-[var(--color-text-primary)]">{title}</h3>
|
||||||
<button
|
<button
|
||||||
onClick={handleClose}
|
onClick={handleClose}
|
||||||
|
|
@ -128,9 +128,9 @@ export function ResponsiveModal({ isOpen, onClose, title, children, className =
|
||||||
{/* Desktop Modal */}
|
{/* Desktop Modal */}
|
||||||
<div className="hidden md:flex fixed inset-0 z-[100] items-center justify-center p-4">
|
<div className="hidden md:flex fixed inset-0 z-[100] items-center justify-center p-4">
|
||||||
<div className="absolute inset-0 bg-black/50 backdrop-blur-sm" onClick={onClose} />
|
<div className="absolute inset-0 bg-black/50 backdrop-blur-sm" onClick={onClose} />
|
||||||
<div className={`relative bg-white dark:bg-slate-800 rounded-2xl shadow-2xl max-w-lg w-full max-h-[85vh] overflow-hidden animate-scale-in ${className}`}>
|
<div className={`relative bg-[var(--color-bg-elevated)] rounded-2xl shadow-2xl max-w-lg w-full max-h-[85vh] overflow-hidden animate-scale-in ${className}`}>
|
||||||
{title && (
|
{title && (
|
||||||
<div className="flex items-center justify-between p-4 border-b border-slate-200 dark:border-slate-700">
|
<div className="flex items-center justify-between p-4 border-b border-[var(--color-border-default)]">
|
||||||
<h3 className="text-lg font-bold text-[var(--color-text-primary)]">{title}</h3>
|
<h3 className="text-lg font-bold text-[var(--color-text-primary)]">{title}</h3>
|
||||||
<button
|
<button
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
|
|
|
||||||
|
|
@ -101,8 +101,8 @@ export function CommandPalette() {
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 z-[100] flex items-start justify-center pt-[15vh] p-4">
|
<div className="fixed inset-0 z-[100] flex items-start justify-center pt-[15vh] p-4">
|
||||||
<div className="absolute inset-0 bg-black/50 backdrop-blur-sm" onClick={() => setIsOpen(false)} />
|
<div className="absolute inset-0 bg-black/50 backdrop-blur-sm" onClick={() => setIsOpen(false)} />
|
||||||
<div className="relative w-full max-w-lg bg-white dark:bg-slate-800 rounded-2xl shadow-2xl overflow-hidden animate-scale-in">
|
<div className="relative w-full max-w-lg bg-[var(--color-bg-elevated)] rounded-2xl shadow-2xl overflow-hidden animate-scale-in">
|
||||||
<div className="flex items-center gap-3 p-4 border-b border-slate-200 dark:border-slate-700">
|
<div className="flex items-center gap-3 p-4 border-b border-[var(--color-border-default)]">
|
||||||
<Search size={20} className="text-[var(--color-text-tertiary)]" />
|
<Search size={20} className="text-[var(--color-text-tertiary)]" />
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
|
|
@ -112,7 +112,7 @@ export function CommandPalette() {
|
||||||
className="flex-1 bg-transparent text-[var(--color-text-primary)] placeholder-slate-400 outline-none text-lg"
|
className="flex-1 bg-transparent text-[var(--color-text-primary)] placeholder-slate-400 outline-none text-lg"
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
<kbd className="hidden sm:inline-flex px-2 py-1 text-xs font-mono bg-slate-100 dark:bg-slate-700 text-[var(--color-text-tertiary)] rounded">ESC</kbd>
|
<kbd className="hidden sm:inline-flex px-2 py-1 text-xs font-mono bg-[var(--color-bg-tertiary)] text-[var(--color-text-tertiary)] rounded">ESC</kbd>
|
||||||
</div>
|
</div>
|
||||||
<div className="max-h-80 overflow-y-auto p-2">
|
<div className="max-h-80 overflow-y-auto p-2">
|
||||||
{filteredCommands.length === 0 ? (
|
{filteredCommands.length === 0 ? (
|
||||||
|
|
@ -130,7 +130,7 @@ export function CommandPalette() {
|
||||||
<button
|
<button
|
||||||
key={cmd.id}
|
key={cmd.id}
|
||||||
onClick={() => { cmd.action(); setIsOpen(false); }}
|
onClick={() => { cmd.action(); setIsOpen(false); }}
|
||||||
className={`w-full flex items-center gap-3 px-3 py-2 rounded-lg text-left transition-colors ${isSelected ? 'bg-emerald-50 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300' : 'text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-700'}`}
|
className={`w-full flex items-center gap-3 px-3 py-2 rounded-lg text-left transition-colors ${isSelected ? 'bg-emerald-50 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300' : 'text-[var(--color-text-secondary)] hover:bg-slate-100 dark:hover:bg-slate-700'}`}
|
||||||
>
|
>
|
||||||
<Icon size={18} />
|
<Icon size={18} />
|
||||||
<span>{cmd.label}</span>
|
<span>{cmd.label}</span>
|
||||||
|
|
@ -150,7 +150,7 @@ export function CommandPalette() {
|
||||||
<button
|
<button
|
||||||
key={cmd.id}
|
key={cmd.id}
|
||||||
onClick={() => { cmd.action(); setIsOpen(false); }}
|
onClick={() => { cmd.action(); setIsOpen(false); }}
|
||||||
className={`w-full flex items-center gap-3 px-3 py-2 rounded-lg text-left transition-colors ${isSelected ? 'bg-emerald-50 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300' : 'text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-700'}`}
|
className={`w-full flex items-center gap-3 px-3 py-2 rounded-lg text-left transition-colors ${isSelected ? 'bg-emerald-50 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300' : 'text-[var(--color-text-secondary)] hover:bg-slate-100 dark:hover:bg-slate-700'}`}
|
||||||
>
|
>
|
||||||
<Icon size={18} />
|
<Icon size={18} />
|
||||||
<span>{cmd.label}</span>
|
<span>{cmd.label}</span>
|
||||||
|
|
@ -170,7 +170,7 @@ export function CommandPalette() {
|
||||||
<button
|
<button
|
||||||
key={cmd.id}
|
key={cmd.id}
|
||||||
onClick={() => { cmd.action(); setIsOpen(false); }}
|
onClick={() => { cmd.action(); setIsOpen(false); }}
|
||||||
className={`w-full flex items-center gap-3 px-3 py-2 rounded-lg text-left transition-colors ${isSelected ? 'bg-red-50 dark:bg-red-900/30 text-red-700 dark:text-red-300' : 'text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-700'}`}
|
className={`w-full flex items-center gap-3 px-3 py-2 rounded-lg text-left transition-colors ${isSelected ? 'bg-red-50 dark:bg-red-900/30 text-red-700 dark:text-red-300' : 'text-[var(--color-text-secondary)] hover:bg-slate-100 dark:hover:bg-slate-700'}`}
|
||||||
>
|
>
|
||||||
<Icon size={18} />
|
<Icon size={18} />
|
||||||
<span>{cmd.label}</span>
|
<span>{cmd.label}</span>
|
||||||
|
|
@ -182,15 +182,15 @@ export function CommandPalette() {
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="border-t border-slate-200 dark:border-slate-700 p-3 flex items-center justify-between text-xs text-[var(--color-text-tertiary)]">
|
<div className="border-t border-[var(--color-border-default)] p-3 flex items-center justify-between text-xs text-[var(--color-text-tertiary)]">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<span className="flex items-center gap-1">
|
<span className="flex items-center gap-1">
|
||||||
<kbd className="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-700 rounded">↑</kbd>
|
<kbd className="px-1.5 py-0.5 bg-[var(--color-bg-tertiary)] rounded">↑</kbd>
|
||||||
<kbd className="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-700 rounded">↓</kbd>
|
<kbd className="px-1.5 py-0.5 bg-[var(--color-bg-tertiary)] rounded">↓</kbd>
|
||||||
to navigate
|
to navigate
|
||||||
</span>
|
</span>
|
||||||
<span className="flex items-center gap-1">
|
<span className="flex items-center gap-1">
|
||||||
<kbd className="px-1.5 py-0.5 bg-slate-100 dark:bg-slate-700 rounded">↵</kbd>
|
<kbd className="px-1.5 py-0.5 bg-[var(--color-bg-tertiary)] rounded">↵</kbd>
|
||||||
to select
|
to select
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ export function DataTable<T extends { id: string | number }>({
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{Array.from({ length: 5 }).map((_, i) => (
|
{Array.from({ length: 5 }).map((_, i) => (
|
||||||
<div key={i} className="px-4 py-4 border-b border-slate-100 dark:border-slate-800/50 flex items-center gap-4">
|
<div key={i} className="px-4 py-4 border-b border-[var(--color-border-subtle)]/50 flex items-center gap-4">
|
||||||
<div className="h-4 w-1/4 bg-slate-100 dark:bg-slate-800 rounded animate-pulse" />
|
<div className="h-4 w-1/4 bg-slate-100 dark:bg-slate-800 rounded animate-pulse" />
|
||||||
<div className="h-4 w-1/4 bg-slate-100 dark:bg-slate-800 rounded animate-pulse" />
|
<div className="h-4 w-1/4 bg-slate-100 dark:bg-slate-800 rounded animate-pulse" />
|
||||||
<div className="h-4 w-1/4 bg-slate-100 dark:bg-slate-800 rounded animate-pulse" />
|
<div className="h-4 w-1/4 bg-slate-100 dark:bg-slate-800 rounded animate-pulse" />
|
||||||
|
|
@ -107,7 +107,7 @@ export function DataTable<T extends { id: string | number }>({
|
||||||
<td
|
<td
|
||||||
key={String(col.key) + idx}
|
key={String(col.key) + idx}
|
||||||
className={cn(
|
className={cn(
|
||||||
"px-4 py-3 align-middle text-slate-700 dark:text-slate-300",
|
"px-4 py-3 align-middle text-[var(--color-text-secondary)]",
|
||||||
col.hideOnMobile && "hidden md:table-cell",
|
col.hideOnMobile && "hidden md:table-cell",
|
||||||
col.className
|
col.className
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ export function SectionHeader({ icon: Icon, title, count, accent = 'default' }:
|
||||||
{title}
|
{title}
|
||||||
</h3>
|
</h3>
|
||||||
{count !== undefined && (
|
{count !== undefined && (
|
||||||
<span className="px-1.5 py-0.5 rounded-full bg-slate-100 dark:bg-slate-800 text-[10px] font-bold text-[var(--color-text-tertiary)] border border-slate-200 dark:border-slate-700/50">
|
<span className="px-1.5 py-0.5 rounded-full bg-slate-100 dark:bg-slate-800 text-[10px] font-bold text-[var(--color-text-tertiary)] border border-[var(--color-border-default)]/50">
|
||||||
{count}
|
{count}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
|
@ -85,7 +85,7 @@ interface EmptyStateProps {
|
||||||
export function EmptyState({ icon: Icon, title, description, action }: EmptyStateProps) {
|
export function EmptyState({ icon: Icon, title, description, action }: EmptyStateProps) {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-center justify-center py-20 px-4 text-center border-2 border-dashed border-[var(--color-border-subtle)] rounded-2xl bg-slate-50/30 dark:bg-slate-900/10">
|
<div className="flex flex-col items-center justify-center py-20 px-4 text-center border-2 border-dashed border-[var(--color-border-subtle)] rounded-2xl bg-slate-50/30 dark:bg-slate-900/10">
|
||||||
<div className="w-16 h-16 bg-white dark:bg-slate-900 rounded-2xl flex items-center justify-center shadow-xl mb-6 ring-1 ring-slate-200 dark:ring-slate-800">
|
<div className="w-16 h-16 bg-[var(--color-bg-elevated)] rounded-2xl flex items-center justify-center shadow-xl mb-6 ring-1 ring-slate-200 dark:ring-slate-800">
|
||||||
<Icon size={32} className="text-slate-300 dark:text-slate-700" />
|
<Icon size={32} className="text-slate-300 dark:text-slate-700" />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-base font-bold text-[var(--color-text-primary)]">{title}</h3>
|
<h3 className="text-base font-bold text-[var(--color-text-primary)]">{title}</h3>
|
||||||
|
|
@ -139,7 +139,7 @@ export function MetricCard({ icon: Icon, label, value, subtitle, accent = 'defau
|
||||||
<p className="text-[11px] font-bold text-[var(--color-text-tertiary)] uppercase tracking-widest">{label}</p>
|
<p className="text-[11px] font-bold text-[var(--color-text-tertiary)] uppercase tracking-widest">{label}</p>
|
||||||
</div>
|
</div>
|
||||||
{subtitle && (
|
{subtitle && (
|
||||||
<div className="mt-4 pt-4 border-t border-slate-100 dark:border-slate-800/50">
|
<div className="mt-4 pt-4 border-t border-[var(--color-border-subtle)]/50">
|
||||||
<p className="text-[10px] text-[var(--color-text-tertiary)] dark:text-[var(--color-text-tertiary)]">{subtitle}</p>
|
<p className="text-[10px] text-[var(--color-text-tertiary)] dark:text-[var(--color-text-tertiary)]">{subtitle}</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,7 @@ export default function PhotoUpload({
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
fileInputRef.current?.click();
|
fileInputRef.current?.click();
|
||||||
}}
|
}}
|
||||||
className="flex items-center gap-1 px-3 py-2 bg-slate-100 dark:bg-slate-700 rounded-lg text-sm hover:bg-slate-200 dark:hover:bg-slate-600 transition-colors"
|
className="flex items-center gap-1 px-3 py-2 bg-[var(--color-bg-tertiary)] rounded-lg text-sm hover:bg-slate-200 dark:hover:bg-slate-600 transition-colors"
|
||||||
>
|
>
|
||||||
<Upload size={16} />
|
<Upload size={16} />
|
||||||
Browse
|
Browse
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ export function PullToRefresh({ onRefresh, children, disabled = false }: PullToR
|
||||||
opacity: progress
|
opacity: progress
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className={`p-2 rounded-full bg-white dark:bg-slate-800 shadow-lg ${refreshing ? 'animate-spin' : ''}`}>
|
<div className={`p-2 rounded-full bg-[var(--color-bg-elevated)] shadow-lg ${refreshing ? 'animate-spin' : ''}`}>
|
||||||
<RefreshCw size={20} className="text-[var(--color-primary)]" />
|
<RefreshCw size={20} className="text-[var(--color-primary)]" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ export function Skeleton({ className = '' }: SkeletonProps) {
|
||||||
|
|
||||||
export function SkeletonCard() {
|
export function SkeletonCard() {
|
||||||
return (
|
return (
|
||||||
<div className="bg-white dark:bg-slate-800 p-4 rounded-xl border border-slate-200 dark:border-slate-700">
|
<div className="bg-[var(--color-bg-elevated)] p-4 rounded-xl border border-[var(--color-border-default)]">
|
||||||
<div className="flex justify-between items-start mb-3">
|
<div className="flex justify-between items-start mb-3">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Skeleton className="h-5 w-32" />
|
<Skeleton className="h-5 w-32" />
|
||||||
|
|
@ -30,8 +30,8 @@ export function SkeletonCard() {
|
||||||
|
|
||||||
export function SkeletonTable({ rows = 5 }: { rows?: number }) {
|
export function SkeletonTable({ rows = 5 }: { rows?: number }) {
|
||||||
return (
|
return (
|
||||||
<div className="bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-700 overflow-hidden">
|
<div className="bg-[var(--color-bg-elevated)] rounded-xl border border-[var(--color-border-default)] overflow-hidden">
|
||||||
<div className="p-4 border-b border-slate-200 dark:border-slate-700">
|
<div className="p-4 border-b border-[var(--color-border-default)]">
|
||||||
<Skeleton className="h-6 w-40" />
|
<Skeleton className="h-6 w-40" />
|
||||||
</div>
|
</div>
|
||||||
<div className="divide-y divide-slate-100 dark:divide-slate-700">
|
<div className="divide-y divide-slate-100 dark:divide-slate-700">
|
||||||
|
|
@ -50,7 +50,7 @@ export function SkeletonTable({ rows = 5 }: { rows?: number }) {
|
||||||
|
|
||||||
export function SkeletonMetricCard() {
|
export function SkeletonMetricCard() {
|
||||||
return (
|
return (
|
||||||
<div className="bg-white dark:bg-slate-800 p-4 rounded-xl border border-slate-200 dark:border-slate-700">
|
<div className="bg-[var(--color-bg-elevated)] p-4 rounded-xl border border-[var(--color-border-default)]">
|
||||||
<Skeleton className="h-10 w-10 rounded-lg mb-3" />
|
<Skeleton className="h-10 w-10 rounded-lg mb-3" />
|
||||||
<Skeleton className="h-8 w-12 mb-1" />
|
<Skeleton className="h-8 w-12 mb-1" />
|
||||||
<Skeleton className="h-3 w-24" />
|
<Skeleton className="h-3 w-24" />
|
||||||
|
|
@ -62,7 +62,7 @@ export function SkeletonList({ items = 5 }: { items?: number }) {
|
||||||
return (
|
return (
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
{Array.from({ length: items }).map((_, i) => (
|
{Array.from({ length: items }).map((_, i) => (
|
||||||
<div key={i} className="bg-white dark:bg-slate-800 p-4 rounded-xl border border-slate-200 dark:border-slate-700 flex items-center gap-4">
|
<div key={i} className="bg-[var(--color-bg-elevated)] p-4 rounded-xl border border-[var(--color-border-default)] flex items-center gap-4">
|
||||||
<Skeleton className="h-10 w-10 rounded-full" />
|
<Skeleton className="h-10 w-10 rounded-full" />
|
||||||
<div className="flex-1 space-y-2">
|
<div className="flex-1 space-y-2">
|
||||||
<Skeleton className="h-4 w-3/4" />
|
<Skeleton className="h-4 w-3/4" />
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ export function SwipeableRow({
|
||||||
transform: `translateX(${offset}px)`,
|
transform: `translateX(${offset}px)`,
|
||||||
transition: isSwiping ? 'none' : 'transform 0.2s ease-out'
|
transition: isSwiping ? 'none' : 'transform 0.2s ease-out'
|
||||||
}}
|
}}
|
||||||
className="relative bg-white dark:bg-slate-800"
|
className="relative bg-[var(--color-bg-elevated)]"
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -271,10 +271,10 @@ export default function VisitorBadge({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Content */}
|
{/* Content */}
|
||||||
<div className="bg-white dark:bg-slate-800 p-6">
|
<div className="bg-[var(--color-bg-elevated)] p-6">
|
||||||
{/* Photo + Name */}
|
{/* Photo + Name */}
|
||||||
<div className="flex flex-col items-center mb-4">
|
<div className="flex flex-col items-center mb-4">
|
||||||
<div className="w-20 h-20 rounded-full bg-slate-100 dark:bg-slate-700 flex items-center justify-center mb-3 overflow-hidden">
|
<div className="w-20 h-20 rounded-full bg-[var(--color-bg-tertiary)] flex items-center justify-center mb-3 overflow-hidden">
|
||||||
{photoUrl ? (
|
{photoUrl ? (
|
||||||
<img src={photoUrl} alt={name} className="w-full h-full object-cover" />
|
<img src={photoUrl} alt={name} className="w-full h-full object-cover" />
|
||||||
) : (
|
) : (
|
||||||
|
|
@ -358,7 +358,7 @@ export default function VisitorBadge({
|
||||||
<select
|
<select
|
||||||
value={selectedSize}
|
value={selectedSize}
|
||||||
onChange={(e) => setSelectedSize(e.target.value as BadgeSize)}
|
onChange={(e) => setSelectedSize(e.target.value as BadgeSize)}
|
||||||
className="appearance-none px-3 py-2 pr-8 rounded-lg border border-slate-200 dark:border-slate-600 bg-white dark:bg-slate-800 text-sm cursor-pointer"
|
className="appearance-none px-3 py-2 pr-8 rounded-lg border border-slate-200 dark:border-slate-600 bg-[var(--color-bg-elevated)] text-sm cursor-pointer"
|
||||||
>
|
>
|
||||||
<option value="standard">Standard (3.5" x 5")</option>
|
<option value="standard">Standard (3.5" x 5")</option>
|
||||||
<option value="large">Large (3.5" x 6")</option>
|
<option value="large">Large (3.5" x 6")</option>
|
||||||
|
|
@ -411,7 +411,7 @@ export function BadgePrintQueue({
|
||||||
const doneCount = queue.filter(b => b.status === 'done').length;
|
const doneCount = queue.filter(b => b.status === 'done').length;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-700 p-4">
|
<div className="bg-[var(--color-bg-elevated)] rounded-xl border border-[var(--color-border-default)] p-4">
|
||||||
<div className="flex items-center justify-between mb-4">
|
<div className="flex items-center justify-between mb-4">
|
||||||
<div>
|
<div>
|
||||||
<h3 className="font-medium text-[var(--color-text-primary)]">Print Queue</h3>
|
<h3 className="font-medium text-[var(--color-text-primary)]">Print Queue</h3>
|
||||||
|
|
|
||||||
|
|
@ -39,15 +39,15 @@
|
||||||
|
|
||||||
/* Light mode text */
|
/* Light mode text */
|
||||||
--color-text-primary: #0F172A;
|
--color-text-primary: #0F172A;
|
||||||
--color-text-secondary: #475569;
|
--color-text-secondary: #334155;
|
||||||
--color-text-tertiary: #94A3B8;
|
--color-text-tertiary: #64748B;
|
||||||
--color-text-quaternary: #CBD5E1;
|
--color-text-quaternary: #94A3B8;
|
||||||
--color-text-inverse: #F9FAFB;
|
--color-text-inverse: #F9FAFB;
|
||||||
|
|
||||||
/* Light mode borders */
|
/* Light mode borders */
|
||||||
--color-border-default: #E2E8F0;
|
--color-border-default: #CBD5E1;
|
||||||
--color-border-subtle: #F1F5F9;
|
--color-border-subtle: #E2E8F0;
|
||||||
--color-border-strong: #94A3B8;
|
--color-border-strong: #64748B;
|
||||||
|
|
||||||
/* Primary accent (Cultivation Green) */
|
/* Primary accent (Cultivation Green) */
|
||||||
--color-primary: #4ADE80;
|
--color-primary: #4ADE80;
|
||||||
|
|
@ -115,17 +115,17 @@
|
||||||
--color-bg-tertiary: #151C30;
|
--color-bg-tertiary: #151C30;
|
||||||
--color-bg-elevated: #11182A;
|
--color-bg-elevated: #11182A;
|
||||||
|
|
||||||
/* Text */
|
/* Text - improved contrast */
|
||||||
--color-text-primary: #F9FAFB;
|
--color-text-primary: #F8FAFC;
|
||||||
--color-text-secondary: #9CA3AF;
|
--color-text-secondary: #CBD5E1;
|
||||||
--color-text-tertiary: #6B7280;
|
--color-text-tertiary: #94A3B8;
|
||||||
--color-text-quaternary: #374151;
|
--color-text-quaternary: #64748B;
|
||||||
--color-text-inverse: #020617;
|
--color-text-inverse: #0F172A;
|
||||||
|
|
||||||
/* Borders */
|
/* Borders - more visible */
|
||||||
--color-border-default: #1E293B;
|
--color-border-default: #334155;
|
||||||
--color-border-subtle: #151C30;
|
--color-border-subtle: #1E293B;
|
||||||
--color-border-strong: #334155;
|
--color-border-strong: #475569;
|
||||||
|
|
||||||
/* Primary (Emerald Green) */
|
/* Primary (Emerald Green) */
|
||||||
--color-primary: #4ADE80;
|
--color-primary: #4ADE80;
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ export default function AuditLogPage() {
|
||||||
<div className="w-5 h-5 rounded bg-slate-100 dark:bg-slate-800 flex items-center justify-center border border-[var(--color-border-subtle)]">
|
<div className="w-5 h-5 rounded bg-slate-100 dark:bg-slate-800 flex items-center justify-center border border-[var(--color-border-subtle)]">
|
||||||
<User size={10} className="text-[var(--color-text-tertiary)]" />
|
<User size={10} className="text-[var(--color-text-tertiary)]" />
|
||||||
</div>
|
</div>
|
||||||
<span className="text-xs font-bold text-slate-700 dark:text-slate-300 uppercase tracking-widest">
|
<span className="text-xs font-bold text-[var(--color-text-secondary)] uppercase tracking-widest">
|
||||||
{log.userName || 'SYSTEM_CORE'}
|
{log.userName || 'SYSTEM_CORE'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -206,7 +206,7 @@ export default function AuditLogPage() {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Simplified Clinical Pagination */}
|
{/* Simplified Clinical Pagination */}
|
||||||
<div className="flex items-center justify-between px-2 pt-4 border-t border-slate-100 dark:border-slate-800">
|
<div className="flex items-center justify-between px-2 pt-4 border-t border-[var(--color-border-subtle)]">
|
||||||
<p className="text-[10px] font-bold text-[var(--color-text-tertiary)] uppercase tracking-widest">
|
<p className="text-[10px] font-bold text-[var(--color-text-tertiary)] uppercase tracking-widest">
|
||||||
Index <span className="text-[var(--color-text-primary)]">{((pagination.page - 1) * pagination.limit) + 1}–{Math.min(pagination.page * pagination.limit, pagination.total)}</span> / {pagination.total} RECORDED_EVENTS
|
Index <span className="text-[var(--color-text-primary)]">{((pagination.page - 1) * pagination.limit) + 1}–{Math.min(pagination.page * pagination.limit, pagination.total)}</span> / {pagination.total} RECORDED_EVENTS
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -224,9 +224,9 @@ export default function BatchDetailPage() {
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{batch.touchPoints?.map(tp => (
|
{batch.touchPoints?.map(tp => (
|
||||||
<div key={tp.id} className="flex items-center justify-between p-3 rounded-xl bg-[var(--color-bg-tertiary)]/50 border border-slate-100 dark:border-slate-800/50">
|
<div key={tp.id} className="flex items-center justify-between p-3 rounded-xl bg-[var(--color-bg-tertiary)]/50 border border-[var(--color-border-subtle)]/50">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<div className="w-8 h-8 rounded-lg bg-white dark:bg-slate-800 flex items-center justify-center border border-[var(--color-border-subtle)] shadow-sm">
|
<div className="w-8 h-8 rounded-lg bg-[var(--color-bg-elevated)] flex items-center justify-center border border-[var(--color-border-subtle)] shadow-sm">
|
||||||
<Activity size={14} className="text-[var(--color-primary)]" />
|
<Activity size={14} className="text-[var(--color-primary)]" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -254,7 +254,7 @@ export default function BatchDetailPage() {
|
||||||
<button className="px-3 py-1.5 rounded-lg text-[10px] font-bold uppercase tracking-widest">7d</button>
|
<button className="px-3 py-1.5 rounded-lg text-[10px] font-bold uppercase tracking-widest">7d</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="h-[400px] w-full bg-slate-50/50 dark:bg-slate-900/50 rounded-2xl border border-slate-100 dark:border-slate-800 flex items-center justify-center text-[var(--color-text-tertiary)]">
|
<div className="h-[400px] w-full bg-slate-50/50 dark:bg-slate-900/50 rounded-2xl border border-[var(--color-border-subtle)] flex items-center justify-center text-[var(--color-text-tertiary)]">
|
||||||
<div className="flex flex-col items-center gap-2 text-center">
|
<div className="flex flex-col items-center gap-2 text-center">
|
||||||
<TrendingUp size={32} />
|
<TrendingUp size={32} />
|
||||||
<span className="text-xs font-bold tracking-widest uppercase">Interactive Analytics Terminal</span>
|
<span className="text-xs font-bold tracking-widest uppercase">Interactive Analytics Terminal</span>
|
||||||
|
|
@ -389,7 +389,7 @@ function TabButton({ active, label, icon: Icon, count, onClick }: any) {
|
||||||
|
|
||||||
function ActionButton({ label, icon: Icon }: any) {
|
function ActionButton({ label, icon: Icon }: any) {
|
||||||
return (
|
return (
|
||||||
<button className="flex flex-col items-center justify-center p-4 rounded-xl bg-[var(--color-bg-tertiary)]/50 border border-slate-100 dark:border-slate-800/50 hover:border-emerald-500/50 hover:bg-[var(--color-primary)]/10 transition-all group">
|
<button className="flex flex-col items-center justify-center p-4 rounded-xl bg-[var(--color-bg-tertiary)]/50 border border-[var(--color-border-subtle)]/50 hover:border-emerald-500/50 hover:bg-[var(--color-primary)]/10 transition-all group">
|
||||||
<Icon size={20} className="text-[var(--color-text-tertiary)] group-hover:text-[var(--color-primary)] mb-2 transition-colors" />
|
<Icon size={20} className="text-[var(--color-text-tertiary)] group-hover:text-[var(--color-primary)] mb-2 transition-colors" />
|
||||||
<span className="text-[10px] font-bold uppercase tracking-widest text-[var(--color-text-tertiary)] group-hover:text-[var(--color-primary)]">{label}</span>
|
<span className="text-[10px] font-bold uppercase tracking-widest text-[var(--color-text-tertiary)] group-hover:text-[var(--color-primary)]">{label}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -398,7 +398,7 @@ function ActionButton({ label, icon: Icon }: any) {
|
||||||
|
|
||||||
function IntegrationItem({ name, status, time }: any) {
|
function IntegrationItem({ name, status, time }: any) {
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-between p-3 rounded-xl bg-[var(--color-bg-tertiary)]/50 border border-slate-100 dark:border-slate-800/50">
|
<div className="flex items-center justify-between p-3 rounded-xl bg-[var(--color-bg-tertiary)]/50 border border-[var(--color-border-subtle)]/50">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="w-1.5 h-1.5 rounded-full bg-[var(--color-primary)]" />
|
<div className="w-1.5 h-1.5 rounded-full bg-[var(--color-primary)]" />
|
||||||
<div>
|
<div>
|
||||||
|
|
|
||||||
|
|
@ -146,7 +146,7 @@ export default function BatchesPage() {
|
||||||
const days = Math.floor((Date.now() - new Date(batch.startDate).getTime()) / (1000 * 60 * 60 * 24));
|
const days = Math.floor((Date.now() - new Date(batch.startDate).getTime()) / (1000 * 60 * 60 * 24));
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-end">
|
<div className="flex flex-col items-end">
|
||||||
<span className="font-medium text-slate-700 dark:text-slate-300">Day {days}</span>
|
<span className="font-medium text-[var(--color-text-secondary)]">Day {days}</span>
|
||||||
<span className="text-[10px] text-[var(--color-text-tertiary)]">
|
<span className="text-[10px] text-[var(--color-text-tertiary)]">
|
||||||
{new Date(batch.startDate).toLocaleDateString()}
|
{new Date(batch.startDate).toLocaleDateString()}
|
||||||
</span>
|
</span>
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ export default function MetrcDashboardPage() {
|
||||||
{
|
{
|
||||||
key: 'room',
|
key: 'room',
|
||||||
header: 'Local Room',
|
header: 'Local Room',
|
||||||
cell: (plant) => <span className="text-sm text-slate-700 dark:text-slate-300">{plant.room}</span>
|
cell: (plant) => <span className="text-sm text-[var(--color-text-secondary)]">{plant.room}</span>
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'status',
|
key: 'status',
|
||||||
|
|
@ -225,7 +225,7 @@ export default function MetrcDashboardPage() {
|
||||||
className={cn(
|
className={cn(
|
||||||
"px-6 py-2 rounded-lg text-xs font-bold uppercase tracking-widest transition-all",
|
"px-6 py-2 rounded-lg text-xs font-bold uppercase tracking-widest transition-all",
|
||||||
activeTab === tab
|
activeTab === tab
|
||||||
? "bg-white dark:bg-slate-800 text-[var(--color-text-primary)] shadow-sm"
|
? "bg-[var(--color-bg-elevated)] text-[var(--color-text-primary)] shadow-sm"
|
||||||
: "text-[var(--color-text-tertiary)] hover:text-slate-600 dark:hover:text-slate-200"
|
: "text-[var(--color-text-tertiary)] hover:text-slate-600 dark:hover:text-slate-200"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@ export default function RoomsPage() {
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
) : rooms.length === 0 ? (
|
) : rooms.length === 0 ? (
|
||||||
<div className="py-16 text-center rounded-2xl border-2 border-dashed border-slate-100 dark:border-slate-800">
|
<div className="py-16 text-center rounded-2xl border-2 border-dashed border-[var(--color-border-subtle)]">
|
||||||
<Home size={40} className="mx-auto text-slate-300 dark:text-slate-700 mb-4" />
|
<Home size={40} className="mx-auto text-slate-300 dark:text-slate-700 mb-4" />
|
||||||
<p className="text-sm font-bold text-[var(--color-text-tertiary)] uppercase tracking-widest mb-4">No Cultivation Zones Configured</p>
|
<p className="text-sm font-bold text-[var(--color-text-tertiary)] uppercase tracking-widest mb-4">No Cultivation Zones Configured</p>
|
||||||
{isManager && (
|
{isManager && (
|
||||||
|
|
@ -149,7 +149,7 @@ export default function RoomsPage() {
|
||||||
>
|
>
|
||||||
<Card className="p-0 overflow-hidden bg-[var(--color-bg-elevated)] border-[var(--color-border-subtle)] hover:border-emerald-500/50 transition-all">
|
<Card className="p-0 overflow-hidden bg-[var(--color-bg-elevated)] border-[var(--color-border-subtle)] hover:border-emerald-500/50 transition-all">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className={cn("px-5 py-4 border-b border-slate-100 dark:border-slate-800 flex items-center justify-between", accentClasses[accent as keyof typeof accentClasses])}>
|
<div className={cn("px-5 py-4 border-b border-[var(--color-border-subtle)] flex items-center justify-between", accentClasses[accent as keyof typeof accentClasses])}>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<Icon size={16} />
|
<Icon size={16} />
|
||||||
<span className="text-[10px] font-black uppercase tracking-[0.2em]">{room.type}</span>
|
<span className="text-[10px] font-black uppercase tracking-[0.2em]">{room.type}</span>
|
||||||
|
|
@ -169,7 +169,7 @@ export default function RoomsPage() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Environmental Vitals */}
|
{/* Environmental Vitals */}
|
||||||
<div className="grid grid-cols-2 gap-4 py-4 border-y border-slate-100 dark:border-slate-800">
|
<div className="grid grid-cols-2 gap-4 py-4 border-y border-[var(--color-border-subtle)]">
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<div className="flex items-center justify-center gap-1.5 text-xl font-black tracking-tighter text-[var(--color-text-primary)]">
|
<div className="flex items-center justify-center gap-1.5 text-xl font-black tracking-tighter text-[var(--color-text-primary)]">
|
||||||
<Thermometer size={14} className="text-[var(--color-error)]" />
|
<Thermometer size={14} className="text-[var(--color-error)]" />
|
||||||
|
|
@ -190,7 +190,7 @@ export default function RoomsPage() {
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<div className={cn("w-2 h-2 rounded-full", room.batches?.length > 0 ? 'bg-[var(--color-primary)]' : 'bg-slate-300 dark:bg-slate-700')} />
|
<div className={cn("w-2 h-2 rounded-full", room.batches?.length > 0 ? 'bg-[var(--color-primary)]' : 'bg-slate-300 dark:bg-slate-700')} />
|
||||||
<span className="text-xs font-bold text-slate-700 dark:text-slate-300">
|
<span className="text-xs font-bold text-[var(--color-text-secondary)]">
|
||||||
{room.batches?.length || 0} Active Batch{room.batches?.length === 1 ? '' : 'es'}
|
{room.batches?.length || 0} Active Batch{room.batches?.length === 1 ? '' : 'es'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,7 @@ export default function SuppliesPage() {
|
||||||
className: 'w-48',
|
className: 'w-48',
|
||||||
cell: (item) => (
|
cell: (item) => (
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="flex items-center bg-slate-100 dark:bg-slate-800 rounded-lg p-0.5 border border-slate-200 dark:border-slate-700/50">
|
<div className="flex items-center bg-slate-100 dark:bg-slate-800 rounded-lg p-0.5 border border-[var(--color-border-default)]/50">
|
||||||
<button
|
<button
|
||||||
onClick={(e) => { e.stopPropagation(); handleQuantityAdjust(item.id, -1); }}
|
onClick={(e) => { e.stopPropagation(); handleQuantityAdjust(item.id, -1); }}
|
||||||
disabled={item.quantity <= 0}
|
disabled={item.quantity <= 0}
|
||||||
|
|
@ -292,7 +292,7 @@ export default function SuppliesPage() {
|
||||||
className={cn(
|
className={cn(
|
||||||
"px-6 py-2 rounded-lg text-xs font-bold uppercase tracking-widest transition-all",
|
"px-6 py-2 rounded-lg text-xs font-bold uppercase tracking-widest transition-all",
|
||||||
view === 'all'
|
view === 'all'
|
||||||
? "bg-white dark:bg-slate-800 text-[var(--color-text-primary)] shadow-sm"
|
? "bg-[var(--color-bg-elevated)] text-[var(--color-text-primary)] shadow-sm"
|
||||||
: "text-[var(--color-text-tertiary)] hover:text-slate-700 dark:hover:text-slate-300"
|
: "text-[var(--color-text-tertiary)] hover:text-slate-700 dark:hover:text-slate-300"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
@ -303,7 +303,7 @@ export default function SuppliesPage() {
|
||||||
className={cn(
|
className={cn(
|
||||||
"px-6 py-2 rounded-lg text-xs font-bold uppercase tracking-widest transition-all relative",
|
"px-6 py-2 rounded-lg text-xs font-bold uppercase tracking-widest transition-all relative",
|
||||||
view === 'shopping'
|
view === 'shopping'
|
||||||
? "bg-white dark:bg-slate-800 text-[var(--color-text-primary)] shadow-sm"
|
? "bg-[var(--color-bg-elevated)] text-[var(--color-text-primary)] shadow-sm"
|
||||||
: "text-[var(--color-text-tertiary)] hover:text-slate-700 dark:hover:text-slate-300"
|
: "text-[var(--color-text-tertiary)] hover:text-slate-700 dark:hover:text-slate-300"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
@ -388,7 +388,7 @@ export default function SuppliesPage() {
|
||||||
exit={{ opacity: 0, scale: 0.95, y: 20 }}
|
exit={{ opacity: 0, scale: 0.95, y: 20 }}
|
||||||
className="relative w-full max-w-lg bg-white dark:bg-[#0C0C0C] border border-[var(--color-border-subtle)] rounded-3xl shadow-2xl overflow-hidden"
|
className="relative w-full max-w-lg bg-white dark:bg-[#0C0C0C] border border-[var(--color-border-subtle)] rounded-3xl shadow-2xl overflow-hidden"
|
||||||
>
|
>
|
||||||
<div className="p-6 border-b border-slate-100 dark:border-slate-800 flex justify-between items-center">
|
<div className="p-6 border-b border-[var(--color-border-subtle)] flex justify-between items-center">
|
||||||
<h2 className="text-xl font-bold tracking-tight">Add Supply Record</h2>
|
<h2 className="text-xl font-bold tracking-tight">Add Supply Record</h2>
|
||||||
<button onClick={() => setIsAddModalOpen(false)} className="p-2 hover:bg-slate-100 dark:hover:bg-slate-800 rounded-xl transition-colors">
|
<button onClick={() => setIsAddModalOpen(false)} className="p-2 hover:bg-slate-100 dark:hover:bg-slate-800 rounded-xl transition-colors">
|
||||||
<X size={20} className="text-[var(--color-text-tertiary)]" />
|
<X size={20} className="text-[var(--color-text-tertiary)]" />
|
||||||
|
|
|
||||||
|
|
@ -164,7 +164,7 @@ export default function TasksPage() {
|
||||||
))}
|
))}
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
{pendingTasks.length === 0 && (
|
{pendingTasks.length === 0 && (
|
||||||
<div className="py-12 text-center rounded-2xl border-2 border-dashed border-slate-100 dark:border-slate-800">
|
<div className="py-12 text-center rounded-2xl border-2 border-dashed border-[var(--color-border-subtle)]">
|
||||||
<CheckCircle2 size={32} className="mx-auto text-[var(--color-primary)]/20 mb-3" />
|
<CheckCircle2 size={32} className="mx-auto text-[var(--color-primary)]/20 mb-3" />
|
||||||
<p className="text-sm font-bold text-[var(--color-text-tertiary)] uppercase tracking-widest">All Actions Complete</p>
|
<p className="text-sm font-bold text-[var(--color-text-tertiary)] uppercase tracking-widest">All Actions Complete</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -174,14 +174,14 @@ export default function TasksPage() {
|
||||||
|
|
||||||
{/* Recently Completed Section */}
|
{/* Recently Completed Section */}
|
||||||
{completedTasks.length > 0 && (
|
{completedTasks.length > 0 && (
|
||||||
<div className="space-y-4 pt-4 border-t border-slate-100 dark:border-slate-800">
|
<div className="space-y-4 pt-4 border-t border-[var(--color-border-subtle)]">
|
||||||
<div className="flex items-center justify-between px-2">
|
<div className="flex items-center justify-between px-2">
|
||||||
<h3 className="text-xs font-bold uppercase tracking-[0.2em] text-[var(--color-text-tertiary)]">Archive / Verification</h3>
|
<h3 className="text-xs font-bold uppercase tracking-[0.2em] text-[var(--color-text-tertiary)]">Archive / Verification</h3>
|
||||||
<button className="text-[10px] font-bold text-[var(--color-text-tertiary)] uppercase tracking-widest hover:text-[var(--color-primary)]">View History</button>
|
<button className="text-[10px] font-bold text-[var(--color-text-tertiary)] uppercase tracking-widest hover:text-[var(--color-primary)]">View History</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="opacity-60 saturate-50 hover:opacity-100 transition-all duration-500 space-y-2">
|
<div className="opacity-60 saturate-50 hover:opacity-100 transition-all duration-500 space-y-2">
|
||||||
{completedTasks.slice(0, 3).map(task => (
|
{completedTasks.slice(0, 3).map(task => (
|
||||||
<div key={task.id} className="flex items-center justify-between p-4 bg-slate-50/50 dark:bg-slate-900/30 rounded-xl border border-slate-100 dark:border-slate-800/50">
|
<div key={task.id} className="flex items-center justify-between p-4 bg-slate-50/50 dark:bg-slate-900/30 rounded-xl border border-[var(--color-border-subtle)]/50">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<CheckCircle2 size={16} className="text-[var(--color-primary)]" />
|
<CheckCircle2 size={16} className="text-[var(--color-primary)]" />
|
||||||
<div>
|
<div>
|
||||||
|
|
|
||||||
|
|
@ -263,7 +263,7 @@ export default function VisitorManagementPage() {
|
||||||
className={cn(
|
className={cn(
|
||||||
"px-5 py-2 rounded-lg text-xs font-bold uppercase tracking-widest transition-all flex items-center gap-2",
|
"px-5 py-2 rounded-lg text-xs font-bold uppercase tracking-widest transition-all flex items-center gap-2",
|
||||||
activeTab === tab.id
|
activeTab === tab.id
|
||||||
? "bg-white dark:bg-slate-800 text-[var(--color-text-primary)] shadow-sm"
|
? "bg-[var(--color-bg-elevated)] text-[var(--color-text-primary)] shadow-sm"
|
||||||
: "text-[var(--color-text-tertiary)] hover:text-slate-700 dark:hover:text-slate-300"
|
: "text-[var(--color-text-tertiary)] hover:text-slate-700 dark:hover:text-slate-300"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
@ -382,7 +382,7 @@ export default function VisitorManagementPage() {
|
||||||
<p className="text-xs text-[var(--color-text-tertiary)] leading-relaxed">{zone.description || 'No zone constraints defined.'}</p>
|
<p className="text-xs text-[var(--color-text-tertiary)] leading-relaxed">{zone.description || 'No zone constraints defined.'}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-8 pt-6 border-t border-slate-100 dark:border-slate-800/50 flex items-center justify-between">
|
<div className="mt-8 pt-6 border-t border-[var(--color-border-subtle)]/50 flex items-center justify-between">
|
||||||
<div className="flex -space-x-2">
|
<div className="flex -space-x-2">
|
||||||
{[1, 2].map(i => (
|
{[1, 2].map(i => (
|
||||||
<div key={i} className="w-6 h-6 rounded-full bg-slate-200 dark:bg-slate-800 border-2 border-white dark:border-[#0C0C0C]" />
|
<div key={i} className="w-6 h-6 rounded-full bg-slate-200 dark:bg-slate-800 border-2 border-white dark:border-[#0C0C0C]" />
|
||||||
|
|
|
||||||
|
|
@ -68,17 +68,17 @@ export default function PageTemplate() {
|
||||||
placeholder="Search..."
|
placeholder="Search..."
|
||||||
value={searchQuery}
|
value={searchQuery}
|
||||||
onChange={(e) => setSearchQuery(e.target.value)}
|
onChange={(e) => setSearchQuery(e.target.value)}
|
||||||
className="w-full pl-10 pr-4 py-2.5 rounded-lg border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-800 text-sm focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500 outline-none"
|
className="w-full pl-10 pr-4 py-2.5 rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-elevated)] text-sm focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500 outline-none"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<button className="flex items-center gap-2 px-4 py-2.5 rounded-lg border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-800 text-sm hover:bg-slate-50 dark:hover:bg-slate-700">
|
<button className="flex items-center gap-2 px-4 py-2.5 rounded-lg border border-[var(--color-border-default)] bg-[var(--color-bg-elevated)] text-sm hover:bg-slate-50 dark:hover:bg-slate-700">
|
||||||
<Filter size={16} />
|
<Filter size={16} />
|
||||||
Filters
|
Filters
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Content Area */}
|
{/* Content Area */}
|
||||||
<div className="bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-700 shadow-sm">
|
<div className="bg-[var(--color-bg-elevated)] rounded-xl border border-[var(--color-border-default)] shadow-sm">
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<div className="flex items-center justify-center p-12">
|
<div className="flex items-center justify-center p-12">
|
||||||
<div className="animate-spin w-8 h-8 border-2 border-emerald-500 border-t-transparent rounded-full" />
|
<div className="animate-spin w-8 h-8 border-2 border-emerald-500 border-t-transparent rounded-full" />
|
||||||
|
|
@ -86,7 +86,7 @@ export default function PageTemplate() {
|
||||||
) : items.length === 0 ? (
|
) : items.length === 0 ? (
|
||||||
/* Empty State */
|
/* Empty State */
|
||||||
<div className="flex flex-col items-center justify-center p-12 text-center">
|
<div className="flex flex-col items-center justify-center p-12 text-center">
|
||||||
<div className="w-16 h-16 rounded-full bg-slate-100 dark:bg-slate-700 flex items-center justify-center mb-4">
|
<div className="w-16 h-16 rounded-full bg-[var(--color-bg-tertiary)] flex items-center justify-center mb-4">
|
||||||
<FileText size={32} className="text-[var(--color-text-tertiary)]" />
|
<FileText size={32} className="text-[var(--color-text-tertiary)]" />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-lg font-semibold text-[var(--color-text-primary)] mb-2">
|
<h3 className="text-lg font-semibold text-[var(--color-text-primary)] mb-2">
|
||||||
|
|
|
||||||
|
|
@ -70,11 +70,11 @@ export function WidgetTemplate({
|
||||||
const trendColor = data?.trend === 'up' ? 'text-[var(--color-primary)]' : data?.trend === 'down' ? 'text-red-500' : 'text-[var(--color-text-tertiary)]';
|
const trendColor = data?.trend === 'up' ? 'text-[var(--color-primary)]' : data?.trend === 'down' ? 'text-red-500' : 'text-[var(--color-text-tertiary)]';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-700 p-4 shadow-sm">
|
<div className="bg-[var(--color-bg-elevated)] rounded-xl border border-[var(--color-border-default)] p-4 shadow-sm">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex items-center justify-between mb-3">
|
<div className="flex items-center justify-between mb-3">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<div className={`p-2 rounded-lg bg-slate-100 dark:bg-slate-700 ${iconColor}`}>
|
<div className={`p-2 rounded-lg bg-[var(--color-bg-tertiary)] ${iconColor}`}>
|
||||||
<Icon size={18} />
|
<Icon size={18} />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-sm font-medium text-[var(--color-text-primary)]">{title}</h3>
|
<h3 className="text-sm font-medium text-[var(--color-text-primary)]">{title}</h3>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue