Sets up the foundational structure for the CAR Auto Center application using Vite and React. Includes project dependencies, basic HTML structure, TypeScript configuration, and initial README content. This commit establishes the project's build tool, core libraries, and essential configuration files.
104 lines
4.3 KiB
TypeScript
104 lines
4.3 KiB
TypeScript
import React, { useEffect } from 'react';
|
|
import { Routes, Route, Navigate, Outlet } from 'react-router-dom';
|
|
import { Header } from './components/Header';
|
|
import { Login } from './components/Admin/Login';
|
|
import { Dashboard } from './components/Admin/Dashboard';
|
|
import { useData } from './contexts/DataContext';
|
|
import { Footer } from './components/AppContent';
|
|
|
|
// Páginas
|
|
import {
|
|
HomePage,
|
|
AboutPage,
|
|
ServicesPage,
|
|
PromotionsPage,
|
|
BlogPage,
|
|
BlogPostPage,
|
|
ContactPage
|
|
} from './components/Pages';
|
|
|
|
// Layout do site público com Tema Dinâmico e Estrutura Fixa
|
|
const PublicLayout = () => {
|
|
const { data, getWhatsAppLink } = useData();
|
|
|
|
// Aplica cor primária dinamicamente
|
|
useEffect(() => {
|
|
document.documentElement.style.setProperty('--primary-color', data.settings.primaryColor);
|
|
|
|
// Atualiza Favicon
|
|
if (data.settings.faviconUrl) {
|
|
const link = document.querySelector("link[rel~='icon']") as HTMLLinkElement;
|
|
if (link) {
|
|
link.href = data.settings.faviconUrl;
|
|
} else {
|
|
const newLink = document.createElement('link');
|
|
newLink.rel = 'icon';
|
|
newLink.href = data.settings.faviconUrl;
|
|
document.head.appendChild(newLink);
|
|
}
|
|
}
|
|
|
|
// Atualiza Título
|
|
document.title = data.settings.siteName;
|
|
}, [data.settings]);
|
|
|
|
return (
|
|
<div className="bg-zinc-950 min-h-screen font-sans text-gray-100 selection:bg-primary selection:text-white flex flex-col">
|
|
<Header />
|
|
<main className="flex-1">
|
|
<Outlet />
|
|
</main>
|
|
<Footer />
|
|
<a
|
|
href={getWhatsAppLink("Olá! Gostaria de mais informações.")}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="fixed bottom-8 right-8 z-50 bg-green-500 text-white p-4 rounded-full shadow-lg hover:scale-110 transition-transform hover:bg-green-600 flex items-center justify-center"
|
|
aria-label="Contato WhatsApp"
|
|
>
|
|
<svg viewBox="0 0 24 24" fill="white" width="32" height="32">
|
|
<path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z"/>
|
|
</svg>
|
|
</a>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
// Proteção de rota simples
|
|
const ProtectedRoute: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
|
const isAuth = localStorage.getItem('admin_auth') === 'true';
|
|
return isAuth ? <>{children}</> : <Navigate to="/admin" replace />;
|
|
};
|
|
|
|
function App() {
|
|
return (
|
|
<Routes>
|
|
{/* Rotas Públicas */}
|
|
<Route path="/" element={<PublicLayout />}>
|
|
<Route index element={<HomePage />} />
|
|
<Route path="sobre" element={<AboutPage />} />
|
|
<Route path="servicos" element={<ServicesPage />} />
|
|
<Route path="promocoes" element={<PromotionsPage />} />
|
|
<Route path="blog" element={<BlogPage />} />
|
|
<Route path="blog/:id" element={<BlogPostPage />} />
|
|
<Route path="contato" element={<ContactPage />} />
|
|
</Route>
|
|
|
|
{/* Rotas Administrativas */}
|
|
<Route path="/admin" element={<Login />} />
|
|
<Route
|
|
path="/admin/dashboard"
|
|
element={
|
|
<ProtectedRoute>
|
|
<Dashboard />
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
|
|
{/* Rota Catch-all para redirecionar para Home se nada corresponder */}
|
|
<Route path="*" element={<Navigate to="/" replace />} />
|
|
</Routes>
|
|
);
|
|
}
|
|
|
|
export default App; |