tinovisas/frontend/src/app/countries/page.tsx

141 lines
6.7 KiB
TypeScript

"use client";
import { useState, useEffect } from "react";
import { useRouter } from "next/navigation";
import { useAuth } from "../../hooks/useAuth";
import { useCountries } from "../../hooks/useCountries";
import Sidebar from "../../components/Sidebar";
import Header from "../../components/Header";
import CountryCard from "../../components/CountryCard";
import { countryAPI } from "../../lib/api";
import { toast } from "react-toastify";
import { Plus, X, Globe } from "lucide-react";
export default function CountriesPage() {
const router = useRouter();
const { user, loading, isAdmin } = useAuth();
const { countries, refetch } = useCountries();
const [showModal, setShowModal] = useState(false);
const [form, setForm] = useState({ name: "", code: "", flag_emoji: "", vfs_url: "", processing_time: "", visa_types: "", requirements: "" });
useEffect(() => { if (!loading && !user) router.push("/login"); }, [user, loading, router]);
const handleCreate = async (e: React.FormEvent) => {
e.preventDefault();
try {
const visa_types = form.visa_types.split(",").map((s) => s.trim()).filter(Boolean);
const requirements = form.requirements.split("\n").map((s) => s.trim()).filter(Boolean);
await countryAPI.create({ ...form, visa_types, requirements });
toast.success("Country created");
setShowModal(false);
setForm({ name: "", code: "", flag_emoji: "", vfs_url: "", processing_time: "", visa_types: "", requirements: "" });
refetch();
} catch (error: any) {
toast.error(error.response?.data?.message || "Failed to create country");
}
};
const handleDelete = async (id: string) => {
if (!confirm("Delete this country?")) return;
try {
await countryAPI.delete(id);
toast.success("Country deleted");
refetch();
} catch (error: any) {
toast.error(error.response?.data?.message || "Failed to delete");
}
};
if (loading || !user) return null;
return (
<div className="flex min-h-screen bg-dark-900">
<Sidebar />
<div className="flex-1 flex flex-col">
<Header />
<main className="flex-1 p-6 overflow-y-auto">
<div className="flex items-center justify-between mb-6">
<div>
<h1 className="text-2xl font-bold text-white">Countries</h1>
<p className="text-gray-500">Manage visa destinations</p>
</div>
{isAdmin && (
<button onClick={() => setShowModal(true)} className="btn-primary flex items-center gap-2">
<Plus className="w-4 h-4" />
Add Country
</button>
)}
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
{countries.map((country) => (
<div key={country.id} className="relative group">
<CountryCard country={country} />
{isAdmin && (
<button
onClick={() => handleDelete(country.id)}
className="absolute top-2 right-2 opacity-0 group-hover:opacity-100 p-1.5 bg-dark-800 rounded-lg text-gray-400 hover:text-accent-red transition-all"
>
<X className="w-4 h-4" />
</button>
)}
</div>
))}
</div>
{showModal && (
<div className="fixed inset-0 bg-black/60 flex items-center justify-center z-50 p-4">
<div className="card w-full max-w-lg">
<div className="flex items-center justify-between mb-6">
<h2 className="text-xl font-bold text-white flex items-center gap-2">
<Globe className="w-5 h-5 text-accent-blue" />
Add Country
</h2>
<button onClick={() => setShowModal(false)} className="text-gray-400 hover:text-white"><X className="w-5 h-5" /></button>
</div>
<form onSubmit={handleCreate} className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<div>
<label className="label">Name *</label>
<input required value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })} className="input w-full" placeholder="France" />
</div>
<div>
<label className="label">Code *</label>
<input required value={form.code} onChange={(e) => setForm({ ...form, code: e.target.value.toUpperCase() })} className="input w-full" placeholder="FR" />
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="label">Flag Emoji</label>
<input value={form.flag_emoji} onChange={(e) => setForm({ ...form, flag_emoji: e.target.value })} className="input w-full" placeholder="🇫🇷" />
</div>
<div>
<label className="label">Processing Time</label>
<input value={form.processing_time} onChange={(e) => setForm({ ...form, processing_time: e.target.value })} className="input w-full" placeholder="15-20 days" />
</div>
</div>
<div>
<label className="label">VFS URL</label>
<input type="url" value={form.vfs_url} onChange={(e) => setForm({ ...form, vfs_url: e.target.value })} className="input w-full" placeholder="https://..." />
</div>
<div>
<label className="label">Visa Types (comma separated)</label>
<input value={form.visa_types} onChange={(e) => setForm({ ...form, visa_types: e.target.value })} className="input w-full" placeholder="Tourist, Business, Student" />
</div>
<div>
<label className="label">Requirements (one per line)</label>
<textarea value={form.requirements} onChange={(e) => setForm({ ...form, requirements: e.target.value })} className="input w-full h-24 resize-none" placeholder="Passport valid 6 months&#10;2 photos&#10;Bank statement" />
</div>
<div className="flex justify-end gap-3 pt-4">
<button type="button" onClick={() => setShowModal(false)} className="px-4 py-2 text-gray-400 hover:text-white">Cancel</button>
<button type="submit" className="btn-primary">Create Country</button>
</div>
</form>
</div>
</div>
)}
</main>
</div>
</div>
);
}