feat(admin): replace all remaining action buttons with Button component
All checks were successful
Deploy Canina / deploy (push) Successful in 29s

This commit is contained in:
parsa aghaei 2026-08-23 10:22:06 +03:30
parent 1350267ffb
commit 33c1bee483
9 changed files with 172 additions and 65 deletions

View File

@ -201,10 +201,23 @@ export default function Blogs() {
</td>
<td className="py-4 px-6">
<div className="flex items-center gap-2">
<button onClick={() => openModal(blog)} className="p-2 text-blue-600 hover:bg-blue-50 rounded-lg transition-colors cursor-pointer"><Edit2 className="w-4 h-4" /></button>
<button onClick={() => setDeleteTargetId(blog.id)} className="p-2 text-red-600 hover:bg-red-50 rounded-lg transition-colors cursor-pointer"><Trash2 className="w-4 h-4" /></button>
<Button
variant="ghost"
size="xs"
startIcon={Edit2}
onClick={() => openModal(blog)}
className="text-blue-600 hover:bg-blue-50"
/>
<Button
variant="ghost"
size="xs"
startIcon={Trash2}
onClick={() => setDeleteTargetId(blog.id)}
className="text-red-600 hover:bg-red-50"
/>
</div>
</td>
</tr>
))
)}

View File

@ -2,6 +2,8 @@ import React, { useState, useEffect } from 'react';
import { toast } from 'react-hot-toast';
import api from '../services/api';
import ConfirmModal from '../components/ui/ConfirmModal';
import Button from '../components/ui/Button';
export interface HeroBanner {
id: string;
@ -165,9 +167,9 @@ export default function CMS() {
<label className="block text-xs font-bold text-gray-600 mb-1">آدرس تصویر (URL)</label>
<input value={newImageUrl} onChange={e => setNewImageUrl(e.target.value)} className="w-full border rounded-xl p-2.5 text-sm" placeholder="/assets/images/..." />
</div>
<button type="submit" className="bg-blue-600 text-white font-bold px-6 py-2.5 rounded-xl hover:bg-blue-700 text-sm">
<Button type="submit" variant="primary" size="md">
ثبت بنر جدید
</button>
</Button>
</form>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
@ -177,9 +179,14 @@ export default function CMS() {
<h4 className="font-bold text-gray-900">{b.title}</h4>
<p className="text-xs text-gray-500 mt-1">{b.subtitle}</p>
</div>
<button onClick={() => setDeleteBannerId(b.id)} className="text-red-500 text-xs font-bold bg-red-50 px-3 py-1.5 rounded-lg hover:bg-red-100">
<Button
variant="ghost"
size="xs"
onClick={() => setDeleteBannerId(b.id)}
className="text-red-500 hover:bg-red-50"
>
حذف
</button>
</Button>
</div>
))}
</div>
@ -204,9 +211,9 @@ export default function CMS() {
<label className="block text-xs font-bold text-gray-600 mb-1">متن نظر و تجربه علمی</label>
<textarea required value={quote} onChange={e => setQuote(e.target.value)} className="w-full border rounded-xl p-2.5 text-sm" rows={3} placeholder="تجربه استفاده از Canhydrox GAG..." />
</div>
<button type="submit" className="bg-blue-600 text-white font-bold px-6 py-2.5 rounded-xl hover:bg-blue-700 text-sm">
<Button type="submit" variant="primary" size="md">
ثبت نظر جدید
</button>
</Button>
</form>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
@ -216,15 +223,21 @@ export default function CMS() {
<h4 className="font-bold text-gray-900">{t.vetName} <span className="text-blue-600">{t.clinicName}</span></h4>
<p className="text-xs text-gray-600 mt-2 font-medium">"{t.quote}"</p>
</div>
<button onClick={() => setDeleteTestimonialId(t.id)} className="text-red-500 text-xs font-bold bg-red-50 px-3 py-1.5 rounded-lg hover:bg-red-100">
<Button
variant="ghost"
size="xs"
onClick={() => setDeleteTestimonialId(t.id)}
className="text-red-500 hover:bg-red-50"
>
حذف
</button>
</Button>
</div>
))}
</div>
</div>
)}
<ConfirmModal
isOpen={!!deleteBannerId}
title="حذف بنر"

View File

@ -203,14 +203,23 @@ export default function Categories() {
</td>
<td className="py-4 px-6">
<div className="flex items-center gap-2">
<button onClick={() => openModal(cat)} className="p-2 text-blue-600 hover:bg-blue-50 rounded-lg transition-colors cursor-pointer">
<Edit2 className="w-4 h-4" />
</button>
<button onClick={() => setDeleteTargetId(cat.id)} className="p-2 text-red-600 hover:bg-red-50 rounded-lg transition-colors cursor-pointer">
<Trash2 className="w-4 h-4" />
</button>
<Button
variant="ghost"
size="xs"
startIcon={Edit2}
onClick={() => openModal(cat)}
className="text-blue-600 hover:bg-blue-50"
/>
<Button
variant="ghost"
size="xs"
startIcon={Trash2}
onClick={() => setDeleteTargetId(cat.id)}
className="text-red-600 hover:bg-red-50"
/>
</div>
</td>
</tr>
))
)}

