Compare commits

..

No commits in common. "4cf9069bf22b923719b8730e3fd80c45b451f8b1" and "68cd3397d49ff577e1fefbf7bbd011f204c29ed3" have entirely different histories.

13 changed files with 1187 additions and 1363 deletions

1618
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,37 +1,35 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { Col, Row } from "antd"; import { Col, Row } from "antd";
import "../assets/styles/diagram.css"; import '../assets/styles/diagram.css'
const Diagram = ({ data }) => { const Diagram = ({ data }) => {
const [diagramData, setDiagramData] = useState(data); const [diagramData, setDiagramData] = useState(data);
useEffect(() => { useEffect(() => {
setDiagramData(data); setDiagramData(data);
}, [data]); }, [data]);
const maxValue = Math.max(...diagramData.map((item) => item.value)); const maxValue = Math.max(...diagramData.map(item => item.value));
return ( return (
<div className="diagram-container"> <div className="diagram-container">
<h2>Prix total par an</h2> <h2>Prix total par an</h2>
{diagramData.map(({ name, value }) => { {diagramData.map(({ name, value }) => {
// Appliquer l'<EFBFBD>chelle logarithmique <EFBFBD> la valeur // Appliquer l'échelle logarithmique à la valeur
const scaledValue = Math.log(value + 1); // Ajouter 1 pour <EFBFBD>viter le logarithme de z<EFBFBD>ro const scaledValue = Math.log(value + 1); // Ajouter 1 pour éviter le logarithme de zéro
const scaledMaxValue = Math.log(maxValue + 1); const scaledMaxValue = Math.log(maxValue + 1);
return ( return (
<div key={name} className="row-container"> <div key={name} className="row-container">
<div className="label">{name}</div> <div className="label">{name}</div>
<div <div className="row" style={{ width: `${(scaledValue / scaledMaxValue) * 100}%` }}>
className="row" <div className="value">{value}</div>
style={{ width: `${(scaledValue / scaledMaxValue) * 100}%` }} </div>
> </div>
<div className="value">{value}</div> );
</div> })}
</div> </div>
); );
})}
</div>
);
}; };
export default Diagram; export default Diagram;

View File

