7 Commits

15 changed files with 238 additions and 135 deletions

View File

@@ -27,7 +27,7 @@ npx expo start
#### Présentation de l'application : #### Présentation de l'application :
##### 5 écrans : ##### 5 écrans :
Accuil : Accueil :
- Affiche le chantier sélectionné : - Affiche le chantier sélectionné :
- Résumé du chantier - Résumé du chantier
- état éditable par l'utilisateur - état éditable par l'utilisateur
@@ -36,15 +36,20 @@ Accuil :
Ressources : Ressources :
Ouvriers : Permet de voir les ressources enregistrées dans la base de données et leurs différentes données (Nom , Type, quantité totale et quantité disponible). On peut rechercher par le nom et un filtre est aussi disponible pour affiner la recherche.
Users :
Permet de voir les différents utilisateurs enregistrés dans la base de données, ainsi que leur rang (chef ou responsable).
MapScreen : MapScreen :
Permet de voir les différents chantiers sur une carte avec leurs adresses et leur état.
Ajouter : Ajouter :
Permet d'ajouter un chantier ou une ressource (ouvrier,véhicule,outil) Permet d'ajouter un chantier ou une ressource (ouvrier,véhicule,outil)
##### Fonctionnalité manquante : ##### Fonctionnalité manquante :
Par manque de temps nous n'avons pas peu finnali certaine fonctionnalité Par manque de temps nous n'avons pas pu finaliser certaines fonctionnalités
- possibilité de modifier les ressources d'un chantier (ex : réajustement des besoins) - possibilité de modifier les ressources d'un chantier (ex : réajustement des besoins)
- modifier la quantité totale d'une ressource (ex : restock de ressources) - modifier la quantité totale d'une ressource (ex : restock de ressources)

View File

