mirror of
https://github.com/R0m1k3/Priceflow.git
synced 2026-10-12 01:39:25 +02:00
feat: Implement dashboard page for item management and add/edit item modal.
This commit is contained in:
1 parent
18d5f3dbf1
commit
a9cb4e4ac5
2 files changed
+68
-7
No files matched your search
@@ -7,10 +7,11 @@ import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||
import { X } from 'lucide-react';
|
||||
|
||||
const API_URL = '/api';
|
||||
|
||||
export function ItemModal({ item, onClose, onSaved, open }) {
|
||||
export function ItemModal({ item, onClose, onSaved, open, categories = [] }) {
|
||||
const { t } = useTranslation();
|
||||
const [formData, setFormData] = useState({
|
||||
url: '',
|
||||
@@ -18,9 +19,11 @@ export function ItemModal({ item, onClose, onSaved, open }) {
|
||||
target_price: '',
|
||||
tags: '',
|
||||
description: '',
|
||||
notification_channel_id: 'none'
|
||||
notification_channel_id: 'none',
|
||||
category: ''
|
||||
});
|
||||
const [channels, setChannels] = useState([]);
|
||||
const [showCustomInput, setShowCustomInput] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchChannels = async () => {
|
||||
@@ -45,8 +48,10 @@ export function ItemModal({ item, onClose, onSaved, open }) {
|
||||
target_price: item.target_price || '',
|
||||
tags: item.tags || '',
|
||||
description: item.description || '',
|
||||
notification_channel_id: item.notification_channel_id ? item.notification_channel_id.toString() : 'none'
|
||||
notification_channel_id: item.notification_channel_id ? item.notification_channel_id.toString() : 'none',
|
||||
category: item.category || ''
|
||||
});
|
||||
setShowCustomInput(!!item.category && !categories.includes(item.category));
|
||||
} else {
|
||||
setFormData({
|
||||
url: '',
|
||||
@@ -54,10 +59,12 @@ export function ItemModal({ item, onClose, onSaved, open }) {
|
||||
target_price: '',
|
||||
tags: '',
|
||||
description: '',
|
||||
notification_channel_id: 'none'
|
||||
notification_channel_id: 'none',
|
||||
category: ''
|
||||
});
|
||||
setShowCustomInput(false);
|
||||
}
|
||||
}, [item, open]);
|
||||
}, [item, open, categories]);
|
||||
|
||||
|
||||
|
||||
@@ -125,6 +132,58 @@ export function ItemModal({ item, onClose, onSaved, open }) {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="category">{t('itemModal.category') || 'Category'}</Label>
|
||||
{showCustomInput ? (
|
||||
<div className="flex gap-2">
|
||||
<Input
|
||||
id="custom_category"
|
||||
placeholder="Enter new category"
|
||||
value={formData.category}
|
||||
onChange={e => setFormData({ ...formData, category: e.target.value })}
|
||||
autoFocus
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() => {
|
||||
setShowCustomInput(false);
|
||||
setFormData({ ...formData, category: '' });
|
||||
}}
|
||||
title="Select existing category"
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<Select
|
||||
value={categories.includes(formData.category) ? formData.category : (formData.category ? '__custom__' : 'none')}
|
||||
onValueChange={(val) => {
|
||||
if (val === '__custom__') {
|
||||
setShowCustomInput(true);
|
||||
setFormData({ ...formData, category: '' });
|
||||
} else if (val === 'none') {
|
||||
setFormData({ ...formData, category: '' });
|
||||
} else {
|
||||
setFormData({ ...formData, category: val });
|
||||
}
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="w-full">
|
||||
<SelectValue placeholder="Select a category" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="none">None</SelectItem>
|
||||
{categories.map(cat => (
|
||||
<SelectItem key={cat} value={cat}>{cat}</SelectItem>
|
||||
))}
|
||||
<SelectItem value="__custom__">Custom...</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="channel">Notification Channel</Label>
|
||||
<Select
|
||||
|
||||
@@ -178,14 +178,16 @@ export default function Dashboard() {
|
||||
<ItemModal
|
||||
open={showAddModal}
|
||||
onClose={() => setShowAddModal(false)}
|
||||
onSaved={refreshItems}
|
||||
onSaved={() => { refreshItems(); loadCategories(); }}
|
||||
categories={categories}
|
||||
/>
|
||||
|
||||
<ItemModal
|
||||
open={!!editingItem}
|
||||
item={editingItem}
|
||||
onClose={() => setEditingItem(null)}
|
||||
onSaved={refreshItems}
|
||||
onSaved={() => { refreshItems(); loadCategories(); }}
|
||||
categories={categories}
|
||||
/>
|
||||
|
||||
<DeleteConfirmationModal
|
||||
|
||||
Reference in new issue
Block a user