@ -1,12 +1,11 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { Form, Input, InputNumber, Button, Select, DatePicker } from "antd"; import { Form, Input, InputNumber, Button, Select } from "antd";
import axios from "axios"; import axios from "axios";
const { TextArea } = Input; const { TextArea } = Input;
const { Option } = Select; const { Option } = Select;
const dateFormat = "YYYY-MM-DD";
export const FormCreateItem = ({ onClose }) => { export const FormCreateItem = () => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const [rooms, setRooms] = useState([]); const [rooms, setRooms] = useState([]);
@ -32,8 +31,6 @@ export const FormCreateItem = ({ onClose }) => {
values, values,
); );
console.log(response.data); console.log(response.data);
// Fermer la fenêtre modale après soumission réussie
onClose();
} catch (error) { } catch (error) {
console.error(error); console.error(error);
} }
@ -61,7 +58,7 @@ export const FormCreateItem = ({ onClose }) => {
<InputNumber /> <InputNumber />
</Form.Item> </Form.Item>
<Form.Item label="Purchase Date" name="purchaseDate"> <Form.Item label="Purchase Date" name="purchaseDate">
<DatePicker format={dateFormat} /> <Input />
</Form.Item> </Form.Item>
<Form.Item label="Description" name="description"> <Form.Item label="Description" name="description">
<TextArea rows={4} /> <TextArea rows={4} />

View File

@ -3,125 +3,113 @@ import { Form, Input, InputNumber, Button, Select, DatePicker } from "antd";
import axios from "axios"; import axios from "axios";
import { getRooms } from "../../api/room"; import { getRooms } from "../../api/room";
import { getItem } from "../../api/item"; import { getItem } from "../../api/item";
import moment from "moment"; import moment from 'moment';
const { Option } = Select; const { Option } = Select;
function formatItem(itemObj) {
const {
_id,
brand,
model,
room,
price,
purchaseDate,
description,
categories,
createdAt,
updatedAt,
__v,
link,
} = itemObj;
const formattedPurchaseDate =
typeof purchaseDate === "string" ? new Date(purchaseDate) : purchaseDate;
return { function formatItem(itemObj) {
_id, const {_id,brand,model,room,price,purchaseDate,description,categories,createdAt,updatedAt,__v,link} = itemObj
brand, const formattedPurchaseDate = typeof purchaseDate === 'string' ? new Date(purchaseDate) : purchaseDate;
model,
room, return {
price, _id,
purchaseDate: formattedPurchaseDate, brand,
description, model,
categories, room,
createdAt, price,
updatedAt, purchaseDate: formattedPurchaseDate,
__v, description,
link, categories,
}; createdAt,
updatedAt,
__v,
link
};
} }
export const FormUpdateItem = ({ itemId, onClose }) => { export const FormUpdateItem = ({ itemId }) => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const [rooms, setRooms] = useState([]); const [rooms, setRooms] = useState([]);
const [item, setItem] = useState(null); const [item, setItem] = useState(null)
useEffect(() => { useEffect(() => {
const fetchData = async () => { const fetchData = async () => {
const roomsResponse = await getRooms(); const roomsResponse = await getRooms();
setRooms(roomsResponse); setRooms(roomsResponse);
const itemResponse = await getItem(itemId); const itemResponse = await getItem(itemId);
console.log(itemResponse); console.log(itemResponse)
setItem(formatItem(itemResponse)); setItem(formatItem(itemResponse));
};
fetchData();
}, [itemId]);
useEffect(() => {
if (item) {
form.setFieldsValue({
...item,
purchaseDate: item.purchaseDate ? moment(item.purchaseDate) : null,
});
}
}, [item, form]);
const onFinish = async (values) => {
try {
const response = await axios.put(
`${import.meta.env.VITE_API_URL}/item/${item._id}`,
values,
);
console.log(response.data);
} catch (error) {
console.error(error);
}
}; };
fetchData(); const dateFormat = 'YYYY-MM-DD';
}, [itemId]); return (
<Form
useEffect(() => { form={form}
if (item) { onFinish={onFinish}
form.setFieldsValue({ initialValues={item} // Initialise le formulaire avec les valeurs de l'élément
...item, >
purchaseDate: item.purchaseDate ? moment(item.purchaseDate) : null, <h1>Update Item</h1>
}); <Form.Item label="Brand" name="brand">
} <Input />
}, [item, form]); </Form.Item>
<Form.Item label="Model" name="model">
const onFinish = async (values) => { <Input />
try { </Form.Item>
const response = await axios.put( <Form.Item label="Room" name="room">
`${import.meta.env.VITE_API_URL}/item/${item._id}`, <Select placeholder="Select a room">
values, {console.log(rooms)}
); {
console.log(response.data); rooms.map((room) => (
// Fermer la fenêtre modale après soumission réussie <Option key={room._id} value={room._id}>
onClose(); {room.name}
} catch (error) { </Option>
console.error(error); ))}
} </Select>
}; </Form.Item>
<Form.Item label="Price" name="price">
const dateFormat = "YYYY-MM-DD"; <InputNumber />
return ( </Form.Item>
<Form <Form.Item label="Purchase Date" name="purchaseDate">
form={form} <DatePicker
onFinish={onFinish} dateFormat={dateFormat}
initialValues={item} // Initialise le formulaire avec les valeurs de l'élément />
> </Form.Item>
<h1>Update Item</h1> <Form.Item label="Description" name="description">
<Form.Item label="Brand" name="brand"> <Input.TextArea rows={4} />
<Input /> </Form.Item>
</Form.Item> <Form.Item>
<Form.Item label="Model" name="model"> <Button type="primary" htmlType="submit">
<Input /> Submit
</Form.Item> </Button>
<Form.Item label="Room" name="room"> </Form.Item>
<Select placeholder="Select a room"> </Form>
{console.log(rooms)} );
{rooms.map((room) => (
<Option key={room._id} value={room._id}>
{room.name}
</Option>
))}
</Select>
</Form.Item>
<Form.Item label="Price" name="price">
<InputNumber />
</Form.Item>
<Form.Item label="Purchase Date" name="purchaseDate">
<DatePicker dateFormat={dateFormat} />
</Form.Item>
<Form.Item label="Description" name="description">
<Input.TextArea rows={4} />
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
);
}; };
export default FormUpdateItem; export default FormUpdateItem;