View File

@ -218,17 +218,34 @@ export default function Coupons() {
{c.maxUses && <span className="text-gray-400 text-xs mr-1">/ {c.maxUses}</span>}
</td>
<td className="py-4 px-6">
<button onClick={() => handleToggle(c.id, c.isActive)} className={`px-3 py-1 text-xs font-bold rounded-lg transition-colors flex items-center gap-1 ${c.isActive ? 'bg-green-100 text-green-700 hover:bg-green-200' : 'bg-gray-100 text-gray-600 hover:bg-gray-200'}`}>
{c.isActive ? <CheckCircle2 className="w-3 h-3" /> : <XCircle className="w-3 h-3" />}
<Button
variant={c.isActive ? 'primary' : 'secondary'}
size="xs"
startIcon={c.isActive ? CheckCircle2 : XCircle}
onClick={() => handleToggle(c.id, c.isActive)}
>
{c.isActive ? 'فعال' : 'غیرفعال'}
</button>
</Button>
</td>
<td className="py-4 px-6">
<div className="flex items-center gap-2">
<button onClick={() => openModal(c)} className="p-2 text-blue-600 hover:bg-blue-50 rounded-lg transition-colors"><Edit2 className="w-4 h-4" /></button>
<button onClick={() => setDeleteTargetId(c.id)} className="p-2 text-red-600 hover:bg-red-50 rounded-lg transition-colors"><Trash2 className="w-4 h-4" /></button>
<Button
variant="ghost"
size="xs"
startIcon={Edit2}
onClick={() => openModal(c)}
className="text-blue-600 hover:bg-blue-50"
/>
<Button
variant="ghost"
size="xs"
startIcon={Trash2}
onClick={() => setDeleteTargetId(c.id)}
className="text-red-600 hover:bg-red-50"
/>
</div>
</td>
</tr>
))
)}
@ -456,9 +473,15 @@ function CouponModal({ formData, setFormData, onSave, onClose, isEditing }: Coup
<div className="space-y-4">
<div className="flex items-center justify-between border-b border-gray-100 pb-2">
<h4 className="font-bold text-gray-800">اهداف اختصاصی (Targets & Modifiers)</h4>
<button type="button" onClick={addTarget} className="text-xs font-bold text-purple-600 bg-purple-50 px-3 py-1.5 rounded-xl hover:bg-purple-100 transition-colors flex items-center gap-1 cursor-pointer">
<Plus className="w-4 h-4" /> افزودن هدف
</button>
<Button
type="button"
variant="outline"
size="xs"
startIcon={Plus}
onClick={addTarget}
>
افزودن هدف
</Button>
</div>
{formData.targets.length === 0 ? (
@ -499,13 +522,19 @@ function CouponModal({ formData, setFormData, onSave, onClose, isEditing }: Coup
<input type="number" placeholder="مقدار پایه" value={t.modifierValue} onChange={(e) => updateTarget(i, 'modifierValue', e.target.value)} dir="ltr" className="w-full px-2.5 py-2 rounded-xl border border-gray-200 text-xs outline-none focus:border-purple-500" />
</div>
<button type="button" onClick={() => removeTarget(i)} className="p-2.5 text-red-500 bg-red-50 hover:bg-red-100 rounded-xl transition-colors shrink-0 cursor-pointer">
<Trash2 className="w-4 h-4" />
</button>
<Button
type="button"
variant="ghost"
size="xs"
startIcon={Trash2}
onClick={() => removeTarget(i)}
className="text-red-500 hover:bg-red-50"
/>
</div>
))}
</div>
)}
</div>
<div className="flex items-center">

View File

@ -233,14 +233,23 @@ export default function IngredientsManager() {
</td>
<td className="py-4 px-6">
<div className="flex items-center gap-2">
<button onClick={() => openModal(item)} className="p-2 text-blue-600 hover:bg-blue-50 rounded-lg transition-colors">
<Edit2 className="w-4 h-4" />
</button>
<button onClick={() => setDeleteTargetId(item.id)} className="p-2 text-red-600 hover:bg-red-50 rounded-lg transition-colors">
<Trash2 className="w-4 h-4" />
</button>
<Button
variant="ghost"
size="xs"
startIcon={Edit2}
onClick={() => openModal(item)}
className="text-blue-600 hover:bg-blue-50"
/>
<Button
variant="ghost"
size="xs"
startIcon={Trash2}
onClick={() => setDeleteTargetId(item.id)}
className="text-red-600 hover:bg-red-50"
/>
</div>
</td>
</tr>
))
)}

