Conversion vers données JSON statiques pour compatibilité APK

- Création des fichiers JSON dans public/data/
- Modification de tous les composants pour fetch depuis /data/*.json
- PlaceList, FAQ, Lexique, Tides, SunTimes, Excursions, Notifications
- Données complètes pour Fakarava (plages, restaurants, épiceries)
- Fix docker-compose.build.yml (suppression volume node_modules)
This commit is contained in:
2025-11-23 10:23:13 +01:00
parent 115d8c05a7
commit d0694df12a
67 changed files with 377 additions and 1034 deletions

View File

@ -16,11 +16,15 @@ export default function PlaceList({ category }: PlaceListProps) {
const fetchPlaces = async () => {
setLoading(true);
try {
const response = await fetch(
`/api/places${category !== "all" ? `?category=${category}` : ""}`
);
const data = await response.json();
setPlaces(data);
const response = await fetch("/data/places.json");
const data: Place[] = await response.json();
// Filtrer par catégorie si nécessaire
const filteredPlaces = category === "all"
? data
: data.filter((place) => place.category === category);
setPlaces(filteredPlaces);
} catch (error) {
console.error("Erreur lors du chargement des lieux:", error);
} finally {

View File

@ -16,9 +16,9 @@ export default function FAQAccordion() {
useEffect(() => {
const fetchFAQ = async () => {
try {
const response = await fetch("/api/infos?type=faq");
const response = await fetch("/data/infos.json");
const data = await response.json();
setFaqItems(data);
setFaqItems(data.faq || []);
} catch (error) {
console.error("Erreur lors du chargement de la FAQ:", error);
} finally {

View File

@ -11,9 +11,9 @@ export default function LexiqueSection() {
useEffect(() => {
const fetchLexique = async () => {
try {
const response = await fetch("/api/infos?type=lexique");
const response = await fetch("/data/infos.json");
const data = await response.json();
setLexiqueItems(data);
setLexiqueItems(data.lexique || []);
} catch (error) {
console.error("Erreur lors du chargement du lexique:", error);
} finally {

View File

@ -23,7 +23,7 @@ export default function ExcursionBooking() {
useEffect(() => {
const fetchExcursions = async () => {
try {
const response = await fetch("/api/excursions");
const response = await fetch("/data/excursions.json");
const data = await response.json();
setExcursions(data);
} catch (error) {
@ -41,30 +41,18 @@ export default function ExcursionBooking() {
if (!selectedExcursion) return;
setSubmitting(true);
try {
const response = await fetch("/api/excursions", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
excursionId: selectedExcursion.id,
...formData,
}),
});
const result = await response.json();
if (result.success) {
setSuccess(true);
setFormData({ name: "", email: "", phone: "", date: "", participants: 1 });
setTimeout(() => {
setSuccess(false);
setSelectedExcursion(null);
}, 3000);
}
} catch (error) {
console.error("Erreur lors de la réservation:", error);
} finally {
// Simuler l'envoi de réservation (sans backend)
// Dans une version production, cela devrait appeler une API ou envoyer un email
setTimeout(() => {
setSuccess(true);
setFormData({ name: "", email: "", phone: "", date: "", participants: 1 });
setTimeout(() => {
setSuccess(false);
setSelectedExcursion(null);
}, 3000);
setSubmitting(false);
}
}, 1000);
};
const getExcursionTypeLabel = (type: string) => {

View File

@ -20,7 +20,7 @@ export default function PushNotificationManager() {
const fetchNotifications = async () => {
try {
const response = await fetch("/api/notifications");
const response = await fetch("/data/notifications.json");
const data = await response.json();
setNotifications(data);
} catch (error) {
@ -48,7 +48,7 @@ export default function PushNotificationManager() {
// Vérifier périodiquement les nouvelles notifications
setInterval(async () => {
try {
const response = await fetch("/api/notifications");
const response = await fetch("/data/notifications.json");
const newNotifications = await response.json();
const unread = newNotifications.filter((n: Notification) => !n.read);
@ -88,18 +88,11 @@ export default function PushNotificationManager() {
};
const markAsRead = async (id: string) => {
try {
await fetch("/api/notifications", {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ id, read: true }),
});
setNotifications(
notifications.map((n) => (n.id === id ? { ...n, read: true } : n))
);
} catch (error) {
console.error("Erreur lors de la mise à jour:", error);
}
// Dans une version statique, on met à jour uniquement localement
// (sans API backend)
setNotifications(
notifications.map((n) => (n.id === id ? { ...n, read: true } : n))
);
};
const getNotificationIcon = (type: string) => {

View File

@ -12,9 +12,10 @@ export default function SunTimesWidget() {
useEffect(() => {
const fetchSunTimes = async () => {
try {
const response = await fetch("/api/sun-times");
const response = await fetch("/data/sun-times.json");
const data = await response.json();
setSunTimes(data);
// Récupérer les données d'aujourd'hui
setSunTimes(data[0] || null);
} catch (error) {
console.error("Erreur lors du chargement des heures du soleil:", error);
} finally {

View File

@ -12,7 +12,7 @@ export default function TideWidget() {
useEffect(() => {
const fetchTides = async () => {
try {
const response = await fetch("/api/tides");
const response = await fetch("/data/tides.json");
const data = await response.json();
setTides(data);
} catch (error) {