View File

@ -1,55 +1,63 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from 'react';
import "../../assets/styles/modal.css"; import '../../assets/styles/modal.css'
import "../../assets/styles/itembox.css"; import '../../assets/styles/itembox.css'
import FormUpdateItem from "../form/formUpdateItem"; import FormUpdateItem from '../form/formUpdateItem';
import { Image } from "../parts/image"; import {Image } from '../parts/image'
import { Description } from "../parts/description"; import {Description } from '../parts/description'
import { Characteristic } from "../parts/characteristic"; import {Characteristic } from '../parts/characteristic'
// Composant Détails du Produit // Composant Détails du Produit
export const ItemBox = ({ model, brand, purchaseDate, price, _id }) => { export const ItemBox = ({ model, brand, purchaseDate, price, _id }) => {
const [isModalOpen, setIsModalOpen] = useState(false);
// Fonction pour ouvrir la fenêtre modale const [isModalOpen, setIsModalOpen] = useState(false);
const openModal = () => {
setIsModalOpen(true);
};
// Fonction pour fermer la fenêtre modale // Fonction pour ouvrir la fenêtre modale
const closeModal = () => { const openModal = () => {
setIsModalOpen(false); setIsModalOpen(true);
}; };
let productname = brand + " " + model; // Fonction pour fermer la fenêtre modale
let formatedPrice = price + "€"; const closeModal = () => {
let formatedDate = new Date(purchaseDate).toLocaleDateString("fr-FR"); setIsModalOpen(false);
};
let request = brand + " " + model;
return (
<div className="product-details"> let productname = brand + " " + model;
<Description title={productname}> let formatedPrice = price + "€";
<Image request={request} _id={_id} alt="Product" /> let formatedDate = new Date(purchaseDate).toLocaleDateString('fr-FR');
<Characteristic label="Model" value={model} />
<Characteristic label="Brand" value={brand} /> let request = brand + " " + model
<Characteristic label="Purchase Date" value={formatedDate} />
<Characteristic label="Price" value={formatedPrice} /> return (
{/* Bouton d'édition pour ouvrir la fenêtre modale */} <div className="product-details" >
<button onClick={openModal}>Edit</button> <Description title={productname} >
</Description> <Image request={request} _id={_id} alt="Product" />
{/* Fenêtre modale */} <Characteristic label="Model" value={model} />
{isModalOpen && ( <Characteristic label="Brand" value={brand} />
<div className="modal"> <Characteristic label="Purchase Date" value={formatedDate} />
<div className="modal-content"> <Characteristic label="Price" value={formatedPrice} />
<span className="close" onClick={closeModal}> {/* Bouton d'édition pour ouvrir la fenêtre modale */}
&times; <button onClick={openModal}>Edit</button>
</span> </Description>
<FormUpdateItem itemId={_id}> {/* Fenêtre modale */}
{console.log("item ID :" + _id)} {isModalOpen && (
</FormUpdateItem> <div className="modal">
</div> <div className="modal-content">
<span className="close" onClick={closeModal}>&times;</span>
<FormUpdateItem itemId={_id}>{console.log("item ID :" + _id)}</FormUpdateItem>
</div>
</div>
)}
</div> </div>
)} );
</div> };
);
};

View File

