Features added: - Database schema for pages and media files with content types (Rich Text, HTML, Markdown) - Admin API routes for full page CRUD operations - Image upload functionality with file management - Rich text editor using TinyMCE with image insertion - Admin interface for creating/editing pages with SEO options - Dynamic navigation and footer integration - Public page display routes with proper SEO metadata - Support for featured images and content excerpts Admin features: - Create/edit/delete pages with rich content editor - Upload and manage images through media library - Configure pages to appear in navigation or footer - Set page status (Draft, Published, Archived) - SEO title and description management - Real-time preview of content changes 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
167 lines
5.8 KiB
TypeScript
167 lines
5.8 KiB
TypeScript
'use client'
|
|
import { useState, useEffect } from 'react'
|
|
import {
|
|
Paper,
|
|
Container,
|
|
Box,
|
|
Typography,
|
|
Button,
|
|
Divider,
|
|
IconButton,
|
|
Chip,
|
|
} from '@mui/material'
|
|
import {
|
|
Facebook,
|
|
Twitter,
|
|
Instagram,
|
|
YouTube,
|
|
} from '@mui/icons-material'
|
|
import { useRouter } from 'next/navigation'
|
|
import { useTranslations, useLocale } from 'next-intl'
|
|
|
|
interface DynamicPage {
|
|
id: string
|
|
title: string
|
|
slug: string
|
|
showInFooter: boolean
|
|
footerOrder?: number
|
|
}
|
|
|
|
export function Footer() {
|
|
const [dynamicPages, setDynamicPages] = useState<DynamicPage[]>([])
|
|
const router = useRouter()
|
|
const t = useTranslations('home')
|
|
const tSeo = useTranslations('seo')
|
|
const locale = useLocale()
|
|
|
|
useEffect(() => {
|
|
fetchDynamicPages()
|
|
}, [])
|
|
|
|
const fetchDynamicPages = async () => {
|
|
try {
|
|
const response = await fetch('/api/pages?location=footer')
|
|
if (response.ok) {
|
|
const data = await response.json()
|
|
setDynamicPages(data.data || [])
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to fetch dynamic pages:', error)
|
|
}
|
|
}
|
|
|
|
const getCurrentYear = () => {
|
|
return new Date().getFullYear()
|
|
}
|
|
|
|
return (
|
|
<Paper component="footer" sx={{ bgcolor: 'grey.900', color: 'white', py: 6 }}>
|
|
<Container maxWidth="lg">
|
|
<Box sx={{ display: 'flex', gap: 6, flexWrap: 'wrap', justifyContent: 'space-between', mb: 4 }}>
|
|
{/* Brand */}
|
|
<Box sx={{ flex: { xs: '1 1 100%', md: '1 1 auto' } }}>
|
|
<Typography variant="h5" sx={{ mb: 2, fontWeight: 600 }}>
|
|
{t('footer.brand')}
|
|
</Typography>
|
|
<Typography variant="body2" color="grey.400" sx={{ maxWidth: 300 }}>
|
|
{tSeo('footer')}
|
|
</Typography>
|
|
</Box>
|
|
|
|
{/* Quick Links */}
|
|
<Box sx={{ flex: { xs: '1 1 50%', md: '1 1 auto' } }}>
|
|
<Typography variant="h6" sx={{ mb: 2 }}>
|
|
{t('footer.quickLinks.title')}
|
|
</Typography>
|
|
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
|
|
<Button color="inherit" sx={{ justifyContent: 'flex-start', p: 0 }}>
|
|
{t('footer.quickLinks.about')}
|
|
</Button>
|
|
<Button color="inherit" sx={{ justifyContent: 'flex-start', p: 0 }}>
|
|
{t('footer.quickLinks.blog')}
|
|
</Button>
|
|
<Button
|
|
color="inherit"
|
|
sx={{ justifyContent: 'flex-start', p: 0 }}
|
|
onClick={() => router.push(`/${locale}/contact`)}
|
|
>
|
|
{t('footer.quickLinks.contact')}
|
|
</Button>
|
|
<Button color="inherit" sx={{ justifyContent: 'flex-start', p: 0 }}>
|
|
{t('footer.quickLinks.support')}
|
|
</Button>
|
|
<Button color="inherit" sx={{ justifyContent: 'flex-start', p: 0 }}>
|
|
{t('footer.quickLinks.api')}
|
|
</Button>
|
|
{dynamicPages.map((page) => (
|
|
<Button
|
|
key={page.id}
|
|
color="inherit"
|
|
sx={{ justifyContent: 'flex-start', p: 0 }}
|
|
onClick={() => router.push(`/${locale}/pages/${page.slug}`)}
|
|
>
|
|
{page.title}
|
|
</Button>
|
|
))}
|
|
</Box>
|
|
</Box>
|
|
|
|
{/* Legal */}
|
|
<Box sx={{ flex: { xs: '1 1 50%', md: '1 1 auto' } }}>
|
|
<Typography variant="h6" sx={{ mb: 2 }}>
|
|
{t('footer.legal.title')}
|
|
</Typography>
|
|
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
|
|
<Button color="inherit" sx={{ justifyContent: 'flex-start', p: 0 }}>
|
|
{t('footer.legal.terms')}
|
|
</Button>
|
|
<Button color="inherit" sx={{ justifyContent: 'flex-start', p: 0 }}>
|
|
{t('footer.legal.privacy')}
|
|
</Button>
|
|
<Button color="inherit" sx={{ justifyContent: 'flex-start', p: 0 }}>
|
|
{t('footer.legal.cookies')}
|
|
</Button>
|
|
<Button color="inherit" sx={{ justifyContent: 'flex-start', p: 0 }}>
|
|
{t('footer.legal.gdpr')}
|
|
</Button>
|
|
</Box>
|
|
</Box>
|
|
|
|
{/* Social */}
|
|
<Box sx={{ flex: { xs: '1 1 100%', md: '1 1 auto' } }}>
|
|
<Typography variant="h6" sx={{ mb: 2 }}>
|
|
{t('footer.social.title')}
|
|
</Typography>
|
|
<Box sx={{ display: 'flex', gap: 1 }}>
|
|
<IconButton color="inherit" size="small">
|
|
<Facebook />
|
|
</IconButton>
|
|
<IconButton color="inherit" size="small">
|
|
<Twitter />
|
|
</IconButton>
|
|
<IconButton color="inherit" size="small">
|
|
<Instagram />
|
|
</IconButton>
|
|
<IconButton color="inherit" size="small">
|
|
<YouTube />
|
|
</IconButton>
|
|
</Box>
|
|
</Box>
|
|
</Box>
|
|
|
|
<Divider sx={{ bgcolor: 'grey.700', mb: 3 }} />
|
|
|
|
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 2 }}>
|
|
<Typography variant="body2" color="grey.400">
|
|
© {getCurrentYear()} Biblical Guide - {locale === 'ro' ? 'Făcut cu ❤️ și 🙏' : 'Made with ❤️ and 🙏'}
|
|
</Typography>
|
|
<Box sx={{ display: 'flex', gap: 1, flexWrap: 'wrap' }}>
|
|
<Chip label="🇷🇴 Română" size="small" variant="outlined" sx={{ color: 'white', borderColor: 'grey.600' }} />
|
|
<Chip label="🇺🇸 English" size="small" variant="outlined" sx={{ color: 'white', borderColor: 'grey.600' }} />
|
|
<Chip label="+20 more" size="small" variant="outlined" sx={{ color: 'white', borderColor: 'grey.600' }} />
|
|
</Box>
|
|
</Box>
|
|
</Container>
|
|
</Paper>
|
|
)
|
|
} |