feat: add admin dashboard and core API routes with Docker configuration
This commit is contained in:
@@ -5,6 +5,7 @@ import React from 'react';
|
||||
import Link from 'next/link';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { Facebook, Twitter, Instagram, Linkedin } from 'lucide-react';
|
||||
import { safeUrl } from '@/lib/utils';
|
||||
|
||||
interface FooterProps {
|
||||
settings?: any;
|
||||
@@ -49,7 +50,7 @@ const Footer = ({ settings }: FooterProps) => {
|
||||
{socialLinks.map((social, index) => (
|
||||
<a
|
||||
key={index}
|
||||
href={social.url}
|
||||
href={safeUrl(social.url)}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="p-2 rounded-full border border-gray-800 text-gray-400 hover:text-brand-500 hover:border-brand-500/50 hover:bg-white/5 transition-all"
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { Search, MapPin, ChevronLeft, ChevronRight, ArrowRight } from 'lucide-react';
|
||||
import { safeUrl } from '@/lib/utils';
|
||||
|
||||
interface HomeSlide {
|
||||
id: string;
|
||||
@@ -130,7 +131,7 @@ const HomeSlider = ({ slides, onSearch }: Props) => {
|
||||
|
||||
<div className="flex flex-wrap gap-4 items-center">
|
||||
<Link
|
||||
href={slide.type === 'BUSINESS' ? `/annuaire/${slide.business?.id}` : (slide.linkUrl || '#')}
|
||||
href={slide.type === 'BUSINESS' ? `/annuaire/${slide.business?.id}` : safeUrl(slide.linkUrl)}
|
||||
className="inline-flex items-center gap-2 bg-brand-600 text-white px-8 py-4 rounded-lg font-bold hover:bg-brand-700 transition-all shadow-lg shadow-brand-600/20 hover:scale-105"
|
||||
>
|
||||
{slide.type === 'BUSINESS' ? 'Voir la fiche' : 'En savoir plus'}
|
||||
|
||||
@@ -22,9 +22,27 @@ export function UserProvider({ children }: { children: ReactNode }) {
|
||||
React.useEffect(() => {
|
||||
const savedUser = localStorage.getItem('afro_user');
|
||||
if (savedUser) {
|
||||
setUser(JSON.parse(savedUser));
|
||||
try {
|
||||
setUser(JSON.parse(savedUser));
|
||||
} catch {
|
||||
localStorage.removeItem('afro_user');
|
||||
}
|
||||
}
|
||||
|
||||
// Synchronize user session from signed HttpOnly cookie
|
||||
fetch('/api/users/me')
|
||||
.then(async res => {
|
||||
if (res.ok) {
|
||||
const freshUser = await res.json();
|
||||
setUser(freshUser);
|
||||
localStorage.setItem('afro_user', JSON.stringify(freshUser));
|
||||
} else if (res.status === 401) {
|
||||
setUser(null);
|
||||
localStorage.removeItem('afro_user');
|
||||
}
|
||||
})
|
||||
.catch(err => console.error('Error verifying session:', err));
|
||||
|
||||
// Fetch settings
|
||||
fetch('/api/settings')
|
||||
.then(res => res.json())
|
||||
@@ -47,6 +65,9 @@ export function UserProvider({ children }: { children: ReactNode }) {
|
||||
const logout = () => {
|
||||
setUser(null);
|
||||
localStorage.removeItem('afro_user');
|
||||
fetch('/api/auth/logout', { method: 'POST' }).catch(err =>
|
||||
console.error('Error logging out:', err)
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user