@ -1,16 +1,18 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import axios from "axios"; import axios from 'axios'; // Assurez-vous que le chemin d'importation soit correct
import { ItemBox } from "./ItemBox"; import { ItemBox } from './ItemBox';
import { DatePicker, Row, Col, Select, Input, InputNumber } from "antd"; import { Space, DatePicker, Row, Col, Select, Input, InputNumber } from 'antd';
import "../../assets/styles/item-page.css"; import '../../assets/styles/item-page.css'
import FormCreateItem from "../form/formCreateItem";
const { RangePicker } = DatePicker; const { RangePicker } = DatePicker;
const { Option } = Select; const { Option } = Select;
const itemsPerPage = 8; const itemsPerPage = 8; // Nombre total d'items par page
const itemsPerRow = 4; const itemsPerRow = 4; // Nombre d'items par rangée
// Fonction pour diviser le tableau d'items en rangées
const chunkArray = (arr, size) => { const chunkArray = (arr, size) => {
const chunkedArr = []; const chunkedArr = [];
for (let i = 0; i < arr.length; i += size) { for (let i = 0; i < arr.length; i += size) {
@ -19,26 +21,39 @@ const chunkArray = (arr, size) => {
return chunkedArr; return chunkedArr;
}; };
// Composant d'affichage de la page
export const ItemPage = () => { export const ItemPage = () => {
const [items, setItems] = useState([]); const [items, setItems] = useState([]);
const [filteredItems, setFilteredItems] = useState([]); const [filteredItems, setFilteredItems] = useState([]); // State pour les items filtrés
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
const [filterName, setFilterName] = useState(""); const [filterName, setFilterName] = useState('');
const [filterPriceMin, setFilterPriceMin] = useState(""); const [filterPriceMin, setFilterPriceMin] = useState('');
const [filterPriceMax, setFilterPriceMax] = useState(""); const [filterPriceMax, setFilterPriceMax] = useState('');
const [filterDateRange, setFilterDateRange] = useState([]); const [filterDateRange, setFilterDateRange] = useState([]);
const [selectedRoom, setSelectedRoom] = useState("all"); const [selectedRoom, setSelectedRoom] = useState('all'); // State pour la chambre sélectionnée
const [rooms, setRooms] = useState([]);
const [isCreateItemModalOpen, setIsCreateItemModalOpen] = useState(false); const [rooms, setRooms] = useState([]); // State pour stocker les chambres
useEffect(() => { useEffect(() => {
const fetchItems = async () => { const fetchItems = async () => {
try { try {
const response = await axios.get( const response = await axios.get(
`${import.meta.env.VITE_API_URL}/item`, `${import.meta.env.VITE_API_URL}/item`,
); );
//await response.data.forEach(async (item) => {
// let cacheUrl = localStorage.getItem(item._id);
// if (cacheUrl == null || cacheUrl == "") {
// let request = item.brand + " " + item.model
// cacheUrl = await searchAndResizeImage(request)
// await localStorage.setItem(item._id, cacheUrl)
// console.log("mise en cache "+ item.imageUrl)
// }
// item.imageUrl = cacheUrl;
//})
setItems(response.data); setItems(response.data);
} catch (error) { }
catch (error) {
console.error(error); console.error(error);
} }
}; };
@ -53,108 +68,98 @@ export const ItemPage = () => {
console.error(error); console.error(error);
} }
}; };
fetchItems(); fetchItems();
fetchRooms(); fetchRooms();
}, []); }, []);
useEffect(() => { useEffect(() => {
const filtered = items.filter((item) => { // Filtrer les éléments chaque fois que les filtres ou la chambre sélectionnée changent
const matchesRoom = selectedRoom === "all" || item.room === selectedRoom; const filtered = items.filter(item => {
const matchesName = // Filtrer par chambre si une chambre est sélectionnée
item.brand.toLowerCase().includes(filterName.toLowerCase()) || const matchesRoom = selectedRoom === 'all' || item.room === selectedRoom;
item.model.toLowerCase().includes(filterName.toLowerCase()); // Filtrer par nom (brand ou model)
const matchesPrice = const matchesName = item.brand.toLowerCase().includes(filterName.toLowerCase()) ||
(filterPriceMin === "" || item.price >= parseFloat(filterPriceMin)) && item.model.toLowerCase().includes(filterName.toLowerCase());
(filterPriceMax === "" || item.price <= parseFloat(filterPriceMax)); // Filtrer par prix
const matchesDate = const matchesPrice =
filterDateRange.length === 0 || (filterPriceMin === '' || item.price >= parseFloat(filterPriceMin)) &&
(new Date(item.purchaseDate) >= filterDateRange[0] && (filterPriceMax === '' || item.price <= parseFloat(filterPriceMax));
new Date(item.purchaseDate) <= filterDateRange[1]); // Filtrer par date
const matchesDate = filterDateRange.length === 0 || (
new Date(item.purchaseDate) >= filterDateRange[0] &&
new Date(item.purchaseDate) <= filterDateRange[1]
);
return matchesRoom && matchesName && matchesPrice && matchesDate; return matchesRoom && matchesName && matchesPrice && matchesDate;
}); });
setFilteredItems(filtered); setFilteredItems(filtered);
}, [ }, [items, selectedRoom, filterName, filterPriceMin, filterPriceMax, filterDateRange]);
items,
selectedRoom,
filterName,
filterPriceMin,
filterPriceMax,
filterDateRange,
]);
const handleNextPage = () => { const handleNextPage = () => {
setCurrentPage((prevPage) => prevPage + 1); setCurrentPage(prevPage => prevPage + 1);
}; };
const handlePrevPage = () => { const handlePrevPage = () => {
setCurrentPage((prevPage) => prevPage - 1); setCurrentPage(prevPage => prevPage - 1);
}; };
const handleRoomChange = (value) => { const handleRoomChange = (value) => {
setSelectedRoom(value); setSelectedRoom(value);
}; };
const handleCloseModal = () => {
setIsCreateItemModalOpen(false);
};
const chunkedItems = chunkArray(filteredItems, itemsPerRow); const chunkedItems = chunkArray(filteredItems, itemsPerRow);
const startIndex = (currentPage - 1) * (itemsPerPage / itemsPerRow); const startIndex = (currentPage - 1) * (itemsPerPage / itemsPerRow);
const endIndex = startIndex + itemsPerPage / itemsPerRow; const endIndex = startIndex + (itemsPerPage / itemsPerRow);
const rowsToDisplay = chunkedItems.slice(startIndex, endIndex); const rowsToDisplay = chunkedItems.slice(startIndex, endIndex);
return ( return (
<div className="item-container"> <div className="item-container">
<div className="filters">{/* Filters here */}</div> <div className="filters">
<div className="filter-group">
{/* Button to open create item modal */} <label htmlFor="roomSelect">Chambre :</label>
<button onClick={() => setIsCreateItemModalOpen(true)}> <Select id="roomSelect" defaultValue="all" style={{ width: 120 }} onChange={handleRoomChange}>
Create Item <Option value="all">Toutes</Option>
</button> {rooms.map(room => (
<Option key={room._id} value={room._id}>{room.name}</Option>
{/* Create item form modal */} ))}
{isCreateItemModalOpen && ( </Select>
<div className="modal"> </div>
<div className="modal-content"> <div className="filter-group">
<span className="close" onClick={handleCloseModal}> <label htmlFor="nameInput">Recherche par nom :</label>
&times; <Input id="nameInput" placeholder="Recherche par nom" value={filterName} onChange={e => setFilterName(e.target.value)} />
</span> </div>
<FormCreateItem onClose={handleCloseModal} /> <div className="filter-group">
<label>Prix :</label>
<InputNumber placeholder="Prix min" value={filterPriceMin} onChange={value => setFilterPriceMin(value)} />
<span> - </span>
<InputNumber placeholder="Prix max" value={filterPriceMax} onChange={value => setFilterPriceMax(value)} />
</div>
<div className="filter-group">
<label>Date d'achat :</label>
<RangePicker format="YYYY-MM-DD" onChange={dates => setFilterDateRange(dates)} value={filterDateRange} />
</div>
</div>
<div className="item-list">
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 32 }}>
{rowsToDisplay.map((row, rowIndex) => (
<React.Fragment key={rowIndex}>
{row.map(item => (
<Col className="gutter-row" span={24 / itemsPerRow} key={item._id}>
<ItemBox {...item} />
</Col>
))}
</React.Fragment>
))}
</Row>
</div>
<div className="pagination">
<button onClick={handlePrevPage} disabled={currentPage === 1}>Précédente</button>
<span>Page {currentPage}</span>
<button onClick={handleNextPage} disabled={endIndex >= chunkedItems.length}>Suivante</button>
</div> </div>
</div>
)}
<div className="item-list">
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 32 }}>
{rowsToDisplay.map((row, rowIndex) => (
<React.Fragment key={rowIndex}>
{row.map((item) => (
<Col
className="gutter-row"
span={24 / itemsPerRow}
key={item._id}
>
<ItemBox {...item} />
</Col>
))}
</React.Fragment>
))}
</Row>
</div> </div>
<div className="pagination">
<button onClick={handlePrevPage} disabled={currentPage === 1}>
Previous
</button>
<span>Page {currentPage}</span>
<button
onClick={handleNextPage}
disabled={endIndex >= chunkedItems.length}
>
Next
</button>
</div>
</div>
); );
}; };

