Compare commits
7 Commits
reservatio
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
677972626f | ||
|
|
b7eb0be157 | ||
|
|
41b2b58102 | ||
|
|
5271fe1f54 | ||
|
|
3296d301ee | ||
|
|
707ae1dc30 | ||
|
|
0de6462c31 |
11
README.md
11
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,15 +36,20 @@ 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)
|
||||
|
||||
@@ -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,6 +102,7 @@ export default function GestionnaireRessource() {
|
||||
>
|
||||
<ThemedText style={{ textAlign: "center" }}>{t}</ThemedText>
|
||||
</ThemedButton>
|
||||
|
||||
))}
|
||||
|
||||
{/* Bouton "Fermer" remplacé */}
|
||||
@@ -117,14 +136,22 @@ export default function GestionnaireRessource() {
|
||||
</ThemedView>
|
||||
|
||||
{/* Bouton filtre en haut à droite */}
|
||||
<View style={{flexDirection: "row", gap:5}}>
|
||||
<ThemedButton
|
||||
lvl={1}
|
||||
shadow={true}
|
||||
style={{ padding: 10, borderRadius: 8, marginTop: 10 }}
|
||||
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 = {
|
||||
|
||||
@@ -29,3 +29,26 @@ 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,22 +18,21 @@ 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 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