Bump app version to 0.2.1 and add Spell and DeleteButton components

- Introduced comprehensive `Spell` models with tagging and state management capabilities.
- Added reusable `DeleteButton` component with confirmation workflow for destructive actions.
This commit is contained in:
natreex
2026-01-26 14:24:22 -05:00
parent 512955d10a
commit 2359638cb0
3 changed files with 176 additions and 1 deletions

View File

@@ -0,0 +1,66 @@
'use client';
import {useState} from 'react';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {faTrash} from '@fortawesome/free-solid-svg-icons';
import AlertBox from '@/components/AlertBox';
interface DeleteButtonProps {
onDelete: () => void | Promise<void>;
confirmTitle: string;
confirmMessage: string;
confirmButtonText: string;
cancelButtonText: string;
disabled?: boolean;
className?: string;
}
export default function DeleteButton(
{
onDelete,
confirmTitle,
confirmMessage,
confirmButtonText,
cancelButtonText,
disabled = false,
className = ''
}: DeleteButtonProps
) {
const [showConfirm, setShowConfirm] = useState<boolean>(false);
function handlePress(): void {
if (disabled) return;
setShowConfirm(true);
}
async function handleConfirm(): Promise<void> {
setShowConfirm(false);
await onDelete();
}
function handleCancel(): void {
setShowConfirm(false);
}
return (
<>
<button
onClick={handlePress}
disabled={disabled}
className={`flex items-center justify-center bg-error/90 hover:bg-error w-10 h-10 rounded-xl border border-error shadow-md hover:shadow-lg hover:scale-110 transition-all duration-200 ${disabled ? 'opacity-50 cursor-not-allowed' : ''} ${className}`}
>
<FontAwesomeIcon icon={faTrash} className="text-text-primary w-5 h-5"/>
</button>
{showConfirm && (
<AlertBox
title={confirmTitle}
message={confirmMessage}
type="danger"
confirmText={confirmButtonText}
cancelText={cancelButtonText}
onConfirm={handleConfirm}
onCancel={handleCancel}
/>
)}
</>
);
}

109
lib/models/Spell.ts Normal file
View File

@@ -0,0 +1,109 @@
import {SelectBoxProps} from "@/shared/interface";
// ==================== SPELL TAG INTERFACES ====================
export interface SpellTagProps {
id: string;
name: string;
color: string | null;
}
// ==================== SPELL INTERFACES ====================
// Réponse de GET /spell/detail et POST /spell/add
export interface SpellProps {
id: string;
name: string;
description: string;
appearance: string;
tags: string[]; // IDs des tags
powerLevel: string | null;
components: string | null;
limitations: string | null;
notes: string | null;
}
// Pour POST /spell/add et PUT /spell/update
export interface SpellPropsPost {
id?: string;
name: string;
description: string;
appearance: string;
tags: string[];
powerLevel?: string | null;
components?: string | null;
limitations?: string | null;
notes?: string | null;
}
// Item dans la liste (GET /spell/list)
export interface SpellListItem {
id: string;
name: string;
description: string;
tags: SpellTagProps[]; // Tags résolus (pas les IDs)
}
// Réponse de GET /spell/list
export interface SpellListResponse {
enabled: boolean;
spells: SpellListItem[];
tags: SpellTagProps[];
}
// État local pour l'édition (avec id nullable pour création)
export interface SpellEditState {
id: string | null;
name: string;
description: string;
appearance: string;
tags: string[];
powerLevel: string | null;
components: string | null;
limitations: string | null;
notes: string | null;
}
export const initialSpellState: SpellEditState = {
id: null,
name: '',
description: '',
appearance: '',
tags: [],
powerLevel: null,
components: null,
limitations: null,
notes: null,
};
export const spellPowerLevels: SelectBoxProps[] = [
{value: 'none', label: 'spellPowerLevels.none'},
{value: 'cantrip', label: 'spellPowerLevels.cantrip'},
{value: 'novice', label: 'spellPowerLevels.novice'},
{value: 'apprentice', label: 'spellPowerLevels.apprentice'},
{value: 'journeyman', label: 'spellPowerLevels.journeyman'},
{value: 'expert', label: 'spellPowerLevels.expert'},
{value: 'master', label: 'spellPowerLevels.master'},
{value: 'grandmaster', label: 'spellPowerLevels.grandmaster'},
{value: 'legendary', label: 'spellPowerLevels.legendary'},
{value: 'divine', label: 'spellPowerLevels.divine'},
];
export const defaultTagColors: string[] = [
'#51AE84',
'#3A8B69',
'#2196F3',
'#1976D2',
'#FFA726',
'#FF9800',
'#EF5350',
'#E53935',
'#AB47BC',
'#9C27B0',
'#26A69A',
'#00897B',
'#5C6BC0',
'#3F51B5',
'#EC407A',
'#D81B60',
];

View File

@@ -1,7 +1,7 @@
{
"name": "eritorsscribe",
"productName": "ERitors Scribe",
"version": "0.1.1",
"version": "0.2.1",
"type": "module",
"main": "dist/electron/main.js",
"scripts": {