View File

@ -1,9 +1,9 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { Menu } from "antd"; import { Menu } from "antd";
import { HomeOutlined } from "@ant-design/icons"; import { HomeOutlined } from "@ant-design/icons"
import { Home } from "../../pages"; import { Home } from "../../pages";
import { getRooms } from "../../api/room"; import { getRooms } from "../../api/room";
import { isLoggedIn } from "../../api/authentication"; import { isLoggedIn } from "../../api/authentication"
import { Items } from "../../pages/items"; import { Items } from "../../pages/items";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
@ -14,13 +14,11 @@ function getItem(key, label) {
// children, // children,
// label, // label,
// link, // link,
//}; //};
var item = ( var item = <Menu.Item key={key}>
<Menu.Item key={key}> <Link to="/test">{label}</Link>
<Link to="/test">{label}</Link> </Menu.Item >
</Menu.Item> return item
);
return item;
} }
const { SubMenu } = Menu; const { SubMenu } = Menu;
@ -28,48 +26,52 @@ const { SubMenu } = Menu;
// Component // Component
const Navbar = () => { const Navbar = () => {
//Hook calls //Hook calls
const [rooms, setRooms] = useState([]); const [rooms, setRooms] = useState([]);
useEffect(() => { useEffect(() => {
console.log("NAVBAR EFFECT"); console.log("NAVBAR EFFECT")
isLoggedIn().then((user) => { isLoggedIn().then((user) => {
if (user !== "Unauthorized") { if (user !== "Unauthorized") {
getRooms().then((result) => { getRooms().then((result) => {
setRooms(result); setRooms(result);
}); })
} }
}); })
}, []); }, []);
const items = [
<Menu.Item key="0">
<Link to="/logout">Login / Logout</Link>
</Menu.Item>,
<Menu.Item key="1">
<Link to="/home">Menu Principal</Link>
</Menu.Item>,
<Menu.Item key="2">
<Link to="/items">Tous les articles</Link>
</Menu.Item>,
<Menu.Item key="3">
<Link to="/rooms">Voir les chambres</Link>
</Menu.Item>,
];
// Rendu du composant Navbar const items = [
try { <Menu.Item key="0">
return ( <Link to="/logout">Login / Logout</Link>
<Menu </Menu.Item>,
defaultSelectedKeys={["1"]} <Menu.Item key="1" >
defaultOpenKeys={["sub1"]} <Link to="/home">Menu Principal</Link>
theme="dark" </Menu.Item>,
mode="inline" <Menu.Item key="2" >
> <Link to="/items">Tous les articles</Link>
{items} </Menu.Item>,
</Menu> <Menu.Item key="3" >
); <Link to="/rooms">Voir les chambres</Link>
} catch (error) { </Menu.Item>,
console.log(error.stack);
}
];
// Rendu du composant Navbar
try {
return (
<Menu
defaultSelectedKeys={["1"]}
defaultOpenKeys={["sub1"]}
theme="dark"
mode="inline"
>
{items}
</Menu>
);
} catch (error) {
console.log(error.stack)
}
}; };
export default Navbar; export default Navbar;

