Add foundational components and logic for migration, UI design, and input handling

- Introduced foundational UI components (`Badge`, `LockCard`, `SectionHeader`, `AvatarIcon`, etc.) for flexible layouts and consistent design.
- Added migration support with the `MigrationModal` component and backend integration for exporting/importing data between Electron and Tauri.
- Extended form components with `TextAreaInput`, `OrderInput`, `ToggleField`, and `ToolbarSelect` for improved input handling.
- Updated `ScribeShell` with migration popup logic to prompt users for data migration.
- Integrated `AlertStack` for better alert handling and notification management.
- Enhanced Rust/Tauri services with migration command implementations.
- Added translations and styles for new components.
This commit is contained in:
natreex
2026-04-05 12:52:54 -04:00
parent 2b6d4cc48b
commit d4765e6576
49 changed files with 3115 additions and 2 deletions

123
components/ui/AlertBox.tsx Normal file
View File

@@ -0,0 +1,123 @@
import React, {useEffect, useState} from 'react';
import {createPortal} from 'react-dom';
import {AlertTriangle, Check, Info, LucideIcon, X} from 'lucide-react';
import Button from "@/components/ui/Button";
export type AlertType = 'alert' | 'danger' | 'informatif' | 'success';
interface AlertBoxProps {
title: string;
message: string;
type: AlertType;
confirmText?: string;
cancelText?: string;
onConfirm: () => Promise<void>;
onCancel: () => void;
}
interface AlertConfig {
background: string;
borderColor: string;
icon: LucideIcon;
iconBg: string;
}
export default function AlertBox(
{
title,
message,
type,
confirmText = 'Confirmer',
cancelText = 'Annuler',
onConfirm,
onCancel
}: AlertBoxProps) {
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
return () => setMounted(false);
}, []);
function getButtonVariant(alertType: AlertType): 'warning' | 'danger' | 'info' | 'success' {
switch (alertType) {
case 'alert':
return 'warning';
case 'danger':
return 'danger';
case 'informatif':
return 'info';
case 'success':
default:
return 'success';
}
}
function getAlertConfig(alertType: AlertType): AlertConfig {
switch (alertType) {
case 'alert':
return {
background: 'bg-warning',
borderColor: 'border-warning/30',
icon: AlertTriangle,
iconBg: 'bg-warning/10'
};
case 'danger':
return {
background: 'bg-error',
borderColor: 'border-error/30',
icon: X,
iconBg: 'bg-error/10'
};
case 'informatif':
return {
background: 'bg-info',
borderColor: 'border-info/30',
icon: Info,
iconBg: 'bg-info/10'
};
case 'success':
default:
return {
background: 'bg-success',
borderColor: 'border-success/30',
icon: Check,
iconBg: 'bg-success/10'
};
}
}
const alertSettings = getAlertConfig(type);
const AlertIcon = alertSettings.icon;
const alertContent = (
<div
className="fixed inset-0 z-[9999] flex items-center justify-center p-4 bg-darkest-background/60 backdrop-blur-md animate-fadeIn">
<div
className="relative w-full max-w-md rounded-2xl bg-tertiary overflow-hidden">
<div className={`${alertSettings.background} px-6 py-4`}>
<div className="flex items-center gap-4">
<div
className={`w-12 h-12 rounded-xl ${alertSettings.iconBg} flex items-center justify-center`}>
<AlertIcon className="w-6 h-6 text-text-primary" strokeWidth={1.75}/>
</div>
<h3 className="text-xl font-bold text-text-primary tracking-wide">{title}</h3>
</div>
</div>
<div className="p-6 bg-darkest-background">
<p className="mb-6 text-text-primary whitespace-pre-line leading-relaxed">{message}</p>
<div className="flex justify-end gap-3">
<Button variant="secondary" onClick={onCancel}>{cancelText}</Button>
<Button variant={getButtonVariant(type)} onClick={onConfirm}>{confirmText}</Button>
</div>
</div>
</div>
</div>
);
if (!mounted) return null;
return createPortal(alertContent, document.body);
}