Files
ERitors-Scribe-Desktop/components/book/settings/objects/page.tsx

328 lines
19 KiB
TypeScript

'use client';
import React, {useState} from 'react';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {faArrowLeft} from '@fortawesome/free-solid-svg-icons';
interface RelatedItem {
name: string;
type: string;
description: string;
history: string;
}
interface Item {
id: number | null;
name: string;
description: string;
history: string;
location: string;
ownedBy: string;
functionality: string;
image: string;
relatedItems: RelatedItem[];
}
const initialItemState: Item = {
id: null,
name: '',
description: '',
history: '',
location: '',
ownedBy: '',
functionality: '',
image: '',
relatedItems: [],
};
export default function Items() {
const [items, setItems] = useState<Item[]>([
{
id: 1,
name: 'Sword of Destiny',
description: 'A powerful sword',
history: 'Forged in the ancient times...',
location: 'Castle',
ownedBy: 'John Doe',
functionality: 'Cuts through anything',
image: 'https://via.placeholder.com/150',
relatedItems: []
},
{
id: 2,
name: 'Shield of Valor',
description: 'An unbreakable shield',
history: 'Used by the legendary hero...',
location: 'Fortress',
ownedBy: 'Jane Doe',
functionality: 'Deflects any attack',
image: 'https://via.placeholder.com/150',
relatedItems: []
}
]);
const [selectedItem, setSelectedItem] = useState<Item | null>(null);
const [searchQuery, setSearchQuery] = useState<string>('');
const [newItem, setNewItem] = useState<Item>(initialItemState);
const [newRelatedItem, setNewRelatedItem] = useState<RelatedItem>({
name: '',
type: '',
description: '',
history: ''
});
const filteredItems = items.filter(
(item) =>
item.name.toLowerCase().includes(searchQuery.toLowerCase())
);
const handleItemClick = (item: Item) => {
setSelectedItem(item);
};
const handleAddItem = () => {
setSelectedItem(newItem);
};
const handleSaveItem = () => {
if (selectedItem) {
if (selectedItem.id === null) {
setItems([...items, {...selectedItem, id: items.length + 1}]);
} else {
setItems(items.map((item) => (item.id === selectedItem.id ? selectedItem : item)));
}
setSelectedItem(null);
setNewItem(initialItemState);
}
};
const handleItemChange = (key: keyof Item, value: string) => {
if (selectedItem) {
setSelectedItem({...selectedItem, [key]: value});
}
};
const handleElementChange = (section: keyof Item, index: number, key: keyof RelatedItem, value: string) => {
if (selectedItem) {
const updatedSection = [...(selectedItem[section] as RelatedItem[])];
updatedSection[index][key] = value;
setSelectedItem({...selectedItem, [section]: updatedSection});
}
};
const handleAddElement = (section: keyof Item, value: RelatedItem) => {
if (selectedItem) {
const updatedSection = [...(selectedItem[section] as RelatedItem[]), value];
setSelectedItem({...selectedItem, [section]: updatedSection});
}
};
const handleRemoveElement = (section: keyof Item, index: number) => {
if (selectedItem) {
const updatedSection = (selectedItem[section] as RelatedItem[]).filter((_, i) => i !== index);
setSelectedItem({...selectedItem, [section]: updatedSection});
}
};
return (
<main className="flex-grow p-8 overflow-y-auto">
{selectedItem ? (
<div>
<div className="flex justify-between sticky top-0 z-10 bg-gray-900 py-4">
<button onClick={() => setSelectedItem(null)}
className="flex items-center gap-2 text-text-primary bg-secondary/50 hover:bg-secondary px-4 py-2 rounded-xl transition-all duration-200 hover:scale-105 shadow-md">
<FontAwesomeIcon icon={faArrowLeft} className="mr-2 w-5 h-5"/> Back
</button>
<h2 className="text-3xl font-['ADLaM_Display'] text-center text-text-primary">{selectedItem.name}</h2>
<button onClick={handleSaveItem}
className="bg-primary hover:bg-primary-dark text-text-primary font-semibold py-2.5 px-6 rounded-xl shadow-md hover:shadow-lg hover:scale-105 transition-all duration-200">
Save Item
</button>
</div>
<div className="bg-gray-700 rounded-lg p-8 shadow-lg space-y-4">
<div>
<label className="block text-white mb-2" htmlFor="name">Name</label>
<input
type="text"
id="name"
value={selectedItem.name}
onChange={(e) => handleItemChange('name', e.target.value)}
className="w-full px-4 py-2.5 rounded-xl bg-secondary/50 text-text-primary border border-secondary/50 outline-none hover:bg-secondary hover:border-secondary focus:border-primary focus:ring-4 focus:ring-primary/20 transition-all duration-200"
/>
</div>
<div>
<label className="block text-white mb-2" htmlFor="description">Description</label>
<textarea
id="description"
rows={4}
value={selectedItem.description}
onChange={(e) => handleItemChange('description', e.target.value)}
className="w-full px-4 py-2.5 rounded-xl bg-secondary/50 text-text-primary border border-secondary/50 outline-none hover:bg-secondary hover:border-secondary focus:border-primary focus:ring-4 focus:ring-primary/20 transition-all duration-200"
></textarea>
</div>
<div>
<label className="block text-white mb-2" htmlFor="history">History</label>
<textarea
id="history"
rows={4}
value={selectedItem.history}
onChange={(e) => handleItemChange('history', e.target.value)}
className="w-full px-4 py-2.5 rounded-xl bg-secondary/50 text-text-primary border border-secondary/50 outline-none hover:bg-secondary hover:border-secondary focus:border-primary focus:ring-4 focus:ring-primary/20 transition-all duration-200"
></textarea>
</div>
<div>
<label className="block text-white mb-2" htmlFor="location">Location</label>
<select
id="location"
value={selectedItem.location}
onChange={(e) => handleItemChange('location', e.target.value)}
className="w-full px-4 py-2.5 rounded-xl bg-secondary/50 text-text-primary border border-secondary/50 outline-none hover:bg-secondary hover:border-secondary focus:border-primary focus:ring-4 focus:ring-primary/20 transition-all duration-200"
>
<option value="">Select Location</option>
<option value="Castle">Castle</option>
<option value="Fortress">Fortress</option>
</select>
</div>
<div>
<label className="block text-white mb-2" htmlFor="ownedBy">Owned By</label>
<select
id="ownedBy"
value={selectedItem.ownedBy}
onChange={(e) => handleItemChange('ownedBy', e.target.value)}
className="w-full px-4 py-2.5 rounded-xl bg-secondary/50 text-text-primary border border-secondary/50 outline-none hover:bg-secondary hover:border-secondary focus:border-primary focus:ring-4 focus:ring-primary/20 transition-all duration-200"
>
<option value="">Select Owner</option>
{items.map((item) => (
<option key={item.id} value={item.name}>{item.name}</option>
))}
</select>
</div>
<div>
<label className="block text-white mb-2" htmlFor="functionality">Functionality</label>
<textarea
id="functionality"
rows={4}
value={selectedItem.functionality}
onChange={(e) => handleItemChange('functionality', e.target.value)}
className="w-full px-4 py-2.5 rounded-xl bg-secondary/50 text-text-primary border border-secondary/50 outline-none hover:bg-secondary hover:border-secondary focus:border-primary focus:ring-4 focus:ring-primary/20 transition-all duration-200"
></textarea>
</div>
<div>
<label className="block text-white mb-2" htmlFor="image">Image URL</label>
<input
type="text"
id="image"
value={selectedItem.image}
onChange={(e) => handleItemChange('image', e.target.value)}
className="w-full px-4 py-2.5 rounded-xl bg-secondary/50 text-text-primary border border-secondary/50 outline-none hover:bg-secondary hover:border-secondary focus:border-primary focus:ring-4 focus:ring-primary/20 transition-all duration-200"
/>
</div>
</div>
<div className="bg-gray-700 rounded-lg p-8 shadow-lg space-y-4 mt-4">
<h3 className="text-2xl font-['ADLaM_Display'] text-text-primary">Related Items</h3>
<div className="space-y-2">
{selectedItem.relatedItems.map((relatedItem, index) => (
<details key={index}
className="bg-secondary/30 rounded-xl mb-4 p-4 shadow-sm hover:shadow-md transition-all duration-200">
<summary className="text-lg text-white cursor-pointer">{relatedItem.name}</summary>
<div className="mt-2">
<label className="block text-white mb-2"
htmlFor={`related-item-description-${relatedItem.name}`}>Description</label>
<textarea
id={`related-item-description-${relatedItem.name}`}
rows={3}
value={relatedItem.description}
onChange={(e) => handleElementChange('relatedItems', index, 'description', e.target.value)}
className="w-full px-4 py-2.5 rounded-xl bg-secondary/50 text-text-primary border border-secondary/50 outline-none hover:bg-secondary hover:border-secondary focus:border-primary focus:ring-4 focus:ring-primary/20 transition-all duration-200"
></textarea>
<label className="block text-white mb-2 mt-4"
htmlFor={`related-item-history-${relatedItem.name}`}>History</label>
<textarea
id={`related-item-history-${relatedItem.name}`}
rows={3}
value={relatedItem.history}
onChange={(e) => handleElementChange('relatedItems', index, 'history', e.target.value)}
className="w-full px-4 py-2.5 rounded-xl bg-secondary/50 text-text-primary border border-secondary/50 outline-none hover:bg-secondary hover:border-secondary focus:border-primary focus:ring-4 focus:ring-primary/20 transition-all duration-200"
></textarea>
<button
type="button"
onClick={() => handleRemoveElement('relatedItems', index)}
className="bg-error/90 hover:bg-error text-text-primary font-semibold py-2 px-4 rounded-xl shadow-md hover:shadow-lg hover:scale-105 transition-all duration-200 mt-2"
>
Remove
</button>
</div>
</details>
))}
<div className="flex space-x-2 items-center mt-2">
<select
className="w-full px-4 py-2.5 rounded-xl bg-secondary/50 text-text-primary border border-secondary/50 outline-none hover:bg-secondary hover:border-secondary focus:border-primary focus:ring-4 focus:ring-primary/20 transition-all duration-200"
onChange={(e) => setNewRelatedItem({...newRelatedItem, name: e.target.value})}
value={newRelatedItem.name}
>
<option value="">Select Related Item</option>
{items.map((item) => (
<option key={item.id} value={item.name}>{item.name}</option>
))}
</select>
<select
className="w-full px-4 py-2.5 rounded-xl bg-secondary/50 text-text-primary border border-secondary/50 outline-none hover:bg-secondary hover:border-secondary focus:border-primary focus:ring-4 focus:ring-primary/20 transition-all duration-200"
onChange={(e) => setNewRelatedItem({...newRelatedItem, type: e.target.value})}
value={newRelatedItem.type}
>
<option value="">Relation Type</option>
<option value="Related">Related</option>
<option value="Similar">Similar</option>
{/* Add more relation types as needed */}
</select>
<button
type="button"
onClick={() => {
handleAddElement('relatedItems', {...newRelatedItem});
setNewRelatedItem({name: '', type: '', description: '', history: ''});
}}
className="bg-primary hover:bg-primary-dark text-text-primary font-semibold py-2.5 px-5 rounded-xl shadow-md hover:shadow-lg hover:scale-105 transition-all duration-200"
>
Add Related Item
</button>
</div>
</div>
</div>
</div>
) : (
<div>
<div className="flex justify-between sticky top-0 z-10 bg-gray-900 py-4">
<input
type="text"
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="w-full px-4 py-2.5 rounded-xl bg-secondary/50 text-text-primary border border-secondary/50 outline-none hover:bg-secondary hover:border-secondary focus:border-primary focus:ring-4 focus:ring-primary/20 transition-all duration-200"
placeholder="Search Items"
/>
<button
type="button"
onClick={handleAddItem}
className="bg-primary hover:bg-primary-dark text-text-primary font-semibold py-2.5 px-5 rounded-xl ml-4 shadow-md hover:shadow-lg hover:scale-105 transition-all duration-200"
>
Add New Item
</button>
</div>
<div>
<h2 className="text-4xl font-['ADLaM_Display'] text-text-primary mb-6">Items</h2>
<div className="flex flex-wrap space-x-4">
{filteredItems.map((item) => (
<div key={item.id} onClick={() => handleItemClick(item)}
className="cursor-pointer bg-tertiary/90 backdrop-blur-sm p-4 rounded-xl shadow-lg hover:shadow-xl hover:scale-105 transition-all duration-200 border border-secondary/50">
<img src={item.image || 'https://via.placeholder.com/150'} alt={item.name}
className="w-full h-32 object-cover rounded-lg mb-2"/>
<h3 className="text-lg font-bold text-text-primary">{item.name}</h3>
<p className="text-muted">{item.description}</p>
</div>
))}
</div>
</div>
</div>
)}
</main>
);
}