Compare commits

...

2 Commits

Author SHA1 Message Date
mark a6923e8c3c fix navigation 2025-05-28 09:52:10 +08:00
mark 4d7a9492bc fix: update placeholder and slide image paths to use assets directory 2025-05-28 08:48:41 +08:00
18 changed files with 35 additions and 63 deletions

7
.env
View File

@ -1,6 +1 @@
# .env VITE_API_URL=http://127.0.0.1:8000
VITE_API_URL=http://localhost:8000
# You can also create environment-specific files:
# .env.development
# .env.production

View File

Before

Width:  |  Height:  |  Size: 1.8 MiB

After

Width:  |  Height:  |  Size: 1.8 MiB

View File

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 1.5 MiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -108,16 +108,9 @@ export default function UserCreate() {
<main className="p-4 md:p-6"> <main className="p-4 md:p-6">
<div className="mb-6"> <div className="mb-6">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Button
variant="ghost"
size="icon"
onClick={() => navigate("/admin/dashboard")}
className="hover:bg-gray-800 text-gray-400 hover:text-white">
<ArrowLeft className="size-5" />
</Button>
<h1 className="text-2xl md:text-3xl font-serif font-bold text-white">Account Settings</h1> <h1 className="text-2xl md:text-3xl font-serif font-bold text-white">Account Settings</h1>
</div> </div>
<p className="text-gray-400 mt-2 ml-10">Manage your profile and security preferences</p> <p className="text-gray-400 mt-2">Manage your profile and security preferences</p>
</div> </div>
{/* Current user information card */} {/* Current user information card */}

View File

@ -144,7 +144,7 @@ const PhotosStep: React.FC<PhotosStepProps> = ({
<Card key={`new-${index}`} className="overflow-hidden"> <Card key={`new-${index}`} className="overflow-hidden">
<div className="relative"> <div className="relative">
<img <img
src={photoPreviews[index] || `${import.meta.env.BASE_URL}placeholder.svg`} src={photoPreviews[index] || `${import.meta.env.BASE_URL}assets/placeholder.svg`}
alt={`Preview ${index}`} alt={`Preview ${index}`}
className="w-full h-48 object-cover" className="w-full h-48 object-cover"
/> />

View File

@ -70,16 +70,9 @@ export default function UserCreate() {
<main className="p-4 md:p-6"> <main className="p-4 md:p-6">
<div className="mb-6"> <div className="mb-6">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Button
variant="ghost"
size="icon"
onClick={() => navigate("/admin/settings")}
className="hover:bg-gray-800 text-gray-400 hover:text-white">
<ArrowLeft className="size-5" />
</Button>
<h1 className="text-2xl md:text-3xl font-serif font-bold text-white">Create New User</h1> <h1 className="text-2xl md:text-3xl font-serif font-bold text-white">Create New User</h1>
</div> </div>
<p className="text-gray-400 mt-2 ml-10">Add a new administrator to the system</p> <p className="text-gray-400 mt-2">Add a new administrator to the system</p>
</div> </div>
<div className="max-w-10xl mx-auto"> <div className="max-w-10xl mx-auto">

View File

@ -41,25 +41,13 @@ export default function Home() {
} }
fetchData() fetchData()
}, []) }, [])
const backgroundImages = [ const backgroundImages = [
{ { src: `${import.meta.env.BASE_URL}assets/slide1.avif`, alt: "Italian countryside landscape" },
src: `${import.meta.env.BASE_URL}slide1.avif`, { src: `${import.meta.env.BASE_URL}assets/slide2.avif`, alt: "Vintage Italian architecture" },
alt: "Italian countryside landscape", { src: `${import.meta.env.BASE_URL}assets/slide3.avif`, alt: "Italian coastal town" },
}, { src: `${import.meta.env.BASE_URL}assets/slide4.avif`, alt: "Italian countryside with vineyards" },
{ ];
src: `${import.meta.env.BASE_URL}slide2.avif`,
alt: "Vintage Italian architecture",
},
{
src: `${import.meta.env.BASE_URL}slide3.avif`,
alt: "Italian coastal town",
},
{
src: `${import.meta.env.BASE_URL}slide4.avif`,
alt: "Italian countryside with vineyards",
},
]
const galleryImages = [ const galleryImages = [
{ {
@ -146,7 +134,7 @@ export default function Home() {
className={`absolute inset-0 transition-opacity duration-1000 ${index === currentSlide ? "opacity-100" : "opacity-0" className={`absolute inset-0 transition-opacity duration-1000 ${index === currentSlide ? "opacity-100" : "opacity-0"
}`} }`}
> >
<img src={image.src || `${import.meta.env.BASE_URL}placeholder.svg`} alt={image.alt} className="w-full h-full object-cover" /> <img src={image.src || `${import.meta.env.BASE_URL}assets/placeholder.svg`} alt={image.alt} className="w-full h-full object-cover" />
<div className="absolute inset-0 bg-black/60" /> <div className="absolute inset-0 bg-black/60" />
</div> </div>
))} ))}
@ -352,7 +340,7 @@ export default function Home() {
<div className="p-1"> <div className="p-1">
<div className="overflow-hidden rounded-xl aspect-square"> <div className="overflow-hidden rounded-xl aspect-square">
<img <img
src={image.src || `${import.meta.env.BASE_URL}placeholder.svg`} src={image.src || `${import.meta.env.BASE_URL}assets/placeholder.svg`}
alt={image.alt} alt={image.alt}
className="object-cover w-full h-full hover:scale-105 transition-transform duration-300" className="object-cover w-full h-full hover:scale-105 transition-transform duration-300"
/> />
@ -433,22 +421,22 @@ export default function Home() {
> >
Search Database Search Database
</Link> </Link>
<Link to="/contribute" className="block text-sm text-gray-300 hover:text-[#E8DCCA] transition-colors"> <Link to="#" className="block text-sm text-gray-300 hover:text-[#E8DCCA] transition-colors">
Contribute a Story Contribute a Story
</Link> </Link>
<Link to="/gallery" className="block text-sm text-gray-300 hover:text-[#E8DCCA] transition-colors"> <Link to="/" className="block text-sm text-gray-300 hover:text-[#E8DCCA] transition-colors">
Photo Gallery Photo Gallery
</Link> </Link>
<Link <Link
to="/research-help" to="/"
className="block text-sm text-gray-300 hover:text-[#E8DCCA] transition-colors" className="block text-sm text-gray-300 hover:text-[#E8DCCA] transition-colors"
> >
Research Help Research Help
</Link> </Link>
<Link to="/volunteer" className="block text-sm text-gray-300 hover:text-[#E8DCCA] transition-colors"> <Link to="/" className="block text-sm text-gray-300 hover:text-[#E8DCCA] transition-colors">
Volunteer Volunteer
</Link> </Link>
<Link to="/donations" className="block text-sm text-gray-300 hover:text-[#E8DCCA] transition-colors"> <Link to="/" className="block text-sm text-gray-300 hover:text-[#E8DCCA] transition-colors">
Support Us Support Us
</Link> </Link>
</nav> </nav>
@ -458,22 +446,22 @@ export default function Home() {
<div className="space-y-4"> <div className="space-y-4">
<h3 className="text-lg font-bold font-serif text-[#E8DCCA]">Resources</h3> <h3 className="text-lg font-bold font-serif text-[#E8DCCA]">Resources</h3>
<nav className="space-y-2"> <nav className="space-y-2">
<Link to="/faq" className="block text-sm text-gray-300 hover:text-[#E8DCCA] transition-colors"> <Link to="/" className="block text-sm text-gray-300 hover:text-[#E8DCCA] transition-colors">
FAQ FAQ
</Link> </Link>
<Link <Link
to="/research-guides" to="/"
className="block text-sm text-gray-300 hover:text-[#E8DCCA] transition-colors" className="block text-sm text-gray-300 hover:text-[#E8DCCA] transition-colors"
> >
Research Guides Research Guides
</Link> </Link>
<Link <Link
to="/historical-timeline" to="/"
className="block text-sm text-gray-300 hover:text-[#E8DCCA] transition-colors" className="block text-sm text-gray-300 hover:text-[#E8DCCA] transition-colors"
> >
Historical Timeline Historical Timeline
</Link> </Link>
<Link to="/partnerships" className="block text-sm text-gray-300 hover:text-[#E8DCCA] transition-colors"> <Link to="/" className="block text-sm text-gray-300 hover:text-[#E8DCCA] transition-colors">
Partnerships Partnerships
</Link> </Link>
</nav> </nav>
@ -568,7 +556,7 @@ export default function Home() {
<a href="#" className="text-sm text-gray-300 hover:text-[#E8DCCA] transition-colors"> <a href="#" className="text-sm text-gray-300 hover:text-[#E8DCCA] transition-colors">
Accessibility Accessibility
</a> </a>
<a href="#" className="text-sm text-gray-300 hover:text-[#E8DCCA] transition-colors"> <a href="/login" className="text-sm text-gray-300 hover:text-[#E8DCCA] transition-colors">
Admin Admin
</a> </a>
</nav> </nav>

View File

@ -71,12 +71,12 @@ export default function MigrantProfile() {
? profilePhoto.file_path.startsWith('http') ? profilePhoto.file_path.startsWith('http')
? profilePhoto.file_path ? profilePhoto.file_path
: `${API_BASE_URL}${profilePhoto.file_path}` : `${API_BASE_URL}${profilePhoto.file_path}`
: `${import.meta.env.BASE_URL}placeholder.svg?height=600&width=450`} : `${import.meta.env.BASE_URL}assets/placeholder.svg?height=600&width=450`}
alt={`${migrant.full_name || 'Migrant photo'}`} alt={`${migrant.full_name || 'Migrant photo'}`}
className="aspect-[3/4] object-cover w-full" className="aspect-[3/4] object-cover w-full"
onError={(e) => { onError={(e) => {
// Handle image loading errors by setting a fallback // Handle image loading errors by setting a fallback
e.currentTarget.src = `${import.meta.env.BASE_URL}placeholder.svg?height=600&width=450`; e.currentTarget.src = `${import.meta.env.BASE_URL}assets/placeholder.svg?height=600&width=450`;
}} }}
/> />
</div> </div>
@ -189,12 +189,12 @@ export default function MigrantProfile() {
? photo.file_path.startsWith('http') ? photo.file_path.startsWith('http')
? photo.file_path ? photo.file_path
: `${API_BASE_URL}${photo.file_path}` : `${API_BASE_URL}${photo.file_path}`
: `${import.meta.env.BASE_URL}placeholder.svg?height=400&width=600`} : `${import.meta.env.BASE_URL}assets/placeholder.svg?height=400&width=600`}
alt={photo.caption || "Migrant photo"} alt={photo.caption || "Migrant photo"}
className="aspect-video object-cover w-full" className="aspect-video object-cover w-full"
onError={(e) => { onError={(e) => {
// Handle image loading errors // Handle image loading errors
e.currentTarget.src = `${import.meta.env.BASE_URL}placeholder.svg?height=400&width=600`; e.currentTarget.src = `${import.meta.env.BASE_URL}assets/placeholder.svg?height=400&width=600`;
}} }}
/> />
</div> </div>

View File

@ -75,7 +75,7 @@ export default function SearchResults() {
src={ src={
migrant.profilePhoto migrant.profilePhoto
? `${API_BASE_URL}${migrant.profilePhoto.file_path}` ? `${API_BASE_URL}${migrant.profilePhoto.file_path}`
: `${import.meta.env.BASE_URL}placeholder.svg?height=300&width=300` : `${import.meta.env.BASE_URL}assets/placeholder.svg?height=300&width=300`
} }
alt={migrant.full_name || "Unknown"} alt={migrant.full_name || "Unknown"}
className="w-full h-full object-cover object-center transition-transform hover:scale-105" className="w-full h-full object-cover object-center transition-transform hover:scale-105"

View File

@ -255,7 +255,7 @@ export default function ProfileSettings() {
<div className="h-24 w-24 rounded-full bg-gray-200 overflow-hidden"> <div className="h-24 w-24 rounded-full bg-gray-200 overflow-hidden">
{profile.avatar ? ( {profile.avatar ? (
<img <img
src={profile.avatar || `${import.meta.env.BASE_URL}placeholder.svg`} src={profile.avatar || `${import.meta.env.BASE_URL}assets/placeholder.svg`}
alt="Profile" alt="Profile"
className="h-full w-full object-cover" className="h-full w-full object-cover"
/> />

View File

@ -32,7 +32,7 @@ export default function AnimatedImage({
transition={{ duration: 0.5 }} transition={{ duration: 0.5 }}
> >
<img <img
src={src || `${import.meta.env.BASE_URL}placeholder.svg`} src={src || `${import.meta.env.BASE_URL}assets/placeholder.svg`}
alt={alt} alt={alt}
width={!fill ? width : undefined} width={!fill ? width : undefined}
height={!fill ? height : undefined} height={!fill ? height : undefined}

View File

@ -37,6 +37,10 @@ class ApiService {
// --- AUTH --- // --- AUTH ---
async login(params: { email: string; password: string }) { async login(params: { email: string; password: string }) {
// First get CSRF cookie
await this.api.get("/sanctum/csrf-cookie");
// Then login
return this.api.post("/api/login", params).then((res) => { return this.api.post("/api/login", params).then((res) => {
console.log("Token:", res.data.token); console.log("Token:", res.data.token);
localStorage.setItem("token", res.data.token); localStorage.setItem("token", res.data.token);
@ -46,6 +50,7 @@ class ApiService {
} }
async register(params: { name: string; email: string; password: string }) { async register(params: { name: string; email: string; password: string }) {
return this.api.post("/api/register", params).then((res) => res.data); return this.api.post("/api/register", params).then((res) => res.data);
} }

View File

@ -3,8 +3,8 @@ import tailwindcss from "@tailwindcss/vite";
import react from "@vitejs/plugin-react"; import react from "@vitejs/plugin-react";
import { defineConfig } from "vite"; import { defineConfig } from "vite";
// https://vite.dev/config/
export default defineConfig({ export default defineConfig({
base: '/',
plugins: [react(), tailwindcss()], plugins: [react(), tailwindcss()],
resolve: { resolve: {
alias: { alias: {
@ -16,8 +16,6 @@ export default defineConfig({
"/api": { "/api": {
target: "http://localhost:8000", target: "http://localhost:8000",
changeOrigin: true, changeOrigin: true,
// Don't rewrite the path since Laravel expects /api prefix
// rewrite: (path) => path.replace(/^\/api/, ""),
}, },
}, },
}, },