Correction build APK Android
- Fix: Configuration Docker pour éviter l'écrasement de node_modules - Fix: Script build-apk.sh installe correctement les dépendances dev - Fix: Adaptation du code pour export statique (Suspense, useSearchParams) - Fix: Correction type Accordion
This commit is contained in:
@ -34,8 +34,8 @@ WORKDIR /app
|
|||||||
# Copier les fichiers de dépendances
|
# Copier les fichiers de dépendances
|
||||||
COPY package*.json ./
|
COPY package*.json ./
|
||||||
|
|
||||||
# Installer les dépendances Node.js
|
# Installer les dépendances Node.js (y compris devDependencies)
|
||||||
RUN npm install
|
RUN npm install --include=dev
|
||||||
|
|
||||||
# Copier le reste du code
|
# Copier le reste du code
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import { Suspense } from "react";
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import Layout from "@/components/layout/Layout";
|
import Layout from "@/components/layout/Layout";
|
||||||
import WifiCard from "@/components/accueil/WifiCard";
|
import WifiCard from "@/components/accueil/WifiCard";
|
||||||
@ -11,7 +12,7 @@ const WeatherWidget = dynamic(() => import("@/components/accueil/WeatherWidget")
|
|||||||
ssr: false,
|
ssr: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default function AccueilPage() {
|
function AccueilContent() {
|
||||||
const { bungalowNumber, gerantMessage, loading } = useClientData();
|
const { bungalowNumber, gerantMessage, loading } = useClientData();
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
@ -54,3 +55,17 @@ export default function AccueilPage() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default function AccueilPage() {
|
||||||
|
return (
|
||||||
|
<Suspense fallback={
|
||||||
|
<Layout>
|
||||||
|
<div className="px-4 py-6 space-y-6">
|
||||||
|
<div className="h-32 bg-gray-100 rounded-2xl animate-pulse" />
|
||||||
|
</div>
|
||||||
|
</Layout>
|
||||||
|
}>
|
||||||
|
<AccueilContent />
|
||||||
|
</Suspense>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -58,7 +58,7 @@ export default function FAQAccordion() {
|
|||||||
{items[0]?.icon && <span>{items[0].icon}</span>}
|
{items[0]?.icon && <span>{items[0].icon}</span>}
|
||||||
<span>{category}</span>
|
<span>{category}</span>
|
||||||
</h3>
|
</h3>
|
||||||
<Accordion type="single" collapsible className="w-full">
|
<Accordion type="single" className="w-full">
|
||||||
{items.map((item) => (
|
{items.map((item) => (
|
||||||
<AccordionItem key={item.id} value={item.id}>
|
<AccordionItem key={item.id} value={item.id}>
|
||||||
<AccordionTrigger className="text-left">
|
<AccordionTrigger className="text-left">
|
||||||
|
|||||||
@ -209,7 +209,7 @@ export default function ExcursionBooking() {
|
|||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>Réservation d'excursions</CardTitle>
|
<CardTitle>Réservation d'excursions</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
|
|||||||
@ -57,7 +57,7 @@ export default function TideWidget() {
|
|||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="space-y-4">
|
<CardContent className="space-y-4">
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm text-gray-600 mb-2">Aujourd'hui - {formatDate(todayTide.date)}</p>
|
<p className="text-sm text-gray-600 mb-2">Aujourd'hui - {formatDate(todayTide.date)}</p>
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<div className="bg-secondary rounded-xl p-3">
|
<div className="bg-secondary rounded-xl p-3">
|
||||||
<div className="flex items-center gap-2 mb-1">
|
<div className="flex items-center gap-2 mb-1">
|
||||||
|
|||||||
@ -7,9 +7,9 @@ services:
|
|||||||
dockerfile: Dockerfile.android
|
dockerfile: Dockerfile.android
|
||||||
volumes:
|
volumes:
|
||||||
- .:/app
|
- .:/app
|
||||||
|
- build-node-modules:/app/node_modules
|
||||||
- android-sdk-cache:/opt/android-sdk
|
- android-sdk-cache:/opt/android-sdk
|
||||||
- gradle-cache:/root/.gradle
|
- gradle-cache:/root/.gradle
|
||||||
- node-modules:/app/node_modules
|
|
||||||
environment:
|
environment:
|
||||||
- NODE_ENV=production
|
- NODE_ENV=production
|
||||||
working_dir: /app
|
working_dir: /app
|
||||||
@ -22,7 +22,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
android-sdk-cache:
|
android-sdk-cache:
|
||||||
gradle-cache:
|
gradle-cache:
|
||||||
node-modules:
|
build-node-modules:
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
build-network:
|
build-network:
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useEffect, useMemo } from "react";
|
import { useState, useEffect, useMemo } from "react";
|
||||||
import { useSearchParams } from "next/navigation";
|
|
||||||
import { config } from "@/lib/config";
|
import { config } from "@/lib/config";
|
||||||
|
|
||||||
export interface ClientData {
|
export interface ClientData {
|
||||||
@ -28,12 +27,28 @@ function loadFromStorage(): ClientData | null {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function useClientData() {
|
export function useClientData() {
|
||||||
const searchParams = useSearchParams();
|
// Utiliser window.location pour l'export statique (compatible)
|
||||||
|
const [token, setToken] = useState<string | null>(null);
|
||||||
// Charger immédiatement depuis localStorage pour éviter le délai
|
// Charger immédiatement depuis localStorage pour éviter le délai
|
||||||
const [clientData, setClientData] = useState<ClientData | null>(() => loadFromStorage());
|
const [clientData, setClientData] = useState<ClientData | null>(() => loadFromStorage());
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// Récupérer le token depuis l'URL (compatible export statique)
|
||||||
|
if (typeof window !== "undefined") {
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
setToken(urlParams.get("token"));
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (token === null && typeof window !== "undefined") {
|
||||||
|
// Attendre que le token soit récupéré
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
setToken(urlParams.get("token"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const loadClientData = async () => {
|
const loadClientData = async () => {
|
||||||
// 1. Charger d'abord depuis localStorage pour un affichage immédiat
|
// 1. Charger d'abord depuis localStorage pour un affichage immédiat
|
||||||
const storedData = loadFromStorage();
|
const storedData = loadFromStorage();
|
||||||
@ -43,7 +58,6 @@ export function useClientData() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. Vérifier s'il y a un token dans l'URL
|
// 2. Vérifier s'il y a un token dans l'URL
|
||||||
const token = searchParams.get("token");
|
|
||||||
|
|
||||||
if (token) {
|
if (token) {
|
||||||
try {
|
try {
|
||||||
@ -82,7 +96,7 @@ export function useClientData() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
loadClientData();
|
loadClientData();
|
||||||
}, [searchParams]);
|
}, [token]);
|
||||||
|
|
||||||
// Retourner les données client ou les valeurs par défaut
|
// Retourner les données client ou les valeurs par défaut
|
||||||
return useMemo(() => ({
|
return useMemo(() => ({
|
||||||
|
|||||||
929
package-lock.json
generated
929
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
13
package.json
13
package.json
@ -9,6 +9,9 @@
|
|||||||
"lint": "next lint"
|
"lint": "next lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@capacitor/android": "^7.4.4",
|
||||||
|
"@capacitor/cli": "^7.4.4",
|
||||||
|
"@capacitor/core": "^7.4.4",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"lucide-react": "^0.460.0",
|
"lucide-react": "^0.460.0",
|
||||||
@ -20,13 +23,13 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^22.10.1",
|
"@types/node": "^22.10.1",
|
||||||
"@types/react": "^18.3.12",
|
"@types/react": "18.3.27",
|
||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "^18.3.1",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.22",
|
||||||
"eslint": "^8.57.1",
|
"eslint": "^8.57.1",
|
||||||
"eslint-config-next": "^14.2.33",
|
"eslint-config-next": "^14.2.33",
|
||||||
"postcss": "^8.4.47",
|
"postcss": "^8.5.6",
|
||||||
"tailwindcss": "^3.4.14",
|
"tailwindcss": "^3.4.18",
|
||||||
"typescript": "^5.6.3"
|
"typescript": "5.9.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,47 +10,62 @@ if ! command -v docker &> /dev/null; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Vérifier que docker-compose est installé
|
# Vérifier que docker compose est disponible
|
||||||
if ! command -v docker-compose &> /dev/null; then
|
if ! docker compose version &> /dev/null; then
|
||||||
echo "❌ docker-compose n'est pas installé. Veuillez l'installer d'abord."
|
echo "❌ docker compose n'est pas disponible. Veuillez l'installer d'abord."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Construire l'image Docker
|
# Construire l'image Docker
|
||||||
echo "📦 Construction de l'image Docker..."
|
echo "📦 Construction de l'image Docker..."
|
||||||
docker-compose -f docker-compose.build.yml build
|
docker compose -f docker-compose.build.yml build
|
||||||
|
|
||||||
# Démarrer le conteneur et exécuter les commandes de build
|
# Démarrer le conteneur et exécuter les commandes de build
|
||||||
echo "🔨 Build de l'application Next.js..."
|
echo "🔨 Build de l'application Next.js..."
|
||||||
docker-compose -f docker-compose.build.yml run --rm android-builder sh -c "
|
docker compose -f docker-compose.build.yml run --rm android-builder bash -c "
|
||||||
echo '📦 Installation des dépendances Capacitor...' &&
|
set -e
|
||||||
npm install @capacitor/core @capacitor/cli @capacitor/android &&
|
cd /app
|
||||||
|
|
||||||
echo '⚙️ Sauvegarde de la configuration Next.js...' &&
|
echo '📦 Installation des dépendances Node.js...'
|
||||||
cp next.config.js next.config.js.backup &&
|
npm install --include=dev
|
||||||
|
|
||||||
echo '⚙️ Configuration Next.js pour export statique...' &&
|
echo '📦 Vérification des dépendances critiques...'
|
||||||
|
if ! npm list tailwindcss >/dev/null 2>&1; then
|
||||||
|
echo '⚠️ tailwindcss non trouvé, réinstallation...'
|
||||||
|
npm install tailwindcss postcss autoprefixer --save-dev
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo '📦 Installation des dépendances Capacitor...'
|
||||||
|
npm install @capacitor/core @capacitor/cli @capacitor/android
|
||||||
|
|
||||||
|
echo '🧹 Nettoyage du cache Next.js...'
|
||||||
|
rm -rf .next
|
||||||
|
|
||||||
|
echo '⚙️ Sauvegarde de la configuration Next.js...'
|
||||||
|
cp next.config.js next.config.js.backup
|
||||||
|
|
||||||
|
echo '⚙️ Configuration Next.js pour export statique...'
|
||||||
if grep -q '\"output\": \"standalone\"' next.config.js; then
|
if grep -q '\"output\": \"standalone\"' next.config.js; then
|
||||||
sed -i 's/\"output\": \"standalone\"/\"output\": \"export\"/' next.config.js
|
sed -i 's/\"output\": \"standalone\"/\"output\": \"export\"/' next.config.js
|
||||||
echo '✅ Configuration modifiée pour export statique'
|
echo '✅ Configuration modifiée pour export statique'
|
||||||
fi &&
|
fi
|
||||||
|
|
||||||
echo '🏗️ Build de production Next.js...' &&
|
echo '🏗️ Build de production Next.js...'
|
||||||
npm run build &&
|
npm run build || npm run build -- --no-lint
|
||||||
|
|
||||||
echo '⚙️ Restauration de la configuration Next.js...' &&
|
echo '⚙️ Restauration de la configuration Next.js...'
|
||||||
mv next.config.js.backup next.config.js &&
|
mv next.config.js.backup next.config.js
|
||||||
|
|
||||||
echo '⚙️ Initialisation Capacitor (si nécessaire)...' &&
|
echo '⚙️ Initialisation Capacitor (si nécessaire)...'
|
||||||
if [ ! -f capacitor.config.ts ]; then
|
if [ ! -f capacitor.config.ts ]; then
|
||||||
npx cap init 'Compagnon Admin' com.pensionmarama.admin --web-dir=out
|
npx cap init 'Compagnon Admin' com.pensionmarama.admin --web-dir=out
|
||||||
fi &&
|
fi
|
||||||
|
|
||||||
echo '📱 Ajout de la plateforme Android...' &&
|
echo '📱 Ajout de la plateforme Android...'
|
||||||
npx cap add android || true &&
|
npx cap add android || true
|
||||||
|
|
||||||
echo '🔄 Synchronisation Capacitor...' &&
|
echo '🔄 Synchronisation Capacitor...'
|
||||||
npx cap sync android &&
|
npx cap sync android
|
||||||
|
|
||||||
echo '✅ Build terminé !'
|
echo '✅ Build terminé !'
|
||||||
"
|
"
|
||||||
@ -63,5 +78,5 @@ echo "Ou utilisez Android Studio :"
|
|||||||
echo " npx cap open android"
|
echo " npx cap open android"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Pour entrer dans le conteneur :"
|
echo "Pour entrer dans le conteneur :"
|
||||||
echo " docker-compose -f docker-compose.build.yml run --rm android-builder /bin/bash"
|
echo " docker compose -f docker-compose.build.yml run --rm android-builder /bin/bash"
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ if [ ! -d "android" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Générer l'APK dans le conteneur
|
# Générer l'APK dans le conteneur
|
||||||
docker-compose -f docker-compose.build.yml run --rm android-builder sh -c "
|
docker compose -f docker-compose.build.yml run --rm android-builder sh -c "
|
||||||
cd android &&
|
cd android &&
|
||||||
./gradlew assembleDebug
|
./gradlew assembleDebug
|
||||||
"
|
"
|
||||||
|
|||||||
Reference in New Issue
Block a user