View File

@ -1,10 +1,11 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from 'react';
// Composant Caract<EFBFBD>ristique // Composant Caractéristique
export const Characteristic = ({ label, value }) => { export const Characteristic = ({ label, value }) => {
return (
<div className="characteristic"> return (
<strong>{label}:</strong> {value} <div className="characteristic">
</div> <strong>{label}:</strong> {value}
); </div>
}; );
};

View File

@ -1,11 +1,11 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from 'react';
// Composant Description // Composant Description
export const Description = ({ title, children }) => { export const Description = ({ title, children }) => {
return ( return (
<div className="description"> <div className="description">
<h2 className="text-ellipsis">{title}</h2> <h2 className="text-ellipsis">{title}</h2>
{children} {children}
</div> </div>
); );
}; };

View File

@ -1,46 +1,45 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from 'react';
import { FormCreateRoom } from "../../components/form/formCreateRoom"; import { FormCreateRoom } from '../../components/form/formCreateRoom';
//import { RoomUpdateForm } from './RoomUpdateForm'; //import { RoomUpdateForm } from './RoomUpdateForm';
export const RoomDetail = ({ export const RoomDetail = ({ selectedRoom, onCreateFormSubmit, onUpdateFormSubmit, onBack }) => {
selectedRoom, const [isUpdateFormVisible, setIsUpdateFormVisible] = useState(false);
onCreateFormSubmit,
onUpdateFormSubmit,
onBack,
}) => {
const [isUpdateFormVisible, setIsUpdateFormVisible] = useState(false);
useEffect(() => { useEffect(() => {
if (selectedRoom) { if (selectedRoom) {
setIsUpdateFormVisible(true); setIsUpdateFormVisible(true)
} }
}, [selectedRoom]); }, [selectedRoom]);
// Afficher le formulaire de mise <EFBFBD> jour lorsqu'une chambre est s<EFBFBD>lectionn<EFBFBD>e
const handleRoomClick = () => {
setIsUpdateFormVisible(true);
};
// Afficher le formulaire de cr<EFBFBD>ation lorsqu'on revient en arri<EFBFBD>re // Afficher le formulaire de mise ŕ jour lorsqu'une chambre est sélectionnée
const handleBackClick = () => { const handleRoomClick = () => {
setIsUpdateFormVisible(false); setIsUpdateFormVisible(true);
onBack(null); };
};
return ( // Afficher le formulaire de création lorsqu'on revient en arričre
<div className="room-detail"> const handleBackClick = () => {
{isUpdateFormVisible ? ( setIsUpdateFormVisible(false);
<div> onBack(null);
<h2>Modifier une chambre</h2> };
<FormCreateRoom onSubmit={onCreateFormSubmit} /> return (
<div className="room-detail">
{isUpdateFormVisible
? (
<div>
<h2>Modifier une chambre</h2>
<FormCreateRoom onSubmit={onCreateFormSubmit} />
</div>
)
: (
<div>
<h2>Ajouter une chambre</h2>
<FormCreateRoom onSubmit={onCreateFormSubmit} />
</div>
)
}
</div> </div>
) : ( );
<div> };
<h2>Ajouter une chambre</h2>
<FormCreateRoom onSubmit={onCreateFormSubmit} />
</div>
)}
</div>
);
};