View File

@ -282,14 +282,23 @@ export default function MenuManager() {
<span className="text-xs text-gray-400 font-mono">{child.href}</span>
</div>
<div className="flex items-center gap-1">
<button onClick={() => openModal(child)} className="p-1.5 text-blue-600 hover:bg-blue-50 rounded-lg">
<Edit2 className="w-3.5 h-3.5" />
</button>
<button onClick={() => setDeleteTargetId(child.id)} className="p-1.5 text-red-500 hover:bg-red-50 rounded-lg">
<Trash2 className="w-3.5 h-3.5" />
</button>
<Button
variant="ghost"
size="xs"
startIcon={Edit2}
onClick={() => openModal(child)}
className="text-blue-600 hover:bg-blue-50"
/>
<Button
variant="ghost"
size="xs"
startIcon={Trash2}
onClick={() => setDeleteTargetId(child.id)}
className="text-red-500 hover:bg-red-50"
/>
</div>
</div>
))}
</div>
)}

View File

@ -719,38 +719,41 @@ export default function Orders() {
</td>
<td className="py-4 px-6">
<div className="flex items-center justify-center gap-1.5">
<button
<Button
variant="ghost"
size="xs"
startIcon={Eye}
onClick={() => openOrderModal(order)}
className="text-purple-600 hover:bg-purple-50 p-2 rounded-xl transition-colors flex items-center gap-1 font-bold text-xs cursor-pointer"
title="مشاهده فاکتور و جزئیات کامل"
disabled={isProcessing}
className="text-purple-600 hover:bg-purple-50"
>
<Eye className="w-4 h-4" />
<span>جزئیات</span>
</button>
جزئیات
</Button>
<button
<Button
variant="ghost"
size="xs"
startIcon={Printer}
onClick={() => handlePrintInvoice(order)}
className="text-gray-600 hover:bg-gray-100 p-2 rounded-xl transition-colors cursor-pointer"
title="چاپ فوری فاکتور رسمی"
disabled={isProcessing}
>
<Printer className="w-4 h-4" />
</button>
className="text-gray-600 hover:bg-gray-100"
/>
{(order.status === 'cancelled' || order.status === 'pending_payment') && (
<button
<Button
variant="ghost"
size="xs"
startIcon={Undo2}
onClick={() => openOrderRefundModal(order)}
className="text-rose-600 hover:bg-rose-50 p-2 rounded-xl transition-colors flex items-center gap-1 font-bold text-xs cursor-pointer"
title="استرداد وجه به کاربر (کیف پول / شاپرک)"
disabled={isProcessing}
className="text-rose-600 hover:bg-rose-50"
>
<Undo2 className="w-4 h-4" />
<span>استرداد</span>
</button>
استرداد
</Button>
)}
</div>
</td>
</tr>
);
})

View File

@ -602,14 +602,23 @@ export default function Products() {
</td>
<td className="py-4 px-6">
<div className="flex items-center gap-2">
<button onClick={() => openModal(product)} className="p-2 text-blue-600 hover:bg-blue-50 rounded-lg transition-colors">
<Edit2 className="w-4 h-4" />
</button>
<button onClick={() => setDeleteTargetId(product.id)} className="p-2 text-red-600 hover:bg-red-50 rounded-lg transition-colors">
<Trash2 className="w-4 h-4" />
</button>
<Button
variant="ghost"
size="xs"
startIcon={Edit2}
onClick={() => openModal(product)}
className="text-blue-600 hover:bg-blue-50"
/>
<Button
variant="ghost"
size="xs"
startIcon={Trash2}
onClick={() => setDeleteTargetId(product.id)}
className="text-red-600 hover:bg-red-50"
/>
</div>
</td>
</tr>
))
)}

View File

@ -188,9 +188,22 @@ export default function Wiki() {
<td className="py-4 px-6 text-gray-500 text-sm max-w-xs truncate">{t.definition}</td>
<td className="py-4 px-6">
<div className="flex items-center gap-2">
<button onClick={() => openModal(t)} className="p-2 text-blue-600 hover:bg-blue-50 rounded-lg transition-colors cursor-pointer"><Edit2 className="w-4 h-4" /></button>
<button onClick={() => setDeleteTargetKey(t.key)} className="p-2 text-red-600 hover:bg-red-50 rounded-lg transition-colors cursor-pointer"><Trash2 className="w-4 h-4" /></button>
<Button
variant="ghost"
size="xs"
startIcon={Edit2}
onClick={() => openModal(t)}
className="text-blue-600 hover:bg-blue-50"
/>
<Button
variant="ghost"
size="xs"
startIcon={Trash2}
onClick={() => setDeleteTargetKey(t.key)}
className="text-red-600 hover:bg-red-50"
/>
</div>
</td>
</tr>
))