gestion des ressources fonctionnelle, mais pas fini
This commit is contained in:
32
README.md
32
README.md
@@ -11,7 +11,8 @@
|
|||||||
|
|
||||||
Lien du git : gitlab2.istic.univ-rennes1.fr/trochas/mmm-projet
|
Lien du git : gitlab2.istic.univ-rennes1.fr/trochas/mmm-projet
|
||||||
|
|
||||||
Différentes commandes a effectuer pour lancer le projet:
|
|
||||||
|
#### Différentes commandes a effectuer pour lancer le projet:
|
||||||
|
|
||||||
npx expo install react-native-maps@1.9.0
|
npx expo install react-native-maps@1.9.0
|
||||||
npm install react-native-maps @react-navigation/native @react-navigation/bottom-tabs react-native-safe-area-context react-native-screens firebase
|
npm install react-native-maps @react-navigation/native @react-navigation/bottom-tabs react-native-safe-area-context react-native-screens firebase
|
||||||
@@ -21,3 +22,32 @@ npx expo install expo-image-picker
|
|||||||
npx expo install expo-location
|
npx expo install expo-location
|
||||||
|
|
||||||
npx expo start
|
npx expo start
|
||||||
|
|
||||||
|
|
||||||
|
#### Présentation de l'application :
|
||||||
|
|
||||||
|
##### 5 écrans :
|
||||||
|
Accuil :
|
||||||
|
- Affiche le chantier sélectionné :
|
||||||
|
- Résumé du chantier
|
||||||
|
- état éditable par l'utilisateur
|
||||||
|
- Liste d'anomalies, possibilité d'en ajouter ou de les supprimer
|
||||||
|
- Sélectionner un chantier via le bouton en haut à gauche.
|
||||||
|
|
||||||
|
Ressources :
|
||||||
|
|
||||||
|
Ouvriers :
|
||||||
|
|
||||||
|
MapScreen :
|
||||||
|
|
||||||
|
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é
|
||||||
|
|
||||||
|
- 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.
|
||||||
@@ -23,9 +23,11 @@ export default function Home() {
|
|||||||
<View style={{width:"100%", position: 'absolute'}}>
|
<View style={{width:"100%", position: 'absolute'}}>
|
||||||
<SelectChantier></SelectChantier>
|
<SelectChantier></SelectChantier>
|
||||||
</View>
|
</View>
|
||||||
|
{chantier&&
|
||||||
<View style={{width:"100%", position: 'absolute',marginLeft:"50%"}}>
|
<View style={{width:"100%", position: 'absolute',marginLeft:"50%"}}>
|
||||||
<SetStatus></SetStatus>
|
<SetStatus></SetStatus>
|
||||||
</View>
|
</View>
|
||||||
|
}
|
||||||
<ScrollView>
|
<ScrollView>
|
||||||
<View style={{paddingTop:60}}>
|
<View style={{paddingTop:60}}>
|
||||||
<ChantierSummary style={styles.summary} data={{ chantier }} />
|
<ChantierSummary style={styles.summary} data={{ chantier }} />
|
||||||
|
|||||||
33
app/ContextReservation.tsx
Normal file
33
app/ContextReservation.tsx
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import { Reservation } from "@/class/class";
|
||||||
|
import { createContext, ReactNode, useContext, useMemo, useState } from "react";
|
||||||
|
|
||||||
|
type ReservationContextType = {
|
||||||
|
reservations: Reservation[];
|
||||||
|
setReservations: (list: Reservation[]) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ReservationsContext = createContext<ReservationContextType | null>(null);
|
||||||
|
|
||||||
|
type ReservationsProviderProps = {
|
||||||
|
children: ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ReservationsProvider = ({ children }: ReservationsProviderProps) => {
|
||||||
|
const [reservations, setReservations] = useState<Reservation[]>([]);
|
||||||
|
|
||||||
|
const value = useMemo(() => ({ reservations, setReservations }), [reservations]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ReservationsContext.Provider value={value}>
|
||||||
|
{children}
|
||||||
|
</ReservationsContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useReservations = () => {
|
||||||
|
const context = useContext(ReservationsContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error("useRessources doit être utilisé dans <ReservationsContext>");
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
||||||
@@ -16,9 +16,11 @@ import { Platform, UIManager } from 'react-native';
|
|||||||
import { ChantierProvider } from "./ContextChantier";
|
import { ChantierProvider } from "./ContextChantier";
|
||||||
import { UserProvider } from "./ContextUser";
|
import { UserProvider } from "./ContextUser";
|
||||||
import { RessourcesProvider } from "./ContextRessource";
|
import { RessourcesProvider } from "./ContextRessource";
|
||||||
|
import { ReservationsProvider } from "./ContextReservation";
|
||||||
import LoginScreen from "./login/login";
|
import LoginScreen from "./login/login";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const unstable_settings = {
|
export const unstable_settings = {
|
||||||
anchor: "(tabs)",
|
anchor: "(tabs)",
|
||||||
};
|
};
|
||||||
@@ -60,6 +62,7 @@ export default function RootLayout() {
|
|||||||
<UserProvider>
|
<UserProvider>
|
||||||
<ChantierProvider>
|
<ChantierProvider>
|
||||||
<RessourcesProvider>
|
<RessourcesProvider>
|
||||||
|
<ReservationsProvider>
|
||||||
<ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
|
<ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
|
||||||
<Stack>
|
<Stack>
|
||||||
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
|
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
|
||||||
@@ -72,6 +75,7 @@ export default function RootLayout() {
|
|||||||
</Stack>
|
</Stack>
|
||||||
<StatusBar style="auto" />
|
<StatusBar style="auto" />
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
|
</ReservationsProvider>
|
||||||
</RessourcesProvider>
|
</RessourcesProvider>
|
||||||
</ChantierProvider>
|
</ChantierProvider>
|
||||||
</UserProvider>
|
</UserProvider>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export type User = {
|
|||||||
export type Ressources = {
|
export type Ressources = {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
type: string; //"machine","outil","ouvrier"
|
type: string; //"Machine","Outil","Ouvrier"
|
||||||
Image: string;
|
Image: string;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
available_quantity: number;
|
available_quantity: number;
|
||||||
|
|||||||
31
class/utils.tsx
Normal file
31
class/utils.tsx
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { Reservation,Chantier,User, Ressources } from "./class";
|
||||||
|
|
||||||
|
export function getNbItemReservation(reservations:Reservation[]):number{
|
||||||
|
var res = 0;
|
||||||
|
reservations.forEach(reserv => {
|
||||||
|
res += reserv.quantity;
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function getReservationOfRessource(ressource:Ressources, allReservations:Reservation[]):Reservation[]{
|
||||||
|
const res:Reservation[] = [];
|
||||||
|
allReservations.forEach(reserv => {
|
||||||
|
if(reserv.ressource.name===ressource.name){
|
||||||
|
res.push(reserv);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function getNbUseRessources(ressource:Ressources, allReservations:Reservation[]):number{
|
||||||
|
var res:number = 0;
|
||||||
|
getReservationOfRessource(ressource,allReservations).forEach(reserv => {
|
||||||
|
if(reserv.chantier.etat==="En cours"){
|
||||||
|
res+=reserv.quantity;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return res;
|
||||||
|
}
|
||||||
@@ -90,6 +90,7 @@ export default function AddRessource({ressourceType, ...otherProps }: Props) {
|
|||||||
function onCancel(): void {
|
function onCancel(): void {
|
||||||
setOpenConfirmation(false);
|
setOpenConfirmation(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isValidRessource():Boolean{
|
function isValidRessource():Boolean{
|
||||||
return nom!= "" && quantite != ""
|
return nom!= "" && quantite != ""
|
||||||
}
|
}
|
||||||
@@ -129,7 +130,7 @@ export default function AddRessource({ressourceType, ...otherProps }: Props) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemedView lvl={3} style={styles.back}>
|
<ThemedView lvl={3} style={styles.back}>
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
{editMode &&
|
{editMode &&
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
import { Chantier, Ressources } from '@/class/class';
|
import { Chantier, Ressources } from '@/class/class';
|
||||||
import { ThemedView, } from '@/components/theme/themed-view';
|
import { ThemedView, } from '@/components/theme/themed-view';
|
||||||
import React, { useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { Image, StyleProp, StyleSheet, View, ViewStyle } from 'react-native';
|
import { Image, StyleProp, StyleSheet, View, ViewStyle } from 'react-native';
|
||||||
import { ThemedText } from '@/components/theme/themed-text';
|
import { ThemedText } from '@/components/theme/themed-text';
|
||||||
import { ThemedButton } from '@/components/theme/themed-button';
|
import { ThemedButton } from '@/components/theme/themed-button';
|
||||||
|
import { getNbUseRessources } from '@/class/utils';
|
||||||
|
import { useReservations } from '@/app/ContextReservation';
|
||||||
|
import { getReservations } from '@/services/ressourcesService';
|
||||||
|
|
||||||
type RessourcesQte = [Ressources, number];
|
type RessourcesQte = [Ressources, number];
|
||||||
|
|
||||||
@@ -16,11 +19,11 @@ type Props = {
|
|||||||
|
|
||||||
export default function RessourceSummary({ressource: ressource,qte,style,sendRessource: sendRessource, ...otherProps }: Props) {
|
export default function RessourceSummary({ressource: ressource,qte,style,sendRessource: sendRessource, ...otherProps }: Props) {
|
||||||
|
|
||||||
|
const { reservations, setReservations } = useReservations();
|
||||||
const [count,setCount] = useState(qte);
|
const [count,setCount] = useState(qte);
|
||||||
|
|
||||||
function onPressAdd(ressource: Ressources): void {
|
function onPressAdd(ressource: Ressources): void {
|
||||||
if(count<ressource.quantity){
|
if(count<ressource.quantity-getNbUseRessources(ressource,reservations)){
|
||||||
setCount(count+1);
|
setCount(count+1);
|
||||||
sendRessource([ressource, count+1]);
|
sendRessource([ressource, count+1]);
|
||||||
}
|
}
|
||||||
@@ -33,20 +36,28 @@ export default function RessourceSummary({ressource: ressource,qte,style,sendRes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function loadReservations() {
|
||||||
|
const list = await getReservations();
|
||||||
|
setReservations(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadReservations();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<View style={style}>
|
<View style={style}>
|
||||||
<ThemedView lvl={2} border={3} style={{padding:10,width:"100%",borderRadius:10,flexDirection: 'row',justifyContent: 'space-between',}}>
|
<ThemedView lvl={2} border={3} style={{padding:10,width:"100%",borderRadius:10,flexDirection: 'row',justifyContent: 'space-between',}}>
|
||||||
<View>
|
<View>
|
||||||
<ThemedText>{ressource.id}</ThemedText>
|
<ThemedText>Nom : {ressource.name}</ThemedText>
|
||||||
<ThemedText>{ressource.name}</ThemedText>
|
<ThemedText>Restant : {ressource.quantity-getNbUseRessources(ressource,reservations)}/{ressource.quantity}</ThemedText>
|
||||||
<ThemedText>{ressource.quantity}</ThemedText>
|
|
||||||
<ThemedText>{ressource.type}</ThemedText>
|
|
||||||
</View>
|
</View>
|
||||||
<View style={{alignItems:"center"}}>
|
<View style={{alignItems:"center"}}>
|
||||||
<ThemedButton style={styles.button} lvl={3} onPress={() => onPressAdd(ressource)}>
|
<ThemedButton style={styles.button} lvl={3} onPress={() => onPressAdd(ressource)}>
|
||||||
<ThemedText>+</ThemedText>
|
<ThemedText>+</ThemedText>
|
||||||
</ThemedButton>
|
</ThemedButton>
|
||||||
<ThemedText>{count}/{ressource.quantity}</ThemedText>
|
<ThemedText>{count}/{ressource.quantity-getNbUseRessources(ressource,reservations)}</ThemedText>
|
||||||
<ThemedButton style={styles.button} lvl={3} onPress={() => onPressSub(ressource)}>
|
<ThemedButton style={styles.button} lvl={3} onPress={() => onPressSub(ressource)}>
|
||||||
<ThemedText>-</ThemedText>
|
<ThemedText>-</ThemedText>
|
||||||
</ThemedButton>
|
</ThemedButton>
|
||||||
|
|||||||
@@ -67,10 +67,10 @@ export default function Anomaly({data,style}: Props) {
|
|||||||
<View style={styles.addContainer}>
|
<View style={styles.addContainer}>
|
||||||
<TextInput style={styles.input} placeholder="Nouvelle anomalie..." value={newAnomaly} onChangeText={setNewAnomaly} />
|
<TextInput style={styles.input} placeholder="Nouvelle anomalie..." value={newAnomaly} onChangeText={setNewAnomaly} />
|
||||||
<TouchableOpacity style={styles.addButton} onPress={handleAdd}>
|
<TouchableOpacity style={styles.addButton} onPress={handleAdd}>
|
||||||
<Text style={styles.addButtonText}>Ajouter</Text>
|
<ThemedText style={styles.addButtonText}>Ajouter</ThemedText>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity onPress={selectImage} style={styles.addButton}>
|
<TouchableOpacity onPress={selectImage} style={styles.addButton}>
|
||||||
<Text style={styles.addButton}>Choisir une image</Text>
|
<ThemedText style={styles.addButton}>Choisir une image</ThemedText>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
{imageUri && (
|
{imageUri && (
|
||||||
<Image source={{ uri: imageUri }} style={styles.image} />
|
<Image source={{ uri: imageUri }} style={styles.image} />
|
||||||
@@ -151,13 +151,11 @@ const styles = StyleSheet.create({
|
|||||||
marginRight: 8,
|
marginRight: 8,
|
||||||
},
|
},
|
||||||
addButton: {
|
addButton: {
|
||||||
color: "white",
|
|
||||||
paddingVertical: 8,
|
paddingVertical: 8,
|
||||||
paddingHorizontal: 12,
|
paddingHorizontal: 12,
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
},
|
},
|
||||||
addButtonText: {
|
addButtonText: {
|
||||||
color: "white",
|
|
||||||
fontWeight: "bold",
|
fontWeight: "bold",
|
||||||
},
|
},
|
||||||
image: { width: 200, height: 200, borderRadius: 10 }
|
image: { width: 200, height: 200, borderRadius: 10 }
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { ThemedView, } from '@/components/theme/themed-view';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Image, StyleProp, StyleSheet, View, ViewStyle } from 'react-native';
|
import { Image, StyleProp, StyleSheet, View, ViewStyle } from 'react-native';
|
||||||
import { ThemedText } from './theme/themed-text';
|
import { ThemedText } from './theme/themed-text';
|
||||||
|
import { getNbItemReservation } from '@/class/utils';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
data: {
|
data: {
|
||||||
@@ -20,9 +21,20 @@ export default function ChantierSummary({data,style , ...otherProps }: Props) {
|
|||||||
<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 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}>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:
|
||||||
|
{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>
|
||||||
|
<ThemedText selectable={true}>vehicules:
|
||||||
|
{getNbItemReservation(data.chantier.vehicules)} ({data.chantier.vehicules.length} type{data.chantier.vehicules.length>1&&"s"})
|
||||||
|
</ThemedText>
|
||||||
</View>
|
</View>
|
||||||
</ThemedView>
|
</ThemedView>
|
||||||
) :
|
) :
|
||||||
@@ -42,7 +54,7 @@ const styles = StyleSheet.create({
|
|||||||
borderRadius: 10,
|
borderRadius: 10,
|
||||||
//borderWidth: 1,
|
//borderWidth: 1,
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
height: 150,
|
//height: 150,
|
||||||
gap: 10,
|
gap: 10,
|
||||||
},
|
},
|
||||||
image:{
|
image:{
|
||||||
|
|||||||
@@ -65,14 +65,14 @@ export default function SelectChantier() {
|
|||||||
open.value = withTiming(isOpen ? 1 : 0);
|
open.value = withTiming(isOpen ? 1 : 0);
|
||||||
}, [isOpen]);
|
}, [isOpen]);
|
||||||
|
|
||||||
useEffect(() => {
|
/*useEffect(() => {
|
||||||
async function loadChantiers() {
|
async function loadChantiers() {
|
||||||
const list = await getChantiers();
|
const list = await getChantiers();
|
||||||
setChantiers(list);
|
setChantiers(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
loadChantiers();
|
loadChantiers();
|
||||||
}, []);
|
}, []);*/
|
||||||
|
|
||||||
const filteredChantiers = chantiers.filter((chantier) => {
|
const filteredChantiers = chantiers.filter((chantier) => {
|
||||||
var keyWords:string[] = search.toLowerCase().split(" ") ;
|
var keyWords:string[] = search.toLowerCase().split(" ") ;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { addDoc, arrayUnion, collection, doc, Firestore, getDoc, getDocs, Timestamp, updateDoc, DocumentReference } from "firebase/firestore";
|
import { addDoc, arrayUnion, collection, doc, Firestore, getDoc, getDocs, Timestamp, updateDoc, DocumentReference, query, 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";
|
||||||
|
|
||||||
@@ -53,10 +53,14 @@ export async function addRessources(ressourceData: Omit<Ressources, 'id'>): Prom
|
|||||||
}
|
}
|
||||||
///////////////////////////////////CHANTIER/////////////////////////////////
|
///////////////////////////////////CHANTIER/////////////////////////////////
|
||||||
export async function getChantiers(): Promise<Chantier[]> {
|
export async function getChantiers(): Promise<Chantier[]> {
|
||||||
const snap = await getDocs(collection(db, "chantier"));
|
|
||||||
const chantiers: Chantier[] = [];
|
const chantiers: Chantier[] = [];
|
||||||
|
try {
|
||||||
|
const snap = await getDocs(collection(db, "chantier"));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (const docSnap of snap.docs) {
|
for (const docSnap of snap.docs) {
|
||||||
|
try {
|
||||||
const data = docSnap.data();
|
const data = docSnap.data();
|
||||||
//Faut convertir les Timestamp en Date ( merci à firebase :) )
|
//Faut convertir les Timestamp en Date ( merci à firebase :) )
|
||||||
const dateDep = data.dateDep instanceof Timestamp ? data.dateDep.toDate() : new Date(data.dateDep);
|
const dateDep = data.dateDep instanceof Timestamp ? data.dateDep.toDate() : new Date(data.dateDep);
|
||||||
@@ -67,40 +71,23 @@ export async function getChantiers(): Promise<Chantier[]> {
|
|||||||
chef = chefSnap.data() as User;
|
chef = chefSnap.data() as User;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
const equipe:Reservation[] = [];
|
||||||
let equipe: Reservation[] = [];
|
const vehicules:Reservation[] = [];
|
||||||
if (Array.isArray(data.equipe)) {
|
const materiel:Reservation[] = [];
|
||||||
equipe = await Promise.all(
|
const all:Reservation[] = await getReservationsByChantier(docSnap.id);
|
||||||
data.equipe.map(async (ref: any) => {
|
|
||||||
const snap = await getDoc(ref);
|
|
||||||
return snap.exists() ? (snap.data() as Reservation) : null;
|
|
||||||
})
|
|
||||||
).then(list => list.filter(x => x !== null)) as Reservation[];
|
|
||||||
}
|
|
||||||
|
|
||||||
let vehicules: Reservation[] = [];
|
all.forEach(element => {
|
||||||
if (Array.isArray(data.vehicules)) {
|
if(element.ressource.type==="Ouvrier"){
|
||||||
vehicules = await Promise.all(
|
equipe.push(element)
|
||||||
data.vehicules.map(async (ref: any) => {
|
|
||||||
const snap = await getDoc(ref);
|
|
||||||
return snap.exists() ? (snap.data() as Reservation) : null;
|
|
||||||
})
|
|
||||||
).then(list => list.filter(x => x !== null)) as Reservation[];
|
|
||||||
}
|
}
|
||||||
|
else if(element.ressource.type==="Machine"){
|
||||||
|
vehicules.push(element)
|
||||||
|
}
|
||||||
|
else if(element.ressource.type==="Outil"){
|
||||||
|
materiel.push(element)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let materiel: Reservation[] = [];
|
|
||||||
if (Array.isArray(data.materiel)) {
|
|
||||||
materiel = await Promise.all(
|
|
||||||
data.materiel.map(async (ref: any) => {
|
|
||||||
const snap = await getDoc(ref);
|
|
||||||
return snap.exists() ? (snap.data() as Reservation) : null;
|
|
||||||
})
|
|
||||||
).then(list => list.filter(x => x !== null)) as Reservation[];
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
var equipe:Reservation[] = [];
|
|
||||||
var vehicules:Reservation[] = [];
|
|
||||||
var materiel:Reservation[] = [];
|
|
||||||
chantiers.push({
|
chantiers.push({
|
||||||
...data,
|
...data,
|
||||||
id: docSnap.id,
|
id: docSnap.id,
|
||||||
@@ -110,10 +97,56 @@ export async function getChantiers(): Promise<Chantier[]> {
|
|||||||
vehicules,
|
vehicules,
|
||||||
materiel,
|
materiel,
|
||||||
} as Chantier);
|
} as Chantier);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Erreur lors de la lecture d'un chantiers : " + error);
|
||||||
|
//alert("Erreur lors de la lecture d'un chantiers : " + error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return chantiers;
|
return chantiers;
|
||||||
|
} catch (error) {
|
||||||
|
alert("Erreur lors de la lecture des chantiers : " + error);
|
||||||
|
}
|
||||||
|
return chantiers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//récupère les reservations d'un chantier
|
||||||
|
export async function getReservationsByChantier(chantierId: string): Promise<Reservation[]> {
|
||||||
|
const q = query(
|
||||||
|
collection(db, "Reservation"),
|
||||||
|
where("chantier", "==", doc(db, "chantier", chantierId)),
|
||||||
|
);
|
||||||
|
|
||||||
|
const snap = await getDocs(q);
|
||||||
|
|
||||||
|
const results = await Promise.all(
|
||||||
|
snap.docs.map(convertReservation)
|
||||||
|
);
|
||||||
|
|
||||||
|
return results.filter(
|
||||||
|
(r): r is Reservation => r !== null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////RESERVATION/////////////////////////////////
|
||||||
|
export async function getReservations(): Promise<Reservation[]> {
|
||||||
|
try {
|
||||||
|
const snap = await getDocs(collection(db, "Reservation"));
|
||||||
|
|
||||||
|
const results = await Promise.all(
|
||||||
|
snap.docs.map(convertReservation)
|
||||||
|
);
|
||||||
|
|
||||||
|
return results.filter(
|
||||||
|
(r): r is Reservation => r !== null
|
||||||
|
);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Erreur lors de la lecture des Reservations : " + error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//CHANGE CHANTIER STATUS
|
//CHANGE CHANTIER STATUS
|
||||||
export async function changeChantierStatus(chantierId: string, newStatus: string): Promise<void> {
|
export async function changeChantierStatus(chantierId: string, newStatus: string): Promise<void> {
|
||||||
try {
|
try {
|
||||||
@@ -177,9 +210,10 @@ type ReservationFirestore = {
|
|||||||
quantity: number;
|
quantity: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
async function convertReservation(res: any): Promise<Reservation> {
|
async function convertReservation(res: any): Promise<Reservation|null> {
|
||||||
|
try {
|
||||||
const data = res.data() as ReservationFirestore;
|
const data = res.data() as ReservationFirestore;
|
||||||
|
|
||||||
const chantierSnap = await getDoc(data.chantier as DocumentReference);
|
const chantierSnap = await getDoc(data.chantier as DocumentReference);
|
||||||
const ressourceSnap = await getDoc(data.ressource as DocumentReference);
|
const ressourceSnap = await getDoc(data.ressource as DocumentReference);
|
||||||
|
|
||||||
@@ -189,6 +223,10 @@ async function convertReservation(res: any): Promise<Reservation> {
|
|||||||
ressource: ressourceSnap.data() as Ressources,
|
ressource: ressourceSnap.data() as Ressources,
|
||||||
quantity: data.quantity,
|
quantity: data.quantity,
|
||||||
};
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.warn("Reservation ignorée :", res.id , err);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -201,7 +239,7 @@ export async function sendNewChantier(chantier:Chantier): Promise<void> {
|
|||||||
adresse:chantier.adresse,
|
adresse:chantier.adresse,
|
||||||
etat:chantier.etat,
|
etat:chantier.etat,
|
||||||
contact:chantier.contact,
|
contact:chantier.contact,
|
||||||
chef: doc(db, "users", chantier.chef.id), //un objet déjà dans la base de donné
|
chef: doc(db, "user", chantier.chef.id), //un objet déjà dans la base de donné
|
||||||
date: Timestamp.fromDate(chantier.dateDep),
|
date: Timestamp.fromDate(chantier.dateDep),
|
||||||
tempsEst: chantier.tempsEst,
|
tempsEst: chantier.tempsEst,
|
||||||
anomalies: chantier.anomalies ?? [], //strings[]
|
anomalies: chantier.anomalies ?? [], //strings[]
|
||||||
|
|||||||
Reference in New Issue
Block a user