refactor: migrate from react-hot-toast to react-toastify and replace all emoji icons with Lucide React

- Replaced react-hot-toast with react-toastify (ToastContainer in providers.tsx)
- Removed @heroicons/react dependency
- Added lucide-react for consistent SVG icon system
- Migrated all 18 frontend pages from emoji icons to Lucide components
- Updated sidebar navigation, login/register, dashboard, apps, deploy,
  tickets, admin users/clusters/pools pages
- All emoji indicators (status, runtime, actions) now use proper SVG icons
- Build passes with zero TypeScript errors
This commit is contained in:
keyhan
2026-04-06 17:20:56 +03:30
parent 5d281b85d6
commit 3c3e0e48fa
18 changed files with 248 additions and 229 deletions
+11 -10
View File
@@ -3,8 +3,9 @@
import { useState } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import api from '@/lib/api';
import toast from 'react-hot-toast';
import { toast } from 'react-toastify';
import type { Cluster, ClusterPool } from '@/types';
import { Scale, BarChart3, RotateCw, CheckCircle, XCircle, Pencil, Clock, X } from 'lucide-react';
export default function AdminPoolsPage() {
const queryClient = useQueryClient();
@@ -107,7 +108,7 @@ export default function AdminPoolsPage() {
onClick={() => { showForm ? resetForm() : setShowForm(true); }}
className={showForm ? 'btn-ghost' : 'btn-primary'}
>
{showForm ? '✕ Cancel' : '+ Create Pool'}
{showForm ? <><X className="w-4 h-4 inline" /> Cancel</> : '+ Create Pool'}
</button>
</div>
@@ -135,8 +136,8 @@ export default function AdminPoolsPage() {
value={form.strategy}
onChange={(e) => setForm({ ...form, strategy: e.target.value as any })}
>
<option value="least-apps">📊 Least Apps deploy to cluster with fewest apps</option>
<option value="round-robin">🔄 Round Robin rotate across clusters evenly</option>
<option value="least-apps">Least Apps deploy to cluster with fewest apps</option>
<option value="round-robin">Round Robin rotate across clusters evenly</option>
</select>
</div>
</div>
@@ -223,7 +224,7 @@ export default function AdminPoolsPage() {
className="btn-primary disabled:opacity-50"
>
{createMutation.isPending || updateMutation.isPending
? '⏳ Saving...'
? <><Clock className="w-4 h-4 inline animate-spin" /> Saving...</>
: editingPool
? 'Update Pool'
: 'Create Pool'}
@@ -254,7 +255,7 @@ export default function AdminPoolsPage() {
</div>
) : pools.length === 0 ? (
<div className="card text-center py-16">
<div className="text-5xl mb-4"></div>
<Scale className="w-12 h-12 mx-auto text-gray-300 mb-4" />
<p className="text-gray-600 font-medium">No cluster pools created yet</p>
<p className="text-sm text-gray-400 mt-1">
Create a pool to enable load-balanced deployment across multiple clusters
@@ -274,8 +275,8 @@ export default function AdminPoolsPage() {
<span className={`badge ${pool.isActive ? 'badge-green' : 'badge-gray'}`}>
{pool.isActive ? 'Active' : 'Inactive'}
</span>
<span className="badge badge-purple">
{pool.strategy === 'least-apps' ? '📊 Least Apps' : '🔄 Round Robin'}
<span className="badge badge-purple flex items-center gap-1">
{pool.strategy === 'least-apps' ? <><BarChart3 className="w-3 h-3" /> Least Apps</> : <><RotateCw className="w-3 h-3" /> Round Robin</>}
</span>
</div>
{pool.description && (
@@ -293,7 +294,7 @@ export default function AdminPoolsPage() {
: 'bg-red-50 text-red-700 border border-red-200'
}`}
>
<span>{cluster.status === 'active' ? '✅' : '❌'}</span>
<span>{cluster.status === 'active' ? <CheckCircle className="w-3 h-3" /> : <XCircle className="w-3 h-3" />}</span>
<span>{cluster.name}</span>
<span className="text-gray-400">
({cluster.provider || 'N/A'} · {cluster.region || 'N/A'})
@@ -314,7 +315,7 @@ export default function AdminPoolsPage() {
onClick={() => startEdit(pool)}
className="btn-ghost text-sm"
>
Edit
<Pencil className="w-3 h-3 inline" /> Edit
</button>
<button
onClick={() => {