@@ -1,33 +1,27 @@
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { } from 'expo-router';
import React from 'react';
import { HapticTab } from '@/components/expoExempleComponents/haptic-tab'; import { HapticTab } from '@/components/expoExempleComponents/haptic-tab';
import { IconSymbol } from '@/components/ui/icon-symbol'; import { IconSymbol } from '@/components/ui/icon-symbol';
import { Colors } from '@/constants/theme'; import { Colors } from '@/constants/theme';
import { useColorScheme } from '@/hooks/use-color-scheme'; import { useColorScheme } from '@/hooks/use-color-scheme';
import GestionOuvrier from './gestion_ouvrier';
import ListMateriel from './gestionnaire_ressource';
import Home from './home';
import MapScreen from './mapScreen';
import AntDesign from '@expo/vector-icons/AntDesign'; import AntDesign from '@expo/vector-icons/AntDesign';
import AddScreen from './addScreen'; import { Tabs } from 'expo-router';
import React from 'react';
const Tabs = createBottomTabNavigator(); import { useAuthHandler } from '../AuthHandler';
import { useUser } from '../ContextUser';
export default function TabLayout() { export default function TabLayout() {
const colorScheme = useColorScheme(); const colorScheme = useColorScheme();
const { role } = useUser();
// Handle auth in tabs layout
useAuthHandler();
return ( return (
<Tabs.Navigator <Tabs screenOptions={{tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint, headerShown: false, tabBarButton: HapticTab}}>
initialRouteName='explore' <Tabs.Screen name="index" options={{ href: null}}/>
screenOptions={{ <Tabs.Screen name="explore" options={{ href: null }}/>
tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint, <Tabs.Screen name="templateSreen" options={{ href: null}}/>
headerShown: false,
tabBarButton: HapticTab,
}}>
<Tabs.Screen <Tabs.Screen
name="home" name="home"
component={Home}
options={{ options={{
title: 'Home', title: 'Home',
tabBarIcon: ({ color }) => ( tabBarIcon: ({ color }) => (
@@ -37,7 +31,6 @@ export default function TabLayout() {
/> />
<Tabs.Screen <Tabs.Screen
name="gestionnaire_ressource" name="gestionnaire_ressource"
component={ListMateriel}
options={{ options={{
title: 'Ressources', title: 'Ressources',
tabBarIcon: ({ color }) => ( tabBarIcon: ({ color }) => (
@@ -46,34 +39,29 @@ export default function TabLayout() {
}} }}
/> />
<Tabs.Screen <Tabs.Screen
name="GestionOuvrier" name="gestion_user"
component={GestionOuvrier}
options={{ options={{
title: 'Ouvriers', title: 'Users',
tabBarIcon: ({ color }) => <IconSymbol size={28} name="person.fill" color={color} />, tabBarIcon: ({ color }) => <IconSymbol size={28} name="person.fill" color={color} />,
}} }}
/> />
<Tabs.Screen <Tabs.Screen
name="explore" name="mapScreen"
component={MapScreen}
options={{ options={{
title: 'MapScreen', title: 'Map',
tabBarIcon: ({ color }) => <IconSymbol size={28} name="paperplane.fill" color={color} />, tabBarIcon: ({ color }) => <IconSymbol size={28} name="paperplane.fill" color={color} />,
}} }}
> />
</Tabs.Screen>
<Tabs.Screen <Tabs.Screen
name="Ajouter" name="addScreen"
component={AddScreen}
options={{ options={{
title: 'Ajouter', title: 'Ajouter',
href: role === 'resp' ? '/(tabs)/addScreen' : null,
tabBarIcon: ({ color }) => ( tabBarIcon: ({ color }) => (
<AntDesign name="plus" size={24} color={color} /> <AntDesign name="plus" size={24} color={color} />
), ),
}} }}
/> />
</Tabs>
</Tabs.Navigator>
); );
} }

View File

@@ -2,14 +2,11 @@ import { ThemedText } from "@/components/theme/themed-text";
import { ThemedTextInput } from "@/components/theme/themed-textinput"; import { ThemedTextInput } from "@/components/theme/themed-textinput";
import { ThemedView } from "@/components/theme/themed-view"; import { ThemedView } from "@/components/theme/themed-view";
import Constants from "expo-constants"; //pour connaître la taille de la barre menu de l'OS en haut import Constants from "expo-constants"; //pour connaître la taille de la barre menu de l'OS en haut
import { useLocalSearchParams, useRouter } from "expo-router"; import React, { useEffect, useState } from "react";
import React, { useEffect, useMemo, useState } from "react"; import { FlatList, StyleSheet, Text, View } from "react-native";
import { FlatList, Image, StyleSheet, Text, View } from "react-native";
import { getUsers } from "@/services/ressourcesService"; import { getUsers } from "@/services/ressourcesService";
import { useChantier } from "../ContextChantier";
import SelectChantier from "@/components/selectChantier"; import SelectChantier from "@/components/selectChantier";
import { Ressources } from "@/class/class"; import { User } from "@/class/class";
import { getRessources } from "@/services/ressourcesService";
type Concert = { type Concert = {
group: string; group: string;
@@ -22,19 +19,15 @@ type Concert = {
favorite: boolean; favorite: boolean;
}; };
export default function GestionOuvrier() { export default function GestionUser() {
const router = useRouter();
const { nom, prenom } = useLocalSearchParams(); // Recup data ecran precedent
const [search, setSearch] = useState(""); const [search, setSearch] = useState("");
const { chantier, setChantier } = useChantier(); const [users, setUsers] = useState<User[]>([]);
const [artisans, setRessources] = useState<Ressources[]>([]);
useEffect(() => { useEffect(() => {
async function loadData() { async function loadData() {
try { try {
//Nous ne gardons que les Ouvriers, qui peuvent être assignés à un chantier const data = (await getUsers());
const data = (await getRessources()).filter(u => u.type === "Ouvrier"); setUsers(data);
setRessources(data);
} catch (error) { } catch (error) {
console.error("Erreur lors du chargement :", error); console.error("Erreur lors du chargement :", error);
} }
@@ -42,17 +35,15 @@ export default function GestionOuvrier() {
loadData(); loadData();
}, []); }, []);
const renderItem = ({ item, index }: { item?: Ressources; index: number }) => { const renderItem = ({ item, index }: { item?: User; index: number }) => {
if (!item) { if (!item) {
return null; return null;
} }
return ( return (
<ThemedView lvl={1} shadow={true} style={styles.card}> <ThemedView lvl={1} shadow={true} style={styles.card}>
<ThemedView lvl={1} style={styles.info}> <ThemedView lvl={1} style={styles.info}>
<Image source={{ uri: item.Image }} style={styles.image} /> <ThemedText style={styles.group}>{item.name} {item.last_name}</ThemedText>
<ThemedText style={styles.group}>{item.name}</ThemedText> <ThemedText>{item.role}</ThemedText>
<ThemedText>{item.quantity}</ThemedText>
<ThemedText>{item.type}</ThemedText>
</ThemedView> </ThemedView>
</ThemedView> </ThemedView>
); );
@@ -67,7 +58,7 @@ export default function GestionOuvrier() {
<FlatList <FlatList
data={artisans} data={users}
renderItem={renderItem} renderItem={renderItem}
keyExtractor={(_, index) => index.toString()} keyExtractor={(_, index) => index.toString()}
contentContainerStyle={{ paddingBottom: 40 }} contentContainerStyle={{ paddingBottom: 40 }}

View File

@@ -8,19 +8,25 @@ import { useLocalSearchParams, useRouter } from "expo-router";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { FlatList, Image, StyleSheet, Text, View } from "react-native"; import { FlatList, Image, StyleSheet, Text, View } from "react-native";
import { Ressources } from "../../class/class"; import { Ressources } from "../../class/class";
import { getRessources } from "../../services/ressourcesService"; import { getReservations, getRessources } from "../../services/ressourcesService";
import SelectChantier from "@/components/selectChantier"; import SelectChantier from "@/components/selectChantier";
import { useRessources } from "../ContextRessource"; import { useRessources } from "../ContextRessource";
import { useChantier } from "../ContextChantier";
import { getNbUseRessources, getNbUseRessourcesInChantier, isInChantier } from "@/class/utils";
import { useReservations } from "../ContextReservation";
export default function GestionnaireRessource() { export default function GestionnaireRessource() {
const [search, setSearch] = useState(""); const [search, setSearch] = useState("");
const {ressources, setRessources} = useRessources(); const {ressources, setRessources} = useRessources();
const {reservations, setReservations} = useReservations();
const {chantier, setChantier} = useChantier();
const [filterType, setFilterType] = useState("Tout"); const [filterType, setFilterType] = useState("Tout");
const [showFilterMenu, setShowFilterMenu] = useState(false); const [showFilterMenu, setShowFilterMenu] = useState(false);
const [filterChantier, setFilterChantier] = useState(false);
const router = useRouter(); const router = useRouter();
useEffect(() => { useEffect(() => {
async function loadData() { async function loadDataRessources() {
try { try {
const data = await getRessources(); const data = await getRessources();
setRessources(data); setRessources(data);
@@ -28,13 +34,23 @@ export default function GestionnaireRessource() {
console.error("Erreur lors du chargement :", error); console.error("Erreur lors du chargement :", error);
} }
} }
loadData(); async function loadDataReservations() {
try {
const data = await getReservations();
setReservations(data);
} catch (error) {
console.error("Erreur lors du chargement :", error);
}
}
loadDataRessources();
loadDataReservations();
}, []); }, []);
const filteredData = ressources.filter((r) => { const filteredData = ressources.filter((r) => {
const matchName = r.name.toLowerCase().includes(search.toLowerCase()); const matchName = r.name.toLowerCase().includes(search.toLowerCase());
const matchType = filterType === "Tout" || r.type === filterType; const matchType = filterType === "Tout" || r.type === filterType;
return matchName && matchType;
return matchName && matchType && (!filterChantier || (chantier && isInChantier(r,chantier,reservations)));
}); });
const renderRessource = ({ item }: { item: Ressources }) => { const renderRessource = ({ item }: { item: Ressources }) => {
@@ -43,11 +59,13 @@ export default function GestionnaireRessource() {
<ThemedView lvl={1} shadow={true} style={styles.card}> <ThemedView lvl={1} shadow={true} style={styles.card}>
<Image source={{ uri: item.Image }} style={styles.image} /> <Image source={{ uri: item.Image }} style={styles.image} />
<ThemedView lvl={1} style={styles.info}> <ThemedView lvl={1} style={styles.info}>
<ThemedText>Id : {item.id}</ThemedText>
<ThemedText>Nom : {item.name}</ThemedText> <ThemedText>Nom : {item.name}</ThemedText>
<ThemedText>Type : {item.type}</ThemedText> <ThemedText>Type : {item.type}</ThemedText>
<ThemedText>Quantité totale : {item.quantity}</ThemedText> <ThemedText>Quantité totale : {item.quantity}</ThemedText>
<ThemedText>Quantité disponible : {item.available_quantity}</ThemedText> <ThemedText>Quantité disponible : {item.quantity-getNbUseRessources(item, reservations)}</ThemedText>
{filterChantier&&chantier &&
<ThemedText>Quantité utilisé dans le chantier : {getNbUseRessourcesInChantier(item,chantier, reservations)}</ThemedText>
}
</ThemedView> </ThemedView>
</ThemedView> </ThemedView>
); );
@@ -84,6 +102,7 @@ export default function GestionnaireRessource() {
> >
<ThemedText style={{ textAlign: "center" }}>{t}</ThemedText> <ThemedText style={{ textAlign: "center" }}>{t}</ThemedText>
</ThemedButton> </ThemedButton>
))} ))}
{/* Bouton "Fermer" remplacé */} {/* Bouton "Fermer" remplacé */}
@@ -117,14 +136,22 @@ export default function GestionnaireRessource() {
</ThemedView> </ThemedView>
{/* Bouton filtre en haut à droite */} {/* Bouton filtre en haut à droite */}
<View style={{flexDirection: "row", gap:5}}>
<ThemedButton <ThemedButton
lvl={1} lvl={1}
shadow={true} shadow={true}
style={{ padding: 10, borderRadius: 8, marginTop: 10 }} style={styles.button}
onPress={() => setShowFilterMenu(true)} onPress={() => setShowFilterMenu(true)}
> >
<ThemedText>{`Filtre: ${filterType}`}</ThemedText> <ThemedText>{`Filtre: ${filterType}`}</ThemedText>
</ThemedButton> </ThemedButton>
<ThemedButton style={styles.button}>
<ThemedText onPress={() => setFilterChantier(!filterChantier)}>
{filterChantier?"chantier courant":"tous"}
</ThemedText>
</ThemedButton>
</View>
</View> </View>
} }
ListEmptyComponent={ ListEmptyComponent={
@@ -214,4 +241,9 @@ const styles = StyleSheet.create({
marginBottom: 20, marginBottom: 20,
textAlign: "center", textAlign: "center",
}, },
button:{
padding: 10,
borderRadius: 8,
marginTop: 10
},
}); });

View File

@@ -61,7 +61,7 @@ const region = {
<Marker <Marker
key = {chantier.id} key = {chantier.id}
coordinate={{ latitude: chantier.latitude, longitude: chantier.longitude}} coordinate={{ latitude: chantier.latitude, longitude: chantier.longitude}}
title={chantier.adresse} title={chantier.name}
description={chantier.etat} description={chantier.etat}
/> />
))} ))}

45
app/AuthHandler.tsx Normal file
View File

@@ -0,0 +1,45 @@
import { useRouter, useSegments } from "expo-router";
import { onAuthStateChanged } from "firebase/auth";
import { doc, getDoc } from "firebase/firestore";
import { useEffect } from "react";
import { auth, db } from "../firebase_config";
import { useUser } from "./ContextUser";
export function useAuthHandler() {
const router = useRouter();
const segments = useSegments();
const { setUser, setRole } = useUser();
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, async (currentUser) => {
if (!currentUser) {
setUser(null);
setRole(null);
router.replace("/login/login");
return;
}
const userDocRef = doc(db, "user", currentUser.uid);
const userDoc = await getDoc(userDocRef);
if (!userDoc.exists()) {
setUser(null);
setRole(null);
router.replace("/login/login");
return;
}
const { role } = userDoc.data();
setUser(currentUser);
setRole(role);
// Only redirect if we're on login page
const inAuthGroup = segments[0] === 'login';
if (inAuthGroup) {
router.replace("/(tabs)/home");
}
});
return unsubscribe;
}, []);
}

View File

@@ -1,16 +1,11 @@
import { ThemedText } from "@/components/theme/themed-text"; import { ThemedText } from "@/components/theme/themed-text";
import { ThemedTextInput } from "@/components/theme/themed-textinput"; import { ThemedTextInput } from "@/components/theme/themed-textinput";
import { ThemedView } from "@/components/theme/themed-view"; import { ThemedView } from "@/components/theme/themed-view";
import { router } from "expo-router"; import { signInWithEmailAndPassword } from "firebase/auth";
import {
signInWithEmailAndPassword
} from "firebase/auth";
import React, { useState } from "react"; import React, { useState } from "react";
import { Button, StyleSheet, View } from "react-native"; import { Button, StyleSheet, View } from "react-native";
import { auth } from "../../firebase_config"; import { auth } from "../../firebase_config";
const DEFAULT_ROLE = "resp";
const LoginScreen: React.FC = () => { const LoginScreen: React.FC = () => {
const [email, setEmail] = useState<string>(""); const [email, setEmail] = useState<string>("");
const [password, setPassword] = useState<string>(""); const [password, setPassword] = useState<string>("");
@@ -18,21 +13,11 @@ const LoginScreen: React.FC = () => {
const handleLogin = async () => { const handleLogin = async () => {
try { try {
await signInWithEmailAndPassword(auth, email, password); await signInWithEmailAndPassword(auth, email, password);
router.replace("/(tabs)");
} catch (error: any) { } catch (error: any) {
alert(error.message); alert(error.message);
} }
}; };
/*const handleRegister = async () => {
try {
await createUserWithEmailAndPassword(auth, email, password);
router.replace("/(tabs)");
} catch (error: any) {
alert(error.message);
}
}; */
return ( return (
<ThemedView lvl={1} style={styles.container}> <ThemedView lvl={1} style={styles.container}>
<ThemedText style={styles.title}>Se connecter</ThemedText> <ThemedText style={styles.title}>Se connecter</ThemedText>
@@ -45,7 +30,6 @@ const LoginScreen: React.FC = () => {
value={email} value={email}
onChangeText={setEmail} onChangeText={setEmail}
autoCapitalize="none" autoCapitalize="none"
/> />
<ThemedTextInput <ThemedTextInput
lvl = {2} lvl = {2}
@@ -59,7 +43,6 @@ const LoginScreen: React.FC = () => {
/> />
<Button title="Se connecter" onPress={handleLogin} /> <Button title="Se connecter" onPress={handleLogin} />
<View style={{ height: 10 }} /> <View style={{ height: 10 }} />
{/* <Button title="S'inscrire" onPress={handleRegister} /> */}
</ThemedView> </ThemedView>
); );
}; };
@@ -76,7 +59,6 @@ const styles = StyleSheet.create({
}, },
input: { input: {
borderWidth: 1, borderWidth: 1,
//borderColor: "#ccc",
borderRadius: 8, borderRadius: 8,
padding: 10, padding: 10,
marginBottom: 10, marginBottom: 10,

View File

@@ -30,8 +30,8 @@ export type Ressources = {
type: string; //"Machine","Outil","Ouvrier" type: string; //"Machine","Outil","Ouvrier"
Image: string; Image: string;
quantity: number; quantity: number;
available_quantity: number; //available_quantity: number;
allocation: Reservation[]; //allocation: Reservation[];
}; };
export type Reservation = { export type Reservation = {

View File

@@ -29,3 +29,26 @@ export function getNbUseRessources(ressource:Ressources, allReservations:Reserva
}) })
return res; return res;
} }
export function getNbUseRessourcesInChantier(ressource:Ressources,chantier: Chantier, allReservations:Reservation[]):number{
var res:number = 0;
getReservationOfRessource(ressource,allReservations).forEach(reserv => {
if(reserv.chantier.id === chantier.id && reserv.ressource.id===ressource.id){
res+=reserv.quantity;
}
})
return res;
}
export function isInChantier(ressource:Ressources, chantier: Chantier, allReservations:Reservation[]):boolean{
console.log(allReservations.length+ " --------------------------------");
const reservations:Reservation[] = getReservationOfRessource(ressource,allReservations);
var res=false;
reservations.forEach(reserv => {
console.log(reserv.chantier.id + " " + chantier.id)
if(reserv.chantier.id === chantier.id){
res=true;
}
});
return res;
}

View File

@@ -1,24 +1,17 @@
import ChantierSummary from '@/components/chantierSummary';
import SelectChantier from '@/components/selectChantier'; import SelectChantier from '@/components/selectChantier';
import SetStatus from '@/components/setStatus';
import { ThemedView } from '@/components/theme/themed-view';
import React, { useEffect, useState } from 'react';
import { StyleSheet, ScrollView, Button, TextInput, Text, View, Modal } from 'react-native';
import { useChantier } from '@/app/ContextChantier';
import { useRessources } from '@/app/ContextRessource'; import { useRessources } from '@/app/ContextRessource';
import { useUser } from '@/app/ContextUser'; import { Ressources } from '@/class/class';
import { getRessources, getUsers, addChantier , addRessources} from '@/services/ressourcesService';
import { Chantier, Ressources, User } from '@/class/class';
import { ThemedText } from '@/components/theme/themed-text';
import { ThemedButton } from '@/components/theme/themed-button'; import { ThemedButton } from '@/components/theme/themed-button';
import { ThemedText } from '@/components/theme/themed-text';
import { ThemedTextInput } from '@/components/theme/themed-textinput'; import { ThemedTextInput } from '@/components/theme/themed-textinput';
import DateTimePicker, { DateTimePickerEvent } from '@react-native-community/datetimepicker'; import { ThemedView } from '@/components/theme/themed-view';
import { addRessources } from '@/services/ressourcesService';
import React, { useState } from 'react';
import { Modal, ScrollView, StyleSheet, View } from 'react-native';
import Constants from 'expo-constants'; //pour connaître la taille de la barre menu de l'OS en haut import Constants from 'expo-constants'; //pour connaître la taille de la barre menu de l'OS en haut
import SelectChafChantier from '@/components/add/select/selectChefChantier';
import SelectMachine from '@/components/selectMachine';
type Dictionary = { type Dictionary = {
@@ -66,9 +59,9 @@ export default function AddRessource({ressourceType, ...otherProps }: Props) {
name: nom, name: nom,
type : ressourceType, type : ressourceType,
quantity : parseInt(quantite), quantity : parseInt(quantite),
available_quantity : parseInt(quantite), //available_quantity : parseInt(quantite),
Image : "", Image : "",
allocation : [], //allocation : [],
}; };
const id = await addRessources(nouvelleRessource); const id = await addRessources(nouvelleRessource);

View File

@@ -18,22 +18,21 @@ export default function ChantierSummary({data,style , ...otherProps }: Props) {
{data.chantier ? ( {data.chantier ? (
<ThemedView lvl={4} style={styles.chantier}> <ThemedView lvl={4} style={styles.chantier}>
<View> <View>
<Image source={{ uri:"https://cdn.discordapp.com/attachments/1425108443571945644/1427207643180826757/raw.png?ex=693f1a72&is=693dc8f2&hm=86ffb97145fc8d3aec822b87d99be233c98477d4424c1ef58f80eb81b17c7c80&" /*chantier.urlImg*/ }} style={styles.image} /> <Image source={{ uri:"" /*chantier.urlImg*/ }} style={styles.image} />
</View> </View>
<View style={{flex: 1}}> <View style={{flex: 1}}>
<ThemedText selectable={true}>Id: {data.chantier.id}</ThemedText>
<ThemedText selectable={true}>Objet: {data.chantier.name}</ThemedText> <ThemedText selectable={true}>Objet: {data.chantier.name}</ThemedText>
<ThemedText selectable={true}>Adresse: {data.chantier.adresse}</ThemedText> <ThemedText selectable={true}>Adresse: {data.chantier.adresse}</ThemedText>
<ThemedText selectable={true}>Chef de chantier: {data.chantier.chef.last_name}{" "}{data.chantier.chef.name}</ThemedText> <ThemedText selectable={true}>Chef de chantier: {data.chantier.chef.last_name}{" "}{data.chantier.chef.name}</ThemedText>
<ThemedText selectable={true}>État: {data.chantier.etat}</ThemedText> <ThemedText selectable={true}>État: {data.chantier.etat}</ThemedText>
<ThemedText selectable={true}>equipe: <ThemedText selectable={true}>
{getNbItemReservation(data.chantier.equipe)} ({data.chantier.equipe.length} type{data.chantier.equipe.length>1&&"s"}) equipe: {getNbItemReservation(data.chantier.equipe)} ({data.chantier.equipe.length} type{data.chantier.equipe.length>1&&"s"})
</ThemedText> </ThemedText>
<ThemedText selectable={true}>materiel: <ThemedText selectable={true}>
{getNbItemReservation(data.chantier.materiel)} ({data.chantier.materiel.length} type{data.chantier.materiel.length>1&&"s"}) materiel: {getNbItemReservation(data.chantier.materiel)} ({data.chantier.materiel.length} type{data.chantier.materiel.length>1&&"s"})
</ThemedText> </ThemedText>
<ThemedText selectable={true}>vehicules: <ThemedText selectable={true}>
{getNbItemReservation(data.chantier.vehicules)} ({data.chantier.vehicules.length} type{data.chantier.vehicules.length>1&&"s"}) vehicules: {getNbItemReservation(data.chantier.vehicules)} ({data.chantier.vehicules.length} type{data.chantier.vehicules.length>1&&"s"})
</ThemedText> </ThemedText>
</View> </View>
</ThemedView> </ThemedView>

View File

@@ -122,7 +122,7 @@ export default function SelectChantier() {
<Image source={{ uri:"https://cdn.discordapp.com/attachments/1425108443571945644/1427207643180826757/raw.png?ex=693f1a72&is=693dc8f2&hm=86ffb97145fc8d3aec822b87d99be233c98477d4424c1ef58f80eb81b17c7c80&" /*chantier.urlImg*/ }} style={styles.image} /> <Image source={{ uri:"https://cdn.discordapp.com/attachments/1425108443571945644/1427207643180826757/raw.png?ex=693f1a72&is=693dc8f2&hm=86ffb97145fc8d3aec822b87d99be233c98477d4424c1ef58f80eb81b17c7c80&" /*chantier.urlImg*/ }} style={styles.image} />
</View> </View>
<View style={{flex: 1}}> <View style={{flex: 1}}>
<ThemedText>Renovation: {item.name}</ThemedText> <ThemedText>Objet: {item.name}</ThemedText>
<ThemedText>Adresse: {item.adresse}</ThemedText> <ThemedText>Adresse: {item.adresse}</ThemedText>
<ThemedText>Chef de chantier: {item.chef.last_name}{" "}{item.chef.name}</ThemedText> <ThemedText>Chef de chantier: {item.chef.last_name}{" "}{item.chef.name}</ThemedText>
<ThemedText>État: {item.etat}</ThemedText> <ThemedText>État: {item.etat}</ThemedText>
@@ -138,7 +138,7 @@ export default function SelectChantier() {
<ThemedView lvl={2} shadow={true} style={styles.window}> <ThemedView lvl={2} shadow={true} style={styles.window}>
<AnimatedThemedButton style={animatedButtonStyle} lvl={isOpen ? 1 : 1} onPress={() => onPressOpen()}> <AnimatedThemedButton style={animatedButtonStyle} lvl={isOpen ? 1 : 1} onPress={() => onPressOpen()}>
<ThemedText style={styles.buttonText}> <ThemedText style={styles.buttonText}>
{isOpen ? "Fermer" : (chantier!=null ? chantier.adresse : "Chantier")} {isOpen ? "Fermer" : (chantier!=null ? chantier.name : "Chantier")}
</ThemedText> </ThemedText>
</AnimatedThemedButton> </AnimatedThemedButton>
{isOpen && ( {isOpen && (

View File

@@ -121,7 +121,7 @@ const styles = StyleSheet.create({
windowBox:{ windowBox:{
zIndex: 2, zIndex: 2,
//backgroundColor: '#00FFFF40', //backgroundColor: '#00FFFF40',
width:"30%", width:"35%",
padding: 10, padding: 10,
paddingLeft: 0, paddingLeft: 0,
//overflow: 'hidden', //overflow: 'hidden',

32
package-lock.json generated
View File

@@ -90,6 +90,7 @@
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz",
"integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.27.1", "@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.3", "@babel/generator": "^7.28.3",
@@ -1471,6 +1472,7 @@
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz",
"integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==",
"license": "MIT", "license": "MIT",
"peer": true,
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
@@ -2329,6 +2331,7 @@
"version": "0.14.6", "version": "0.14.6",
"resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.14.6.tgz", "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.14.6.tgz",
"integrity": "sha512-4uyt8BOrBsSq6i4yiOV/gG6BnnrvTeyymlNcaN/dKvyU1GoolxAafvIvaNP1RCGPlNab3OuE4MKUQuv2lH+PLQ==", "integrity": "sha512-4uyt8BOrBsSq6i4yiOV/gG6BnnrvTeyymlNcaN/dKvyU1GoolxAafvIvaNP1RCGPlNab3OuE4MKUQuv2lH+PLQ==",
"peer": true,
"dependencies": { "dependencies": {
"@firebase/component": "0.7.0", "@firebase/component": "0.7.0",
"@firebase/logger": "0.5.0", "@firebase/logger": "0.5.0",
@@ -2394,6 +2397,7 @@
"version": "0.5.6", "version": "0.5.6",
"resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.5.6.tgz", "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.5.6.tgz",
"integrity": "sha512-YYGARbutghQY4zZUWMYia0ib0Y/rb52y72/N0z3vglRHL7ii/AaK9SA7S/dzScVOlCdnbHXz+sc5Dq+r8fwFAg==", "integrity": "sha512-YYGARbutghQY4zZUWMYia0ib0Y/rb52y72/N0z3vglRHL7ii/AaK9SA7S/dzScVOlCdnbHXz+sc5Dq+r8fwFAg==",
"peer": true,
"dependencies": { "dependencies": {
"@firebase/app": "0.14.6", "@firebase/app": "0.14.6",
"@firebase/component": "0.7.0", "@firebase/component": "0.7.0",
@@ -2409,7 +2413,8 @@
"version": "0.9.3", "version": "0.9.3",
"resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.3.tgz", "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.3.tgz",
"integrity": "sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw==", "integrity": "sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw==",
"license": "Apache-2.0" "license": "Apache-2.0",
"peer": true
}, },
"node_modules/@firebase/auth": { "node_modules/@firebase/auth": {
"version": "1.11.1", "version": "1.11.1",
@@ -2859,6 +2864,7 @@
"integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==",
"hasInstallScript": true, "hasInstallScript": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"peer": true,
"dependencies": { "dependencies": {
"tslib": "^2.1.0" "tslib": "^2.1.0"
}, },
@@ -3894,6 +3900,7 @@
"resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-7.1.25.tgz", "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-7.1.25.tgz",
"integrity": "sha512-zQeWK9txDePWbYfqTs0C6jeRdJTm/7VhQtW/1IbJNDi9/rFIRzZule8bdQPAnf8QWUsNujRmi1J9OG/hhfbalg==", "integrity": "sha512-zQeWK9txDePWbYfqTs0C6jeRdJTm/7VhQtW/1IbJNDi9/rFIRzZule8bdQPAnf8QWUsNujRmi1J9OG/hhfbalg==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@react-navigation/core": "^7.13.6", "@react-navigation/core": "^7.13.6",
"escape-string-regexp": "^4.0.0", "escape-string-regexp": "^4.0.0",
@@ -4096,6 +4103,7 @@
"integrity": "sha512-Qec1E3mhALmaspIrhWt9jkQMNdw6bReVu64mjvhbhq2NFPftLPVr+l1SZgmw/66WwBNpDh7ao5AT6gF5v41PFA==", "integrity": "sha512-Qec1E3mhALmaspIrhWt9jkQMNdw6bReVu64mjvhbhq2NFPftLPVr+l1SZgmw/66WwBNpDh7ao5AT6gF5v41PFA==",
"devOptional": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"csstype": "^3.0.2" "csstype": "^3.0.2"
} }
@@ -4167,6 +4175,7 @@
"integrity": "sha512-n1H6IcDhmmUEG7TNVSspGmiHHutt7iVKtZwRppD7e04wha5MrkV1h3pti9xQLcCMt6YWsncpoT0HMjkH1FNwWQ==", "integrity": "sha512-n1H6IcDhmmUEG7TNVSspGmiHHutt7iVKtZwRppD7e04wha5MrkV1h3pti9xQLcCMt6YWsncpoT0HMjkH1FNwWQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "8.46.0", "@typescript-eslint/scope-manager": "8.46.0",
"@typescript-eslint/types": "8.46.0", "@typescript-eslint/types": "8.46.0",
@@ -4729,6 +4738,7 @@
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"license": "MIT", "license": "MIT",
"peer": true,
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
}, },
@@ -5414,6 +5424,7 @@
} }
], ],
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"baseline-browser-mapping": "^2.8.9", "baseline-browser-mapping": "^2.8.9",
"caniuse-lite": "^1.0.30001746", "caniuse-lite": "^1.0.30001746",
@@ -6553,6 +6564,7 @@
"integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==", "integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1", "@eslint-community/regexpp": "^4.12.1",
@@ -6750,6 +6762,7 @@
"integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@rtsao/scc": "^1.1.0", "@rtsao/scc": "^1.1.0",
"array-includes": "^3.1.9", "array-includes": "^3.1.9",
@@ -6988,6 +7001,7 @@
"resolved": "https://registry.npmjs.org/expo/-/expo-54.0.13.tgz", "resolved": "https://registry.npmjs.org/expo/-/expo-54.0.13.tgz",
"integrity": "sha512-F1puKXzw8ESnsbvaKdXtcIiyYLQ2kUHqP8LuhgtJS1wm6w55VhtOPg8yl/0i8kPbTA0YfD+KYdXjSfhPXgUPxw==", "integrity": "sha512-F1puKXzw8ESnsbvaKdXtcIiyYLQ2kUHqP8LuhgtJS1wm6w55VhtOPg8yl/0i8kPbTA0YfD+KYdXjSfhPXgUPxw==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@babel/runtime": "^7.20.0", "@babel/runtime": "^7.20.0",
"@expo/cli": "54.0.11", "@expo/cli": "54.0.11",
@@ -7055,6 +7069,7 @@
"resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-18.0.9.tgz", "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-18.0.9.tgz",
"integrity": "sha512-sqoXHAOGDcr+M9NlXzj1tGoZyd3zxYDy215W6E0Z0n8fgBaqce9FAYQE2bu5X4G629AYig5go7U6sQz7Pjcm8A==", "integrity": "sha512-sqoXHAOGDcr+M9NlXzj1tGoZyd3zxYDy215W6E0Z0n8fgBaqce9FAYQE2bu5X4G629AYig5go7U6sQz7Pjcm8A==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@expo/config": "~12.0.9", "@expo/config": "~12.0.9",
"@expo/env": "~2.0.7" "@expo/env": "~2.0.7"
@@ -7079,6 +7094,7 @@
"resolved": "https://registry.npmjs.org/expo-font/-/expo-font-14.0.9.tgz", "resolved": "https://registry.npmjs.org/expo-font/-/expo-font-14.0.9.tgz",
"integrity": "sha512-xCoQbR/36qqB6tew/LQ6GWICpaBmHLhg/Loix5Rku/0ZtNaXMJv08M9o1AcrdiGTn/Xf/BnLu6DgS45cWQEHZg==", "integrity": "sha512-xCoQbR/36qqB6tew/LQ6GWICpaBmHLhg/Loix5Rku/0ZtNaXMJv08M9o1AcrdiGTn/Xf/BnLu6DgS45cWQEHZg==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"fontfaceobserver": "^2.1.0" "fontfaceobserver": "^2.1.0"
}, },
@@ -7150,6 +7166,7 @@
"resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-8.0.8.tgz", "resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-8.0.8.tgz",
"integrity": "sha512-MyeMcbFDKhXh4sDD1EHwd0uxFQNAc6VCrwBkNvvvufUsTYFq3glTA9Y8a+x78CPpjNqwNAamu74yIaIz7IEJyg==", "integrity": "sha512-MyeMcbFDKhXh4sDD1EHwd0uxFQNAc6VCrwBkNvvvufUsTYFq3glTA9Y8a+x78CPpjNqwNAamu74yIaIz7IEJyg==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"expo-constants": "~18.0.8", "expo-constants": "~18.0.8",
"invariant": "^2.2.4" "invariant": "^2.2.4"
@@ -11394,6 +11411,7 @@
"resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
"integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
"license": "MIT", "license": "MIT",
"peer": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@@ -11413,6 +11431,7 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
"integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"scheduler": "^0.26.0" "scheduler": "^0.26.0"
}, },
@@ -11449,6 +11468,7 @@
"resolved": "https://registry.npmjs.org/react-native/-/react-native-0.81.4.tgz", "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.81.4.tgz",
"integrity": "sha512-bt5bz3A/+Cv46KcjV0VQa+fo7MKxs17RCcpzjftINlen4ZDUl0I6Ut+brQ2FToa5oD0IB0xvQHfmsg2EDqsZdQ==", "integrity": "sha512-bt5bz3A/+Cv46KcjV0VQa+fo7MKxs17RCcpzjftINlen4ZDUl0I6Ut+brQ2FToa5oD0IB0xvQHfmsg2EDqsZdQ==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@jest/create-cache-key-function": "^29.7.0", "@jest/create-cache-key-function": "^29.7.0",
"@react-native/assets-registry": "0.81.4", "@react-native/assets-registry": "0.81.4",
@@ -11506,6 +11526,7 @@
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.28.0.tgz", "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.28.0.tgz",
"integrity": "sha512-0msfJ1vRxXKVgTgvL+1ZOoYw3/0z1R+Ked0+udoJhyplC2jbVKIJ8Z1bzWdpQRCV3QcQ87Op0zJVE5DhKK2A0A==", "integrity": "sha512-0msfJ1vRxXKVgTgvL+1ZOoYw3/0z1R+Ked0+udoJhyplC2jbVKIJ8Z1bzWdpQRCV3QcQ87Op0zJVE5DhKK2A0A==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@egjs/hammerjs": "^2.0.17", "@egjs/hammerjs": "^2.0.17",
"hoist-non-react-statics": "^3.3.0", "hoist-non-react-statics": "^3.3.0",
@@ -11560,6 +11581,7 @@
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-4.1.3.tgz", "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-4.1.3.tgz",
"integrity": "sha512-GP8wsi1u3nqvC1fMab/m8gfFwFyldawElCcUSBJQgfrXeLmsPPUOpDw44lbLeCpcwUuLa05WTVePdTEwCLTUZg==", "integrity": "sha512-GP8wsi1u3nqvC1fMab/m8gfFwFyldawElCcUSBJQgfrXeLmsPPUOpDw44lbLeCpcwUuLa05WTVePdTEwCLTUZg==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"react-native-is-edge-to-edge": "^1.2.1", "react-native-is-edge-to-edge": "^1.2.1",
"semver": "7.7.2" "semver": "7.7.2"
@@ -11588,6 +11610,7 @@
"resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.6.2.tgz", "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.6.2.tgz",
"integrity": "sha512-4XGqMNj5qjUTYywJqpdWZ9IG8jgkS3h06sfVjfw5yZQZfWnRFXczi0GnYyFyCc2EBps/qFmoCH8fez//WumdVg==", "integrity": "sha512-4XGqMNj5qjUTYywJqpdWZ9IG8jgkS3h06sfVjfw5yZQZfWnRFXczi0GnYyFyCc2EBps/qFmoCH8fez//WumdVg==",
"license": "MIT", "license": "MIT",
"peer": true,
"peerDependencies": { "peerDependencies": {
"react": "*", "react": "*",
"react-native": "*" "react-native": "*"
@@ -11598,6 +11621,7 @@
"resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-4.16.0.tgz", "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-4.16.0.tgz",
"integrity": "sha512-yIAyh7F/9uWkOzCi1/2FqvNvK6Wb9Y1+Kzn16SuGfN9YFJDTbwlzGRvePCNTOX0recpLQF3kc2FmvMUhyTCH1Q==", "integrity": "sha512-yIAyh7F/9uWkOzCi1/2FqvNvK6Wb9Y1+Kzn16SuGfN9YFJDTbwlzGRvePCNTOX0recpLQF3kc2FmvMUhyTCH1Q==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"react-freeze": "^1.0.0", "react-freeze": "^1.0.0",
"react-native-is-edge-to-edge": "^1.2.1", "react-native-is-edge-to-edge": "^1.2.1",
@@ -11613,6 +11637,7 @@
"resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.21.1.tgz", "resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.21.1.tgz",
"integrity": "sha512-BeNsgwwe4AXUFPAoFU+DKjJ+CVQa3h54zYX77p7GVZrXiiNo3vl03WYDYVEy5R2J2HOPInXtQZB5gmj3vuzrKg==", "integrity": "sha512-BeNsgwwe4AXUFPAoFU+DKjJ+CVQa3h54zYX77p7GVZrXiiNo3vl03WYDYVEy5R2J2HOPInXtQZB5gmj3vuzrKg==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@babel/runtime": "^7.18.6", "@babel/runtime": "^7.18.6",
"@react-native/normalize-colors": "^0.74.1", "@react-native/normalize-colors": "^0.74.1",
@@ -11645,6 +11670,7 @@
"resolved": "https://registry.npmjs.org/react-native-worklets/-/react-native-worklets-0.5.1.tgz", "resolved": "https://registry.npmjs.org/react-native-worklets/-/react-native-worklets-0.5.1.tgz",
"integrity": "sha512-lJG6Uk9YuojjEX/tQrCbcbmpdLCSFxDK1rJlkDhgqkVi1KZzG7cdcBFQRqyNOOzR9Y0CXNuldmtWTGOyM0k0+w==", "integrity": "sha512-lJG6Uk9YuojjEX/tQrCbcbmpdLCSFxDK1rJlkDhgqkVi1KZzG7cdcBFQRqyNOOzR9Y0CXNuldmtWTGOyM0k0+w==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@babel/plugin-transform-arrow-functions": "^7.0.0-0", "@babel/plugin-transform-arrow-functions": "^7.0.0-0",
"@babel/plugin-transform-class-properties": "^7.0.0-0", "@babel/plugin-transform-class-properties": "^7.0.0-0",
@@ -11755,6 +11781,7 @@
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
"integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==",
"license": "MIT", "license": "MIT",
"peer": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@@ -13177,6 +13204,7 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"engines": { "engines": {
"node": ">=12" "node": ">=12"
}, },
@@ -13383,6 +13411,7 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"peer": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"
@@ -14358,6 +14387,7 @@
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
"license": "MIT", "license": "MIT",
"peer": true,
"funding": { "funding": {
"url": "https://github.com/sponsors/colinhacks" "url": "https://github.com/sponsors/colinhacks"
} }

View File

@@ -1,4 +1,4 @@
import { addDoc, arrayUnion, collection, doc, Firestore, getDoc, getDocs, Timestamp, updateDoc, DocumentReference, query, where } from "firebase/firestore"; import { addDoc, arrayUnion, collection, doc, DocumentReference, getDoc, getDocs, query, Timestamp, updateDoc, where } from "firebase/firestore";
import { Chantier, Reservation, Ressources, User } from "../class/class"; import { Chantier, Reservation, Ressources, User } from "../class/class";
import { db } from "../firebase_config"; import { db } from "../firebase_config";
@@ -40,10 +40,15 @@ export async function getRessources(): Promise<Ressources[]> {
} }
//ADD RESSOURCES //ADD RESSOURCES
export async function addRessources(ressourceData: Omit<Ressources, 'id'>): Promise<string | null> { export async function addRessources(ressourceData: Ressources): Promise<string | null> {
try { try {
const colRef = collection(db, "ressources"); const ressourcesRef = await addDoc(collection(db, "ressources"), {
const ressourcesRef = await addDoc(colRef, ressourceData); name:ressourceData.name,
type:ressourceData.type,
Image: ressourceData.Image,
quantity: ressourceData.quantity,
});
console.log(`Ressource ajoutée avec ID: ${ressourcesRef.id}`); console.log(`Ressource ajoutée avec ID: ${ressourcesRef.id}`);
return ressourcesRef.id; return ressourcesRef.id;
} catch (err) { } catch (err) {
@@ -219,8 +224,14 @@ async function convertReservation(res: any): Promise<Reservation|null> {
return { return {
id: res.id, id: res.id,
chantier: chantierSnap.data() as Chantier, chantier: {
ressource: ressourceSnap.data() as Ressources, id: chantierSnap.id,
...(chantierSnap.data() as Omit<Chantier, "id">),
},
ressource: {
id: ressourceSnap.id,
...(ressourceSnap.data() as Omit<Ressources, "id">),
},
quantity: data.quantity, quantity: data.quantity,
}; };
} catch (err) { } catch (err) {
@@ -254,6 +265,10 @@ export async function sendNewChantier(chantier:Chantier): Promise<void> {
} }
export async function sendNewReservation(list: Reservation[],chantierId:string): Promise<void> { export async function sendNewReservation(list: Reservation[],chantierId:string): Promise<void> {
list.forEach(reservation => {
console.log("log: " + reservation.ressource.id);
});
const promises = list.map((reservation) => const promises = list.map((reservation) =>
addDoc(collection(db,"Reservation"),{ addDoc(collection(db,"Reservation"),{
chantier: doc(db, "chantier", chantierId), chantier: doc(db, "chantier", chantierId),