View File

@ -1,9 +1,10 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import "../../assets/styles/room-list.css"; import '../../assets/styles/room-list.css'
import { RoomBox } from "../../components/rooms/roomBox"; import { RoomBox } from '../../components/rooms/roomBox'
import { formatRoomStats } from "../../api/room"; import { formatRoomStats } from "../../api/room";
// Fonction pour diviser le tableau d'items en rang<EFBFBD>es
// Fonction pour diviser le tableau d'items en rangées
const chunkArray = (arr, size) => { const chunkArray = (arr, size) => {
const chunkedArr = []; const chunkedArr = [];
for (let i = 0; i < arr.length; i += size) { for (let i = 0; i < arr.length; i += size) {
@ -14,30 +15,31 @@ const chunkArray = (arr, size) => {
// Composant d'affichage de la page // Composant d'affichage de la page
export const RoomList = ({ statsParam, onRoomClick }) => { export const RoomList = ({ statsParam, onRoomClick }) => {
const [rooms, setRooms] = useState([]); const [rooms, setRooms] = useState([]);
const [selectedRoom, setSelectedRoom] = useState("all"); const [selectedRoom, setSelectedRoom] = useState('all');
useEffect(() => { useEffect(() => {
if (statsParam.rooms) { if (statsParam.rooms) {
console.log(statsParam.rooms); console.log(statsParam.rooms)
let formatedStats = formatRoomStats(statsParam); let formatedStats = formatRoomStats(statsParam)
setRooms(formatedStats.rooms); setRooms(formatedStats.rooms)
} }
}, [statsParam]); }, [statsParam]);
const handleRoomClick = (roomId) => {
onRoomClick(roomId);
};
return ( const handleRoomClick = (roomId) => {
<div> onRoomClick(roomId);
<h2>Liste des chambres</h2> };
<div className="list-container">
{rooms && return (
rooms.map((room) => ( <div>
<RoomBox room={room} key={room._id} onRoomClick={handleRoomClick} /> <h2>Liste des chambres</h2>
))} <div className="list-container">
</div> {rooms && rooms.map((room) => (
</div> <RoomBox room={room} key={room._id} onRoomClick={handleRoomClick} />
); ))}
}; </div>
</div>
);
};

View File

@ -1,22 +1,20 @@
import React from "react"; import React from 'react';
import "../../assets/styles/room-list.css"; import '../../assets/styles/room-list.css';
import { Description } from "../parts/description"; import { Description } from '../parts/description';
import { Characteristic } from "../parts/characteristic"; import { Characteristic } from '../parts/characteristic';
export const RoomBox = ({ room, onRoomClick }) => { export const RoomBox = ({ room, onRoomClick }) => {
const handleBoxClick = () => {
onRoomClick(room._id);
};
return ( const handleBoxClick = () => {
<div className="room-details" onClick={handleBoxClick}> onRoomClick(room._id);
<Description title={room?.name}> };
<Characteristic
label="Nombre d'articles" return (
value={room?.items_count || "N/A"} <div className="room-details" onClick={handleBoxClick}>
/> <Description title={room?.name}>
<Characteristic label="Prix total" value={room?.room_price || "N/A"} /> <Characteristic label="Nombre d'articles" value={room?.items_count || "N/A"} />
</Description> <Characteristic label="Prix total" value={room?.room_price || "N/A"} />
</div> </Description>
); </div>
}; );
};

View File

@ -1,53 +1,53 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from 'react';
import "../assets/styles/room-page.css"; import '../assets/styles/room-page.css'
import { useAuth } from "../hooks"; import { useAuth } from "../hooks";
import { getRoomStats } from "../api/room"; import { getRoomStats } from "../api/room";
import { usePageTitle } from "../hooks/page-title-context"; import { usePageTitle } from '../hooks/page-title-context';
import RoomStats from "../components/rooms/room-stats"; import RoomStats from '../components/rooms/room-stats';
import { RoomList } from "../components/rooms/room-list"; import { RoomList } from '../components/rooms/room-list';
import { RoomDetail } from "../components/rooms/room-detail"; import { RoomDetail } from '../components/rooms/room-detail';
export const Rooms = () => { export const Rooms = () => {
const { user } = useAuth(); const { user } = useAuth();
const { setPageTitle } = usePageTitle(); const { setPageTitle } = usePageTitle();
const [stats, setStats] = useState({}); const [stats, setStats] = useState({});
const [selectedRoom, setSelectedRoom] = useState(); const [selectedRoom, setSelectedRoom] = useState();
useEffect(() => {
setPageTitle("Toutes les rooms :");
}, [setPageTitle]);
useEffect(() => { useEffect(() => {
const fetchData = async () => { setPageTitle("Toutes les rooms :");
const roomsStatsResponse = await getRoomStats(); }, [setPageTitle]);
setStats(roomsStatsResponse);
useEffect(() => {
const fetchData = async () => {
const roomsStatsResponse = await getRoomStats();
setStats(roomsStatsResponse);
};
fetchData();
}, []);
const handleRoomClick = (roomId) => {
console.log('Clicked room ID:', roomId);
setSelectedRoom(roomId);
}; };
fetchData();
}, []);
const handleRoomClick = (roomId) => {
console.log("Clicked room ID:", roomId);
setSelectedRoom(roomId);
};
return ( return (
<div className="manContainer"> <div className="manContainer">
<div className="topContainer"> <div className="topContainer">
<div className="statsContainer"> <div className="statsContainer">
<RoomStats statsParam={stats} /> <RoomStats statsParam={stats} />
</div>
<div className="listContainer">
<RoomList statsParam={stats} onRoomClick={handleRoomClick}></RoomList>
</div>
</div> </div>
<div className="listContainer"> <div className="detailContainer">
<RoomList statsParam={stats} onRoomClick={handleRoomClick}></RoomList> <RoomDetail selectedRoom={selectedRoom} onBack={handleRoomClick}></RoomDetail>
</div> </div>
</div>
<div className="detailContainer">
<RoomDetail
selectedRoom={selectedRoom}
onBack={handleRoomClick}
></RoomDetail>
</div>
</div> </div>
); );
}; };