test reservation todo corriger getChantier avec la nouvelelle structure
This commit is contained in:
@@ -9,7 +9,11 @@ import { ThemedView } from "@/components/theme/themed-view";
|
||||
|
||||
export default function AddScreen() {
|
||||
const [typeAdd, setTypeAdd] = useState('');
|
||||
const [editMode, setEditMode] = useState(false);
|
||||
|
||||
function onPressSwitchMode(){
|
||||
setEditMode(!editMode);
|
||||
}
|
||||
|
||||
return(
|
||||
<ThemedView lvl={3} style={styles.back}>
|
||||
|
||||
@@ -5,7 +5,6 @@ import Constants from "expo-constants"; //pour connaître la taille de la barre
|
||||
import { useLocalSearchParams, useRouter } from "expo-router";
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import { FlatList, Image, StyleSheet, Text, View } from "react-native";
|
||||
import rawConcerts from "../../data/concerts.json";
|
||||
import { getUsers } from "@/services/ressourcesService";
|
||||
import { useChantier } from "../ContextChantier";
|
||||
import SelectChantier from "@/components/selectChantier";
|
||||
@@ -34,7 +33,7 @@ export default function GestionOuvrier() {
|
||||
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");
|
||||
const data = (await getRessources()).filter(u => u.type === "Ouvrier");
|
||||
setRessources(data);
|
||||
} catch (error) {
|
||||
console.error("Erreur lors du chargement :", error);
|
||||
@@ -43,19 +42,6 @@ export default function GestionOuvrier() {
|
||||
loadData();
|
||||
}, []);
|
||||
|
||||
const concertsData: Concert[] = Array.isArray(rawConcerts)
|
||||
? (rawConcerts as Concert[])
|
||||
: [];
|
||||
|
||||
const filteredData = useMemo(() => {
|
||||
if (!Array.isArray(concertsData)) return [];
|
||||
const q = search.trim().toLowerCase();
|
||||
if (!q) return concertsData;
|
||||
return concertsData.filter(
|
||||
(item) => !!item && (item.group ?? "").toLowerCase().includes(q)
|
||||
);
|
||||
}, [concertsData, search]);
|
||||
|
||||
const renderItem = ({ item, index }: { item?: Ressources; index: number }) => {
|
||||
if (!item) {
|
||||
return null;
|
||||
|
||||
@@ -15,7 +15,7 @@ import { useRessources } from "../ContextRessource";
|
||||
export default function GestionnaireRessource() {
|
||||
const [search, setSearch] = useState("");
|
||||
const {ressources, setRessources} = useRessources();
|
||||
const [filterType, setFilterType] = useState("tout");
|
||||
const [filterType, setFilterType] = useState("Tout");
|
||||
const [showFilterMenu, setShowFilterMenu] = useState(false);
|
||||
const router = useRouter();
|
||||
|
||||
@@ -33,7 +33,7 @@ export default function GestionnaireRessource() {
|
||||
|
||||
const filteredData = ressources.filter((r) => {
|
||||
const matchName = r.name.toLowerCase().includes(search.toLowerCase());
|
||||
const matchType = filterType === "tout" || r.type === filterType;
|
||||
const matchType = filterType === "Tout" || r.type === filterType;
|
||||
return matchName && matchType;
|
||||
});
|
||||
|
||||
@@ -43,6 +43,7 @@ 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>
|
||||
@@ -68,7 +69,7 @@ export default function GestionnaireRessource() {
|
||||
<ThemedView lvl={2} style={styles.filterMenuOverlay}>
|
||||
<ThemedView lvl={5} style={styles.filterMenu}>
|
||||
<ThemedText style={styles.filterTitle}>Filtrer par type</ThemedText>
|
||||
{["tout", "Outil", "Machine"].map((t) => (
|
||||
{["Tout", "Outil", "Machine","Ouvrier"].map((t) => (
|
||||
<ThemedButton
|
||||
key={t}
|
||||
lvl={1}
|
||||
|
||||
@@ -5,11 +5,11 @@ export type Chantier = {
|
||||
etat: string;
|
||||
contact: string;
|
||||
chef: User;
|
||||
equipe: User[];
|
||||
materiel: Ressources[];
|
||||
equipe: Reservation[];
|
||||
materiel: Reservation[];
|
||||
vehicules: Reservation[];
|
||||
dateDep: Date;
|
||||
tempsEst: number;
|
||||
vehicules: Ressources[];
|
||||
anomalies: string[];
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
@@ -36,6 +36,7 @@ export type Ressources = {
|
||||
|
||||
export type Reservation = {
|
||||
id: string;
|
||||
dateChantier: Date;
|
||||
dateFin: Date;
|
||||
chantier: Chantier;
|
||||
ressource: Ressources;
|
||||
quantity: number;
|
||||
};
|
||||
@@ -7,8 +7,8 @@ import { StyleSheet, ScrollView, Button, TextInput, Text, View, Modal } from 're
|
||||
import { useChantier } from '../../app/ContextChantier';
|
||||
import { useRessources } from '../../app/ContextRessource';
|
||||
import { useUser } from '../../app/ContextUser';
|
||||
import { getRessources, getUsers, addChantier } from '@/services/ressourcesService';
|
||||
import { Chantier, Ressources, User } from '@/class/class';
|
||||
import { getRessources, getUsers, addChantier, sendNewChantier } from '@/services/ressourcesService';
|
||||
import { Chantier, Ressources, User, Reservation } from '@/class/class';
|
||||
import { ThemedText } from '@/components/theme/themed-text';
|
||||
import { ThemedButton } from '@/components/theme/themed-button';
|
||||
import { ThemedTextInput } from '@/components/theme/themed-textinput';
|
||||
@@ -34,7 +34,6 @@ export default function AddChantier() {
|
||||
|
||||
const [editMode,setEditMode] = useState(false);
|
||||
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [objet, setObjet] = useState('');
|
||||
const [date, setDate] = useState(new Date());
|
||||
const [morning, setMorning] = useState(true);
|
||||
@@ -44,6 +43,7 @@ export default function AddChantier() {
|
||||
const [contact, setContact] = useState('');
|
||||
const [machines, setMachines] = useState<RessourcesQte[]>();
|
||||
const [ouvriers, setOuviers] = useState<RessourcesQte[]>();
|
||||
const [outils, setOutils] = useState<RessourcesQte[]>();
|
||||
|
||||
const [showDateSelect,setSowDateSelect] = useState(false);
|
||||
const [openConfirmation,setOpenConfirmation] = useState(false);
|
||||
@@ -52,7 +52,6 @@ export default function AddChantier() {
|
||||
const [ressourcesSelect, setRessourcesSelect] = useState<string[]>([]);
|
||||
|
||||
async function handleAddChantier() {
|
||||
setLoading(true);
|
||||
setOpenConfirmation(true);
|
||||
}
|
||||
|
||||
@@ -64,15 +63,89 @@ export default function AddChantier() {
|
||||
}
|
||||
};
|
||||
async function onConfirm(): Promise<void> {
|
||||
if (!isValidChantier() || !chefChantier) return;
|
||||
try {
|
||||
setLoading(true);
|
||||
if (!isValidChantier() || !chefChantier){
|
||||
alert("Choisir un chef de Chantier");
|
||||
return;
|
||||
}
|
||||
setOpenConfirmation(false);
|
||||
var latitude=0;
|
||||
var longitude=0;
|
||||
try { //verification de l'adresse
|
||||
const coords = await geocodeAddress(adresse);
|
||||
if (coords) {
|
||||
latitude=coords.latitude;
|
||||
longitude=coords.longitude;
|
||||
}
|
||||
else{
|
||||
console.error("Impossible de géocoder l'adresse");
|
||||
alert("Adresse introuvable. Veuillez vérifier l'adresse.");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Erreur lors de la création du chantier:", error);
|
||||
alert("Erreur lors de la création du chantier");
|
||||
}
|
||||
|
||||
|
||||
|
||||
var chantier: Chantier = {
|
||||
id:"0",
|
||||
name: objet,
|
||||
adresse: adresse,
|
||||
etat: 'En cours',
|
||||
contact: contact,
|
||||
chef: chefChantier,
|
||||
dateDep: date,
|
||||
tempsEst: Number(duree),
|
||||
anomalies: [],
|
||||
latitude: latitude,
|
||||
longitude: longitude,
|
||||
equipe: [],
|
||||
materiel: [],
|
||||
vehicules: []
|
||||
}
|
||||
|
||||
if(machines){
|
||||
machines.forEach(item => {
|
||||
chantier.vehicules.push({
|
||||
id:"0",
|
||||
chantier: chantier,
|
||||
ressource: item[0],
|
||||
quantity: item[1],
|
||||
})
|
||||
});
|
||||
}
|
||||
if(ouvriers){
|
||||
ouvriers.forEach(item => {
|
||||
chantier.equipe.push({
|
||||
id:"0",
|
||||
chantier: chantier,
|
||||
ressource: item[0],
|
||||
quantity: item[1],
|
||||
})
|
||||
});
|
||||
}
|
||||
if(outils){
|
||||
outils.forEach(item => {
|
||||
chantier.materiel.push({
|
||||
id:"0",
|
||||
chantier: chantier,
|
||||
ressource: item[0],
|
||||
quantity: item[1],
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
sendNewChantier(chantier);
|
||||
|
||||
|
||||
|
||||
|
||||
/*try {
|
||||
const coords = await geocodeAddress(adresse);
|
||||
|
||||
if (!coords) {
|
||||
console.error("Impossible de géocoder l'adresse");
|
||||
alert("Adresse introuvable. Veuillez vérifier l'adresse.");
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
const chantierDate = new Date(date);
|
||||
@@ -85,17 +158,17 @@ export default function AddChantier() {
|
||||
contact,
|
||||
chef: doc(db, "user", chefChantier.id),
|
||||
equipe: [],
|
||||
/*materiel: materiels
|
||||
? [doc(db, "ressources", String(materiels.id))]
|
||||
: [],*/
|
||||
//materiel: materiels
|
||||
// ? [doc(db, "ressources", String(materiels.id))]
|
||||
// : [],
|
||||
vehicules: machines?.map(e =>
|
||||
doc(db, "ressources", String(e[0].id))
|
||||
) || [],
|
||||
anomalies: [],
|
||||
dateDep: chantierDate,
|
||||
tempsEst: parseInt(duree) || 1,
|
||||
latitude: coords.latitude, //TODO
|
||||
longitude: coords.longitude, //TODO
|
||||
latitude: coords.latitude,
|
||||
longitude: coords.longitude,
|
||||
};
|
||||
const id = await addChantier(chantierFirestore as any);
|
||||
if (id) {
|
||||
@@ -113,9 +186,7 @@ export default function AddChantier() {
|
||||
} catch (error) {
|
||||
console.error("Erreur lors de la création du chantier:", error);
|
||||
alert("Erreur lors de la création du chantier");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
function onCancel(): void {
|
||||
@@ -231,7 +302,7 @@ export default function AddChantier() {
|
||||
</View>
|
||||
<View style = {styles.inputLine}>
|
||||
<ThemedText style = {styles.inputName}>Outils:</ThemedText>
|
||||
<SelectRessource style={styles.input} sendRessources={setOuviers} ressourceType="Outil"/>
|
||||
<SelectRessource style={styles.input} sendRessources={setOutils} ressourceType="Outil"/>
|
||||
</View>
|
||||
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ export default function SelectChafChantier({style,sendChefChantier , ...otherPro
|
||||
return(
|
||||
<View style={{padding:10,width:"100%"}}>
|
||||
<ThemedButton lvl={2} style={{padding:10,width:"100%",borderRadius:10}} onPress={() => {onPressUser(item)}}>
|
||||
<ThemedText>{item.id}</ThemedText>
|
||||
<ThemedText>{item.name}</ThemedText>
|
||||
<ThemedText>{item.last_name}</ThemedText>
|
||||
<ThemedText>{item.role}</ThemedText>
|
||||
|
||||
@@ -20,9 +20,9 @@ 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} />
|
||||
</View>
|
||||
<View style={{flex: 1}}>
|
||||
<ThemedText>Adresse: {data.chantier.adresse}</ThemedText>
|
||||
<ThemedText>Chef de chantier: {data.chantier.chef.last_name}{" "}{data.chantier.chef.name}</ThemedText>
|
||||
<ThemedText>État: {data.chantier.etat}</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>
|
||||
</View>
|
||||
</ThemedView>
|
||||
) :
|
||||
|
||||
@@ -78,7 +78,7 @@ export default function SelectChantier() {
|
||||
var keyWords:string[] = search.toLowerCase().split(" ") ;
|
||||
var containsAllKeyWord:boolean = true;
|
||||
keyWords.forEach(keyWord => {
|
||||
containsAllKeyWord = containsAllKeyWord && (chantier.adresse.toLowerCase().includes(keyWord))
|
||||
containsAllKeyWord = containsAllKeyWord && (chantier.adresse.toLowerCase().includes(keyWord) || chantier.name.toLowerCase().includes(keyWord))
|
||||
});
|
||||
return containsAllKeyWord
|
||||
});
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
[
|
||||
{
|
||||
"group": "Bernard DupYEEd",
|
||||
"date":"Rennes",
|
||||
"nationality": "French",
|
||||
"location": "PlombYEEr",
|
||||
"price": 20,
|
||||
"ticketsLeft": 36,
|
||||
"Image": "https://media.discordapp.net/attachments/1415267028201246812/1424825038657425518/a06e3304-86ca-4b4f-8016-c4ae9844b0df.png?ex=68e9f879&is=68e8a6f9&hm=b6ff1f540d5c382930b56bd6f90565f517ee179347d6ee6aebd5254b10cf4c88&=&format=webp&quality=lossless&width=579&height=579",
|
||||
"favorite": false
|
||||
},
|
||||
{
|
||||
"group": "MYEEchel Câble",
|
||||
"date":"Nantes",
|
||||
"nationality": "French",
|
||||
"location": "ElectrYEEcien",
|
||||
"price": 22,
|
||||
"ticketsLeft": 400,
|
||||
"Image": "https://media.discordapp.net/attachments/1415267028201246812/1424826240090509332/7fdbfe06-8300-441e-81ac-87851d004dc3.png?ex=68e9f997&is=68e8a817&hm=cc71621c3e7c3c1aaeda5555e9dd4204d43414cd0332c2b116b10d009b68df3c&=&format=webp&quality=lossless&width=579&height=579",
|
||||
"favorite": false
|
||||
|
||||
},
|
||||
{
|
||||
"group": "PYEErre soulever",
|
||||
"date":"Redon",
|
||||
"nationality": "French",
|
||||
"location": "GrutYEEr",
|
||||
"price": 32,
|
||||
"ticketsLeft": 0,
|
||||
"Image": "https://media.discordapp.net/attachments/1425108443571945644/1427207643180826757/raw.png?ex=68ee0632&is=68ecb4b2&hm=1efc51065c6abfb1af75b8382f9924c2eb177c7d7672f7ed9837e96ef3076d16&=&format=webp&quality=lossless&width=233&height=350",
|
||||
"favorite": false
|
||||
|
||||
},
|
||||
{
|
||||
"group": "Greg NegatYEEf",
|
||||
"date":"Pacé",
|
||||
"nationality": "French",
|
||||
"location": "ElectrYEEcien",
|
||||
"price": 20,
|
||||
"ticketsLeft": 36,
|
||||
"Image": "https://media.discordapp.net/attachments/1415267028201246812/1424826240090509332/7fdbfe06-8300-441e-81ac-87851d004dc3.png?ex=68e9f997&is=68e8a817&hm=cc71621c3e7c3c1aaeda5555e9dd4204d43414cd0332c2b116b10d009b68df3c&=&format=webp&quality=lossless&width=579&height=579",
|
||||
"favorite": true
|
||||
|
||||
}
|
||||
]
|
||||
@@ -1,4 +1,4 @@
|
||||
import { addDoc, arrayUnion, collection, doc, getDoc, getDocs, Timestamp, updateDoc } from "firebase/firestore";
|
||||
import { addDoc, arrayUnion, collection, doc, Firestore, getDoc, getDocs, Timestamp, updateDoc, DocumentReference } from "firebase/firestore";
|
||||
import { Chantier, Reservation, Ressources, User } from "../class/class";
|
||||
import { db } from "../firebase_config";
|
||||
|
||||
@@ -28,6 +28,7 @@ export async function getRessources(): Promise<Ressources[]> {
|
||||
return snapshot.docs.map((doc) => {
|
||||
const data = doc.data();
|
||||
return {
|
||||
id: doc.id,
|
||||
...data,
|
||||
allocation: data.allocation?.map(convertReservation) || [],
|
||||
} as Ressources;
|
||||
@@ -66,22 +67,46 @@ export async function getChantiers(): Promise<Chantier[]> {
|
||||
chef = chefSnap.data() as User;
|
||||
}
|
||||
}
|
||||
let equipe: User[] = [];
|
||||
|
||||
let equipe: Reservation[] = [];
|
||||
if (Array.isArray(data.equipe)) {
|
||||
equipe = await Promise.all(
|
||||
data.equipe.map(async (ref: any) => {
|
||||
const snap = await getDoc(ref);
|
||||
return snap.exists() ? (snap.data() as User) : null;
|
||||
return snap.exists() ? (snap.data() as Reservation) : null;
|
||||
})
|
||||
).then(list => list.filter(x => x !== null)) as User[];
|
||||
).then(list => list.filter(x => x !== null)) as Reservation[];
|
||||
}
|
||||
|
||||
let vehicules: Reservation[] = [];
|
||||
if (Array.isArray(data.vehicules)) {
|
||||
vehicules = await Promise.all(
|
||||
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[];
|
||||
}
|
||||
|
||||
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[];
|
||||
}
|
||||
|
||||
|
||||
chantiers.push({
|
||||
...data,
|
||||
id: docSnap.id,
|
||||
dateDep,
|
||||
chef,
|
||||
equipe
|
||||
equipe,
|
||||
vehicules,
|
||||
materiel,
|
||||
} as Chantier);
|
||||
}
|
||||
return chantiers;
|
||||
@@ -144,12 +169,58 @@ export async function deleteAnomalie(chantierId: string, anomalie_String: string
|
||||
}
|
||||
}
|
||||
|
||||
function convertReservation(res: any): Reservation {
|
||||
type ReservationFirestore = {
|
||||
chantier: DocumentReference;
|
||||
ressource: DocumentReference;
|
||||
quantity: number;
|
||||
};
|
||||
|
||||
async function convertReservation(res: any): Promise<Reservation> {
|
||||
|
||||
const data = res.data() as ReservationFirestore;
|
||||
const chantierSnap = await getDoc(data.chantier as DocumentReference);
|
||||
const ressourceSnap = await getDoc(data.ressource as DocumentReference);
|
||||
|
||||
return {
|
||||
id: res.id,
|
||||
dateChantier:
|
||||
res.dateChantier instanceof Timestamp ? res.dateChantier.toDate() : new Date(res.dateChantier),
|
||||
dateFin:
|
||||
res.dateFin instanceof Timestamp ? res.dateFin.toDate() : new Date(res.dateFin),
|
||||
chantier: chantierSnap.data() as Chantier,
|
||||
ressource: ressourceSnap.data() as Ressources,
|
||||
quantity: data.quantity,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//ENVOYER CHANTIER
|
||||
export async function sendNewChantier(chantier:Chantier): Promise<void> {
|
||||
|
||||
const chantierRef = await addDoc(collection(db, "chantier"), {
|
||||
name:chantier.name,
|
||||
adresse:chantier.adresse,
|
||||
etat:chantier.etat,
|
||||
contact:chantier.contact,
|
||||
chef: doc(db, "users", chantier.chef.id), //un objet déjà dans la base de donné
|
||||
date: Timestamp.fromDate(chantier.dateDep),
|
||||
tempsEst: chantier.tempsEst,
|
||||
anomalies: chantier.anomalies ?? [], //strings[]
|
||||
latitude: chantier.latitude,
|
||||
longitude: chantier.longitude,
|
||||
})
|
||||
await Promise.all([
|
||||
sendNewReservation(chantier.equipe, chantierRef.id),
|
||||
sendNewReservation(chantier.materiel, chantierRef.id),
|
||||
sendNewReservation(chantier.vehicules, chantierRef.id),
|
||||
]);
|
||||
}
|
||||
|
||||
export async function sendNewReservation(list: Reservation[],chantierId:string): Promise<void> {
|
||||
const promises = list.map((reservation) =>
|
||||
addDoc(collection(db,"Reservation"),{
|
||||
chantier: doc(db, "chantier", chantierId),
|
||||
ressource: doc(db, "ressources", reservation.ressource.id),
|
||||
quantity: reservation.quantity,
|
||||
})
|
||||
);
|
||||
|
||||
await Promise.all(promises);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user