Compare commits
7 Commits
reservatio
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
677972626f | ||
|
|
b7eb0be157 | ||
|
|
41b2b58102 | ||
|
|
5271fe1f54 | ||
|
|
3296d301ee | ||
|
|
707ae1dc30 | ||
|
|
0de6462c31 |
15
README.md
15
README.md
@@ -27,7 +27,7 @@ npx expo start
|
||||
#### Présentation de l'application :
|
||||
|
||||
##### 5 écrans :
|
||||
Accuil :
|
||||
Accueil :
|
||||
- Affiche le chantier sélectionné :
|
||||
- Résumé du chantier
|
||||
- état éditable par l'utilisateur
|
||||
@@ -36,18 +36,23 @@ Accuil :
|
||||
|
||||
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 :
|
||||
|
||||
Permet de voir les différents chantiers sur une carte avec leurs adresses et leur état.
|
||||
|
||||
Ajouter :
|
||||
Permet d'ajouter un chantier ou une ressource (ouvrier,véhicule,outil)
|
||||
##### Fonctionnalité manquante :
|
||||
|
||||
Par manque de temps nous n'avons pas peu finnalité 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)
|
||||
- modifier la quantité totale d'une ressource (ex: restock de ressources)
|
||||
- possibilité de modifier les ressources d'un chantier (ex : réajustement des besoins)
|
||||
- modifier la quantité totale d'une ressource (ex : restock de ressources)
|
||||
- gestion des stocks non finalisée :
|
||||
Un chantier comptabilise du stock uniquement quand il est "En cours", s'il est dans un autre été, ses réservations ne sont pas comptabilisées, donc les autres chantiers peuvent utiliser le stock libéré. Si on le remet l'état à "En cours" et que le stock n'est pas suffisant, alors la quantité disponible du stock passe en négatif.
|
||||
Ce problème peut être corrigé en bloquant le changement d'état si la quantité de stock n'est pas suffisante, mais aurait besoin de la possibilité de modifier les ressources du chantier, ou la quantité des ressources.
|
||||
@@ -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 { IconSymbol } from '@/components/ui/icon-symbol';
|
||||
import { Colors } from '@/constants/theme';
|
||||
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 AddScreen from './addScreen';
|
||||
|
||||
const Tabs = createBottomTabNavigator();
|
||||
import { Tabs } from 'expo-router';
|
||||
import React from 'react';
|
||||
import { useAuthHandler } from '../AuthHandler';
|
||||
import { useUser } from '../ContextUser';
|
||||
|
||||
export default function TabLayout() {
|
||||
const colorScheme = useColorScheme();
|
||||
const { role } = useUser();
|
||||
|
||||
// Handle auth in tabs layout
|
||||
useAuthHandler();
|
||||
|
||||
return (
|
||||
<Tabs.Navigator
|
||||
initialRouteName='explore'
|
||||
screenOptions={{
|
||||
tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint,
|
||||
headerShown: false,
|
||||
tabBarButton: HapticTab,
|
||||
}}>
|
||||
<Tabs screenOptions={{tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint, headerShown: false, tabBarButton: HapticTab}}>
|
||||
<Tabs.Screen name="index" options={{ href: null}}/>
|
||||
<Tabs.Screen name="explore" options={{ href: null }}/>
|
||||
<Tabs.Screen name="templateSreen" options={{ href: null}}/>
|
||||
<Tabs.Screen
|
||||
name="home"
|
||||
component={Home}
|
||||
options={{
|
||||
title: 'Home',
|
||||
tabBarIcon: ({ color }) => (
|
||||
@@ -37,7 +31,6 @@ export default function TabLayout() {
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="gestionnaire_ressource"
|
||||
component={ListMateriel}
|
||||
options={{
|
||||
title: 'Ressources',
|
||||
tabBarIcon: ({ color }) => (
|
||||
@@ -46,34 +39,29 @@ export default function TabLayout() {
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="GestionOuvrier"
|
||||
component={GestionOuvrier}
|
||||
name="gestion_user"
|
||||
options={{
|
||||
title: 'Ouvriers',
|
||||
title: 'Users',
|
||||
tabBarIcon: ({ color }) => <IconSymbol size={28} name="person.fill" color={color} />,
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="explore"
|
||||
component={MapScreen}
|
||||
name="mapScreen"
|
||||
options={{
|
||||
title: 'MapScreen',
|
||||
title: 'Map',
|
||||
tabBarIcon: ({ color }) => <IconSymbol size={28} name="paperplane.fill" color={color} />,
|
||||
}}
|
||||
>
|
||||
</Tabs.Screen>
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="Ajouter"
|
||||
component={AddScreen}
|
||||
name="addScreen"
|
||||
options={{
|
||||
title: 'Ajouter',
|
||||
href: role === 'resp' ? '/(tabs)/addScreen' : null,
|
||||
tabBarIcon: ({ color }) => (
|
||||
<AntDesign name="plus" size={24} color={color} />
|
||||
),
|
||||
}}
|
||||
/>
|
||||
|
||||
|
||||
</Tabs.Navigator>
|
||||
</Tabs>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2,14 +2,11 @@ import { ThemedText } from "@/components/theme/themed-text";
|
||||
import { ThemedTextInput } from "@/components/theme/themed-textinput";
|
||||
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 { useLocalSearchParams, useRouter } from "expo-router";
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import { FlatList, Image, StyleSheet, Text, View } from "react-native";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { FlatList, StyleSheet, Text, View } from "react-native";
|
||||
import { getUsers } from "@/services/ressourcesService";
|
||||
import { useChantier } from "../ContextChantier";
|
||||
import SelectChantier from "@/components/selectChantier";
|
||||
import { Ressources } from "@/class/class";
|
||||
import { getRessources } from "@/services/ressourcesService";
|
||||
import { User } from "@/class/class";
|
||||
|
||||
type Concert = {
|
||||
group: string;
|
||||
@@ -22,19 +19,15 @@ type Concert = {
|
||||
favorite: boolean;
|
||||
};
|
||||
|
||||
export default function GestionOuvrier() {
|
||||
const router = useRouter();
|
||||
const { nom, prenom } = useLocalSearchParams(); // Recup data ecran precedent
|
||||
export default function GestionUser() {
|
||||
const [search, setSearch] = useState("");
|
||||
const { chantier, setChantier } = useChantier();
|
||||
const [artisans, setRessources] = useState<Ressources[]>([]);
|
||||
const [users, setUsers] = useState<User[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
async function loadData() {
|
||||
try {
|
||||
//Nous ne gardons que les Ouvriers, qui peuvent être assignés à un chantier
|
||||
const data = (await getRessources()).filter(u => u.type === "Ouvrier");
|
||||
setRessources(data);
|
||||
const data = (await getUsers());
|
||||
setUsers(data);
|
||||
} catch (error) {
|
||||
console.error("Erreur lors du chargement :", error);
|
||||
}
|
||||
@@ -42,17 +35,15 @@ export default function GestionOuvrier() {
|
||||
loadData();
|
||||
}, []);
|
||||
|
||||
const renderItem = ({ item, index }: { item?: Ressources; index: number }) => {
|
||||
const renderItem = ({ item, index }: { item?: User; index: number }) => {
|
||||
if (!item) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<ThemedView lvl={1} shadow={true} style={styles.card}>
|
||||
<ThemedView lvl={1} style={styles.info}>
|
||||
<Image source={{ uri: item.Image }} style={styles.image} />
|
||||
<ThemedText style={styles.group}>{item.name}</ThemedText>
|
||||
<ThemedText>{item.quantity}</ThemedText>
|
||||
<ThemedText>{item.type}</ThemedText>
|
||||
<ThemedText style={styles.group}>{item.name} {item.last_name}</ThemedText>
|
||||
<ThemedText>{item.role}</ThemedText>
|
||||
</ThemedView>
|
||||
</ThemedView>
|
||||
);
|
||||
@@ -67,7 +58,7 @@ export default function GestionOuvrier() {
|
||||
|
||||
|
||||
<FlatList
|
||||
data={artisans}
|
||||
data={users}
|
||||
renderItem={renderItem}
|
||||
keyExtractor={(_, index) => index.toString()}
|
||||
contentContainerStyle={{ paddingBottom: 40 }}
|
||||
@@ -8,19 +8,25 @@ import { useLocalSearchParams, useRouter } from "expo-router";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { FlatList, Image, StyleSheet, Text, View } from "react-native";
|
||||
import { Ressources } from "../../class/class";
|
||||
import { getRessources } from "../../services/ressourcesService";
|
||||
import { getReservations, getRessources } from "../../services/ressourcesService";
|
||||
import SelectChantier from "@/components/selectChantier";
|
||||
import { useRessources } from "../ContextRessource";
|
||||
import { useChantier } from "../ContextChantier";
|
||||
import { getNbUseRessources, getNbUseRessourcesInChantier, isInChantier } from "@/class/utils";
|
||||
import { useReservations } from "../ContextReservation";
|
||||
|
||||
export default function GestionnaireRessource() {
|
||||
const [search, setSearch] = useState("");
|
||||
const {ressources, setRessources} = useRessources();
|
||||
const {reservations, setReservations} = useReservations();
|
||||
const {chantier, setChantier} = useChantier();
|
||||
const [filterType, setFilterType] = useState("Tout");
|
||||
const [showFilterMenu, setShowFilterMenu] = useState(false);
|
||||
const [filterChantier, setFilterChantier] = useState(false);
|
||||
const router = useRouter();
|
||||
|
||||
useEffect(() => {
|
||||
async function loadData() {
|
||||
async function loadDataRessources() {
|
||||
try {
|
||||
const data = await getRessources();
|
||||
setRessources(data);
|
||||
@@ -28,13 +34,23 @@ export default function GestionnaireRessource() {
|
||||
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 matchName = r.name.toLowerCase().includes(search.toLowerCase());
|
||||
const matchType = filterType === "Tout" || r.type === filterType;
|
||||
return matchName && matchType;
|
||||
|
||||
return matchName && matchType && (!filterChantier || (chantier && isInChantier(r,chantier,reservations)));
|
||||
});
|
||||
|
||||
const renderRessource = ({ item }: { item: Ressources }) => {
|
||||
@@ -43,11 +59,13 @@ export default function GestionnaireRessource() {
|
||||
<ThemedView lvl={1} shadow={true} style={styles.card}>
|
||||
<Image source={{ uri: item.Image }} style={styles.image} />
|
||||
<ThemedView lvl={1} style={styles.info}>
|
||||
<ThemedText>Id : {item.id}</ThemedText>
|
||||
<ThemedText>Nom : {item.name}</ThemedText>
|
||||
<ThemedText>Type : {item.type}</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>
|
||||
);
|
||||
@@ -84,15 +102,16 @@ export default function GestionnaireRessource() {
|
||||
>
|
||||
<ThemedText style={{ textAlign: "center" }}>{t}</ThemedText>
|
||||
</ThemedButton>
|
||||
|
||||
))}
|
||||
|
||||
{/* Bouton "Fermer" remplacé */}
|
||||
<ThemedButton
|
||||
lvl={1}
|
||||
shadow={true}
|
||||
style={{ padding: 10, borderRadius: 8 }}
|
||||
onPress={() => setShowFilterMenu(false)}
|
||||
>
|
||||
{/* Bouton "Fermer" remplacé */}
|
||||
<ThemedButton
|
||||
lvl={1}
|
||||
shadow={true}
|
||||
style={{ padding: 10, borderRadius: 8 }}
|
||||
onPress={() => setShowFilterMenu(false)}
|
||||
>
|
||||
<ThemedText style={{ textAlign: "center" }}>Fermer</ThemedText>
|
||||
</ThemedButton>
|
||||
</ThemedView>
|
||||
@@ -117,14 +136,22 @@ export default function GestionnaireRessource() {
|
||||
</ThemedView>
|
||||
|
||||
{/* Bouton filtre en haut à droite */}
|
||||
<ThemedButton
|
||||
lvl={1}
|
||||
shadow={true}
|
||||
style={{ padding: 10, borderRadius: 8, marginTop: 10 }}
|
||||
onPress={() => setShowFilterMenu(true)}
|
||||
>
|
||||
<ThemedText>{`Filtre: ${filterType}`}</ThemedText>
|
||||
</ThemedButton>
|
||||
<View style={{flexDirection: "row", gap:5}}>
|
||||
<ThemedButton
|
||||
lvl={1}
|
||||
shadow={true}
|
||||
style={styles.button}
|
||||
onPress={() => setShowFilterMenu(true)}
|
||||
>
|
||||
<ThemedText>{`Filtre: ${filterType}`}</ThemedText>
|
||||
</ThemedButton>
|
||||
<ThemedButton style={styles.button}>
|
||||
<ThemedText onPress={() => setFilterChantier(!filterChantier)}>
|
||||
{filterChantier?"chantier courant":"tous"}
|
||||
</ThemedText>
|
||||
</ThemedButton>
|
||||
</View>
|
||||
|
||||
</View>
|
||||
}
|
||||
ListEmptyComponent={
|
||||
@@ -214,4 +241,9 @@ const styles = StyleSheet.create({
|
||||
marginBottom: 20,
|
||||
textAlign: "center",
|
||||
},
|
||||
button:{
|
||||
padding: 10,
|
||||
borderRadius: 8,
|
||||
marginTop: 10
|
||||
},
|
||||
});
|
||||
|
||||
@@ -61,7 +61,7 @@ const region = {
|
||||
<Marker
|
||||
key = {chantier.id}
|
||||
coordinate={{ latitude: chantier.latitude, longitude: chantier.longitude}}
|
||||
title={chantier.adresse}
|
||||
title={chantier.name}
|
||||
description={chantier.etat}
|
||||
/>
|
||||
))}
|
||||
|
||||
45
app/AuthHandler.tsx
Normal file
45
app/AuthHandler.tsx
Normal 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;
|
||||
}, []);
|
||||
}
|
||||
@@ -1,16 +1,11 @@
|
||||
import { ThemedText } from "@/components/theme/themed-text";
|
||||
import { ThemedTextInput } from "@/components/theme/themed-textinput";
|
||||
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 { Button, StyleSheet, View } from "react-native";
|
||||
import { auth } from "../../firebase_config";
|
||||
|
||||
const DEFAULT_ROLE = "resp";
|
||||
|
||||
const LoginScreen: React.FC = () => {
|
||||
const [email, setEmail] = useState<string>("");
|
||||
const [password, setPassword] = useState<string>("");
|
||||
@@ -18,21 +13,11 @@ const LoginScreen: React.FC = () => {
|
||||
const handleLogin = async () => {
|
||||
try {
|
||||
await signInWithEmailAndPassword(auth, email, password);
|
||||
router.replace("/(tabs)");
|
||||
} catch (error: any) {
|
||||
alert(error.message);
|
||||
}
|
||||
};
|
||||
|
||||
/*const handleRegister = async () => {
|
||||
try {
|
||||
await createUserWithEmailAndPassword(auth, email, password);
|
||||
router.replace("/(tabs)");
|
||||
} catch (error: any) {
|
||||
alert(error.message);
|
||||
}
|
||||
}; */
|
||||
|
||||
return (
|
||||
<ThemedView lvl={1} style={styles.container}>
|
||||
<ThemedText style={styles.title}>Se connecter</ThemedText>
|
||||
@@ -45,7 +30,6 @@ const LoginScreen: React.FC = () => {
|
||||
value={email}
|
||||
onChangeText={setEmail}
|
||||
autoCapitalize="none"
|
||||
|
||||
/>
|
||||
<ThemedTextInput
|
||||
lvl = {2}
|
||||
@@ -59,7 +43,6 @@ const LoginScreen: React.FC = () => {
|
||||
/>
|
||||
<Button title="Se connecter" onPress={handleLogin} />
|
||||
<View style={{ height: 10 }} />
|
||||
{/* <Button title="S'inscrire" onPress={handleRegister} /> */}
|
||||
</ThemedView>
|
||||
);
|
||||
};
|
||||
@@ -76,7 +59,6 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
input: {
|
||||
borderWidth: 1,
|
||||
//borderColor: "#ccc",
|
||||
borderRadius: 8,
|
||||
padding: 10,
|
||||
marginBottom: 10,
|
||||
|
||||
@@ -30,8 +30,8 @@ export type Ressources = {
|
||||
type: string; //"Machine","Outil","Ouvrier"
|
||||
Image: string;
|
||||
quantity: number;
|
||||
available_quantity: number;
|
||||
allocation: Reservation[];
|
||||
//available_quantity: number;
|
||||
//allocation: Reservation[];
|
||||
};
|
||||
|
||||
export type Reservation = {
|
||||
|
||||
@@ -28,4 +28,27 @@ export function getNbUseRessources(ressource:Ressources, allReservations:Reserva
|
||||
}
|
||||
})
|
||||
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;
|
||||
}
|
||||
@@ -1,24 +1,17 @@
|
||||
import ChantierSummary from '@/components/chantierSummary';
|
||||
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 { useUser } from '@/app/ContextUser';
|
||||
import { getRessources, getUsers, addChantier , addRessources} from '@/services/ressourcesService';
|
||||
import { Chantier, Ressources, User } from '@/class/class';
|
||||
import { ThemedText } from '@/components/theme/themed-text';
|
||||
import { Ressources } from '@/class/class';
|
||||
import { ThemedButton } from '@/components/theme/themed-button';
|
||||
import { ThemedText } from '@/components/theme/themed-text';
|
||||
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 SelectChafChantier from '@/components/add/select/selectChefChantier';
|
||||
import SelectMachine from '@/components/selectMachine';
|
||||
|
||||
|
||||
type Dictionary = {
|
||||
@@ -66,9 +59,9 @@ export default function AddRessource({ressourceType, ...otherProps }: Props) {
|
||||
name: nom,
|
||||
type : ressourceType,
|
||||
quantity : parseInt(quantite),
|
||||
available_quantity : parseInt(quantite),
|
||||
//available_quantity : parseInt(quantite),
|
||||
Image : "",
|
||||
allocation : [],
|
||||
//allocation : [],
|
||||
};
|
||||
const id = await addRessources(nouvelleRessource);
|
||||
|
||||
|
||||
@@ -18,23 +18,22 @@ export default function ChantierSummary({data,style , ...otherProps }: Props) {
|
||||
{data.chantier ? (
|
||||
<ThemedView lvl={4} style={styles.chantier}>
|
||||
<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 style={{flex: 1}}>
|
||||
<ThemedText selectable={true}>Id: {data.chantier.id}</ThemedText>
|
||||
<ThemedText selectable={true}>Objet: {data.chantier.name}</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}>État: {data.chantier.etat}</ThemedText>
|
||||
<ThemedText selectable={true}>equipe:
|
||||
{getNbItemReservation(data.chantier.equipe)} ({data.chantier.equipe.length} type{data.chantier.equipe.length>1&&"s"})
|
||||
<ThemedText selectable={true}>
|
||||
equipe: {getNbItemReservation(data.chantier.equipe)} ({data.chantier.equipe.length} type{data.chantier.equipe.length>1&&"s"})
|
||||
</ThemedText>
|
||||
<ThemedText selectable={true}>materiel:
|
||||
{getNbItemReservation(data.chantier.materiel)} ({data.chantier.materiel.length} type{data.chantier.materiel.length>1&&"s"})
|
||||
<ThemedText selectable={true}>
|
||||
materiel: {getNbItemReservation(data.chantier.materiel)} ({data.chantier.materiel.length} type{data.chantier.materiel.length>1&&"s"})
|
||||
</ThemedText>
|
||||
<ThemedText selectable={true}>
|
||||
vehicules: {getNbItemReservation(data.chantier.vehicules)} ({data.chantier.vehicules.length} type{data.chantier.vehicules.length>1&&"s"})
|
||||
</ThemedText>
|
||||
<ThemedText selectable={true}>vehicules:
|
||||
{getNbItemReservation(data.chantier.vehicules)} ({data.chantier.vehicules.length} type{data.chantier.vehicules.length>1&&"s"})
|
||||
</ThemedText>
|
||||
</View>
|
||||
</ThemedView>
|
||||
) :
|
||||
|
||||
@@ -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} />
|
||||
</View>
|
||||
<View style={{flex: 1}}>
|
||||
<ThemedText>Renovation: {item.name}</ThemedText>
|
||||
<ThemedText>Objet: {item.name}</ThemedText>
|
||||
<ThemedText>Adresse: {item.adresse}</ThemedText>
|
||||
<ThemedText>Chef de chantier: {item.chef.last_name}{" "}{item.chef.name}</ThemedText>
|
||||
<ThemedText>État: {item.etat}</ThemedText>
|
||||
@@ -138,7 +138,7 @@ export default function SelectChantier() {
|
||||
<ThemedView lvl={2} shadow={true} style={styles.window}>
|
||||
<AnimatedThemedButton style={animatedButtonStyle} lvl={isOpen ? 1 : 1} onPress={() => onPressOpen()}>
|
||||
<ThemedText style={styles.buttonText}>
|
||||
{isOpen ? "Fermer" : (chantier!=null ? chantier.adresse : "Chantier")}
|
||||
{isOpen ? "Fermer" : (chantier!=null ? chantier.name : "Chantier")}
|
||||
</ThemedText>
|
||||
</AnimatedThemedButton>
|
||||
{isOpen && (
|
||||
|
||||
@@ -121,7 +121,7 @@ const styles = StyleSheet.create({
|
||||
windowBox:{
|
||||
zIndex: 2,
|
||||
//backgroundColor: '#00FFFF40',
|
||||
width:"30%",
|
||||
width:"35%",
|
||||
padding: 10,
|
||||
paddingLeft: 0,
|
||||
//overflow: 'hidden',
|
||||
|
||||
32
package-lock.json
generated
32
package-lock.json
generated
@@ -90,6 +90,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz",
|
||||
"integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.27.1",
|
||||
"@babel/generator": "^7.28.3",
|
||||
@@ -1471,6 +1472,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz",
|
||||
"integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
@@ -2329,6 +2331,7 @@
|
||||
"version": "0.14.6",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.14.6.tgz",
|
||||
"integrity": "sha512-4uyt8BOrBsSq6i4yiOV/gG6BnnrvTeyymlNcaN/dKvyU1GoolxAafvIvaNP1RCGPlNab3OuE4MKUQuv2lH+PLQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.7.0",
|
||||
"@firebase/logger": "0.5.0",
|
||||
@@ -2394,6 +2397,7 @@
|
||||
"version": "0.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.5.6.tgz",
|
||||
"integrity": "sha512-YYGARbutghQY4zZUWMYia0ib0Y/rb52y72/N0z3vglRHL7ii/AaK9SA7S/dzScVOlCdnbHXz+sc5Dq+r8fwFAg==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@firebase/app": "0.14.6",
|
||||
"@firebase/component": "0.7.0",
|
||||
@@ -2409,7 +2413,8 @@
|
||||
"version": "0.9.3",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.3.tgz",
|
||||
"integrity": "sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw==",
|
||||
"license": "Apache-2.0"
|
||||
"license": "Apache-2.0",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@firebase/auth": {
|
||||
"version": "1.11.1",
|
||||
@@ -2859,6 +2864,7 @@
|
||||
"integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
@@ -3894,6 +3900,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-7.1.25.tgz",
|
||||
"integrity": "sha512-zQeWK9txDePWbYfqTs0C6jeRdJTm/7VhQtW/1IbJNDi9/rFIRzZule8bdQPAnf8QWUsNujRmi1J9OG/hhfbalg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@react-navigation/core": "^7.13.6",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
@@ -4096,6 +4103,7 @@
|
||||
"integrity": "sha512-Qec1E3mhALmaspIrhWt9jkQMNdw6bReVu64mjvhbhq2NFPftLPVr+l1SZgmw/66WwBNpDh7ao5AT6gF5v41PFA==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
@@ -4167,6 +4175,7 @@
|
||||
"integrity": "sha512-n1H6IcDhmmUEG7TNVSspGmiHHutt7iVKtZwRppD7e04wha5MrkV1h3pti9xQLcCMt6YWsncpoT0HMjkH1FNwWQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.46.0",
|
||||
"@typescript-eslint/types": "8.46.0",
|
||||
@@ -4729,6 +4738,7 @@
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@@ -5414,6 +5424,7 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"baseline-browser-mapping": "^2.8.9",
|
||||
"caniuse-lite": "^1.0.30001746",
|
||||
@@ -6553,6 +6564,7 @@
|
||||
"integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.8.0",
|
||||
"@eslint-community/regexpp": "^4.12.1",
|
||||
@@ -6750,6 +6762,7 @@
|
||||
"integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@rtsao/scc": "^1.1.0",
|
||||
"array-includes": "^3.1.9",
|
||||
@@ -6988,6 +7001,7 @@
|
||||
"resolved": "https://registry.npmjs.org/expo/-/expo-54.0.13.tgz",
|
||||
"integrity": "sha512-F1puKXzw8ESnsbvaKdXtcIiyYLQ2kUHqP8LuhgtJS1wm6w55VhtOPg8yl/0i8kPbTA0YfD+KYdXjSfhPXgUPxw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.0",
|
||||
"@expo/cli": "54.0.11",
|
||||
@@ -7055,6 +7069,7 @@
|
||||
"resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-18.0.9.tgz",
|
||||
"integrity": "sha512-sqoXHAOGDcr+M9NlXzj1tGoZyd3zxYDy215W6E0Z0n8fgBaqce9FAYQE2bu5X4G629AYig5go7U6sQz7Pjcm8A==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@expo/config": "~12.0.9",
|
||||
"@expo/env": "~2.0.7"
|
||||
@@ -7079,6 +7094,7 @@
|
||||
"resolved": "https://registry.npmjs.org/expo-font/-/expo-font-14.0.9.tgz",
|
||||
"integrity": "sha512-xCoQbR/36qqB6tew/LQ6GWICpaBmHLhg/Loix5Rku/0ZtNaXMJv08M9o1AcrdiGTn/Xf/BnLu6DgS45cWQEHZg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fontfaceobserver": "^2.1.0"
|
||||
},
|
||||
@@ -7150,6 +7166,7 @@
|
||||
"resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-8.0.8.tgz",
|
||||
"integrity": "sha512-MyeMcbFDKhXh4sDD1EHwd0uxFQNAc6VCrwBkNvvvufUsTYFq3glTA9Y8a+x78CPpjNqwNAamu74yIaIz7IEJyg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"expo-constants": "~18.0.8",
|
||||
"invariant": "^2.2.4"
|
||||
@@ -11394,6 +11411,7 @@
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
|
||||
"integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@@ -11413,6 +11431,7 @@
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
|
||||
"integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"scheduler": "^0.26.0"
|
||||
},
|
||||
@@ -11449,6 +11468,7 @@
|
||||
"resolved": "https://registry.npmjs.org/react-native/-/react-native-0.81.4.tgz",
|
||||
"integrity": "sha512-bt5bz3A/+Cv46KcjV0VQa+fo7MKxs17RCcpzjftINlen4ZDUl0I6Ut+brQ2FToa5oD0IB0xvQHfmsg2EDqsZdQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@jest/create-cache-key-function": "^29.7.0",
|
||||
"@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",
|
||||
"integrity": "sha512-0msfJ1vRxXKVgTgvL+1ZOoYw3/0z1R+Ked0+udoJhyplC2jbVKIJ8Z1bzWdpQRCV3QcQ87Op0zJVE5DhKK2A0A==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@egjs/hammerjs": "^2.0.17",
|
||||
"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",
|
||||
"integrity": "sha512-GP8wsi1u3nqvC1fMab/m8gfFwFyldawElCcUSBJQgfrXeLmsPPUOpDw44lbLeCpcwUuLa05WTVePdTEwCLTUZg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"react-native-is-edge-to-edge": "^1.2.1",
|
||||
"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",
|
||||
"integrity": "sha512-4XGqMNj5qjUTYywJqpdWZ9IG8jgkS3h06sfVjfw5yZQZfWnRFXczi0GnYyFyCc2EBps/qFmoCH8fez//WumdVg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
"react-native": "*"
|
||||
@@ -11598,6 +11621,7 @@
|
||||
"resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-4.16.0.tgz",
|
||||
"integrity": "sha512-yIAyh7F/9uWkOzCi1/2FqvNvK6Wb9Y1+Kzn16SuGfN9YFJDTbwlzGRvePCNTOX0recpLQF3kc2FmvMUhyTCH1Q==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"react-freeze": "^1.0.0",
|
||||
"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",
|
||||
"integrity": "sha512-BeNsgwwe4AXUFPAoFU+DKjJ+CVQa3h54zYX77p7GVZrXiiNo3vl03WYDYVEy5R2J2HOPInXtQZB5gmj3vuzrKg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.18.6",
|
||||
"@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",
|
||||
"integrity": "sha512-lJG6Uk9YuojjEX/tQrCbcbmpdLCSFxDK1rJlkDhgqkVi1KZzG7cdcBFQRqyNOOzR9Y0CXNuldmtWTGOyM0k0+w==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/plugin-transform-arrow-functions": "^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",
|
||||
"integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@@ -13177,6 +13204,7 @@
|
||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -13383,6 +13411,7 @@
|
||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@@ -14358,6 +14387,7 @@
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
|
||||
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
|
||||
@@ -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 { db } from "../firebase_config";
|
||||
|
||||
@@ -40,10 +40,15 @@ export async function getRessources(): Promise<Ressources[]> {
|
||||
}
|
||||
|
||||
//ADD RESSOURCES
|
||||
export async function addRessources(ressourceData: Omit<Ressources, 'id'>): Promise<string | null> {
|
||||
export async function addRessources(ressourceData: Ressources): Promise<string | null> {
|
||||
try {
|
||||
const colRef = collection(db, "ressources");
|
||||
const ressourcesRef = await addDoc(colRef, ressourceData);
|
||||
const ressourcesRef = await addDoc(collection(db, "ressources"), {
|
||||
name:ressourceData.name,
|
||||
type:ressourceData.type,
|
||||
Image: ressourceData.Image,
|
||||
quantity: ressourceData.quantity,
|
||||
});
|
||||
|
||||
console.log(`Ressource ajoutée avec ID: ${ressourcesRef.id}`);
|
||||
return ressourcesRef.id;
|
||||
} catch (err) {
|
||||
@@ -219,8 +224,14 @@ async function convertReservation(res: any): Promise<Reservation|null> {
|
||||
|
||||
return {
|
||||
id: res.id,
|
||||
chantier: chantierSnap.data() as Chantier,
|
||||
ressource: ressourceSnap.data() as Ressources,
|
||||
chantier: {
|
||||
id: chantierSnap.id,
|
||||
...(chantierSnap.data() as Omit<Chantier, "id">),
|
||||
},
|
||||
ressource: {
|
||||
id: ressourceSnap.id,
|
||||
...(ressourceSnap.data() as Omit<Ressources, "id">),
|
||||
},
|
||||
quantity: data.quantity,
|
||||
};
|
||||
} catch (err) {
|
||||
@@ -254,6 +265,10 @@ export async function sendNewChantier(chantier:Chantier): 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) =>
|
||||
addDoc(collection(db,"Reservation"),{
|
||||
chantier: doc(db, "chantier", chantierId),
|
||||
|
||||
Reference in New Issue
Block a user