premier commit final

This commit is contained in:
Victor 2024-05-13 00:33:13 +02:00
commit 4cf9069bf2
14 changed files with 270 additions and 172 deletions

Binary file not shown.

Binary file not shown.

2
package-lock.json generated
View File

@ -16,7 +16,7 @@
"react": "^18.2.0", "react": "^18.2.0",
"react-cookie": "^7.0.2", "react-cookie": "^7.0.2",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-router-dom": "^6.21.3" "react-router-dom": "^6.23.1"
}, },
"devDependencies": { "devDependencies": {
"@playwright/test": "^1.42.1", "@playwright/test": "^1.42.1",

View File

@ -22,7 +22,7 @@
"react": "^18.2.0", "react": "^18.2.0",
"react-cookie": "^7.0.2", "react-cookie": "^7.0.2",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-router-dom": "^6.21.3" "react-router-dom": "^6.23.1"
}, },
"devDependencies": { "devDependencies": {
"@playwright/test": "^1.42.1", "@playwright/test": "^1.42.1",

View File

@ -0,0 +1,38 @@
.list-container {
width: 100%;
max-height:500px;
overflow-y: auto; /* Activer le défilement vertical si nécessaire */
padding: 20px; /* Espace intérieur de la liste */
}
.room-details {
width: 100%; /* Largeur de chaque boîte */
background-color: #f9f9f9;
border-radius: 10px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
padding: 20px;
margin-bottom: 20px; /* Espace entre chaque boîte */
transition: transform 0.3s ease;
}
.room-details:hover {
transform: translateY(-5px); /* Effet d'élévation au survol */
}
.room-details .title {
font-size: 18px;
font-weight: bold;
margin-bottom: 10px;
}
.room-details .characteristic {
margin-bottom: 10px;
}
.room-details .label {
font-weight: bold;
}
.room-details .value {
color: #666;
}

View File

@ -1,30 +1,37 @@
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 }) => {
<div key={name} className="row-container"> // Appliquer l'<EFBFBD>chelle logarithmique <EFBFBD> la valeur
<div className="label">{name}</div> const scaledValue = Math.log(value + 1); // Ajouter 1 pour <EFBFBD>viter le logarithme de z<EFBFBD>ro
<div className="row" style={{ width: `${(value / maxValue) * 100}%` }}> const scaledMaxValue = Math.log(maxValue + 1);
<div className="value">{value}</div> return (
</div> <div key={name} className="row-container">
</div> <div className="label">{name}</div>
))} <div
</div> className="row"
); style={{ width: `${(scaledValue / scaledMaxValue) * 100}%` }}
>
<div className="value">{value}</div>
</div>
</div>
);
})}
</div>
);
}; };
export default Diagram; export default Diagram;

View File

@ -1,27 +1,10 @@
import React, { 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";
// Composant Description import { Characteristic } from "../parts/characteristic";
const Description = ({ title, children }) => {
return (
<div className="description">
<h2 className="text-ellipsis">{title}</h2>
{children}
</div>
);
};
// Composant Caractéristique
const Characteristic = ({ label, value }) => {
return (
<div className="characteristic">
<strong>{label}:</strong> {value}
</div>
);
};
// 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 }) => {
@ -54,14 +37,16 @@ export const ItemBox = ({ model, brand, purchaseDate, price, _id }) => {
{/* Bouton d'édition pour ouvrir la fenêtre modale */} {/* Bouton d'édition pour ouvrir la fenêtre modale */}
<button onClick={openModal}>Edit</button> <button onClick={openModal}>Edit</button>
</Description> </Description>
{/* Fenêtre modale pour la mise à jour */} {/* Fenêtre modale */}
{isModalOpen && ( {isModalOpen && (
<div className="modal"> <div className="modal">
<div className="modal-content"> <div className="modal-content">
<span className="close" onClick={closeModal}> <span className="close" onClick={closeModal}>
&times; &times;
</span> </span>
<FormUpdateItem itemId={_id} onClose={closeModal} /> <FormUpdateItem itemId={_id}>
{console.log("item ID :" + _id)}
</FormUpdateItem>
</div> </div>
</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,11 +14,13 @@ function getItem(key, label) {
// children, // children,
// label, // label,
// link, // link,
//}; //};
var item = <Menu.Item key={key}> var item = (
<Link to="/test">{label}</Link> <Menu.Item key={key}>
</Menu.Item > <Link to="/test">{label}</Link>
return item </Menu.Item>
);
return item;
} }
const { SubMenu } = Menu; const { SubMenu } = Menu;
@ -26,52 +28,48 @@ 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>,
];
const items = [ // Rendu du composant Navbar
<Menu.Item key="0"> try {
<Link to="/">Menu Principal</Link> return (
</Menu.Item>, <Menu
<Menu.Item key="1" > defaultSelectedKeys={["1"]}
<Link to="/home">Home</Link> defaultOpenKeys={["sub1"]}
</Menu.Item>, theme="dark"
<Menu.Item key="2" > mode="inline"
<Link to="/items">Tous les articles</Link> >
</Menu.Item>, {items}
<Menu.Item key="3" > </Menu>
<Link to="/rooms">Voir les chambres</Link> );
</Menu.Item>, } catch (error) {
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

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

View File

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

View File

@ -0,0 +1,46 @@
import React, { useEffect, useState } from "react";
import { FormCreateRoom } from "../../components/form/formCreateRoom";
//import { RoomUpdateForm } from './RoomUpdateForm';
export const RoomDetail = ({
selectedRoom,
onCreateFormSubmit,
onUpdateFormSubmit,
onBack,
}) => {
const [isUpdateFormVisible, setIsUpdateFormVisible] = useState(false);
useEffect(() => {
if (selectedRoom) {
setIsUpdateFormVisible(true);
}
}, [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
const handleBackClick = () => {
setIsUpdateFormVisible(false);
onBack(null);
};
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>
);
};

View File

@ -1,18 +1,9 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import axios from 'axios'; // Assurez-vous que le chemin d'importation soit correct import "../../assets/styles/room-list.css";
import { ItemBox } from './ItemBox'; import { RoomBox } from "../../components/rooms/roomBox";
import { Space, DatePicker, Row, Col, Select, Input, InputNumber } from 'antd'; import { formatRoomStats } from "../../api/room";
import '../../assets/styles/item-page.css'
// Fonction pour diviser le tableau d'items en rang<EFBFBD>es
const { RangePicker } = DatePicker;
const { Option } = Select;
const itemsPerPage = 8; // Nombre total d'items par page
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) {
@ -22,25 +13,31 @@ const chunkArray = (arr, size) => {
}; };
// Composant d'affichage de la page // Composant d'affichage de la page
export const RoomList = (roomsParam) => { 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(() => {
setRooms(roomsParam) if (statsParam.rooms) {
}, [roomsParam]); console.log(statsParam.rooms);
let formatedStats = formatRoomStats(statsParam);
setRooms(formatedStats.rooms);
}
}, [statsParam]);
const handleRoomChange = (value) => { const handleRoomClick = (roomId) => {
setSelectedRoom(value); onRoomClick(roomId);
}; };
return ( return (
<div>
<h2>Liste des chambres</h2>
<div className="list-container"> <div className="list-container">
<div className="room-list"> {rooms &&
{rooms.forEach((room) => { rooms.map((room) => (
<roomB <RoomBox room={room} key={room._id} onRoomClick={handleRoomClick} />
}) } ))}
</div>
</div> </div>
</div>
); );
}; };

View File

@ -1,23 +1,22 @@
import React, { useEffect, useState } from 'react'; import React from "react";
import '../../assets/styles/itembox.css' import "../../assets/styles/room-list.css";
import { } from '../item/ItemBox' import { Description } from "../parts/description";
import { Characteristic } from "../parts/characteristic";
export const RoomBox = ({ room, onRoomClick }) => {
const handleBoxClick = () => {
onRoomClick(room._id);
};
// Composant Détails du Produit return (
export const RoomBox = ({ name, itemCount, roomPrice, _id }) => { <div className="room-details" onClick={handleBoxClick}>
const [roomData, setRoomData] = useState(); <Description title={room?.name}>
<Characteristic
useEffect(() => { label="Nombre d'articles"
setRoomData({name, itemCount, roomPrice, _id}) value={room?.items_count || "N/A"}
}, [name, itemCount, roomPrice, _id]); />
<Characteristic label="Prix total" value={room?.room_price || "N/A"} />
</Description>
return ( </div>
<div className="product-details" > );
<Description title={roomData.name} > };
<Characteristic label="Nombre d'articles" value={roomData.itemCount} />
<Characteristic label="Prix total" value={roomData.roomPrice} />
</Description>
</div>
);
};

View File

@ -1,46 +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 { formatRoomStats, getRooms, 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 { 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();
useEffect(() => {
setPageTitle("Toutes les rooms :");
}, [setPageTitle]);
// Mettre à jour le titre de la page dans le contexte useEffect(() => {
useEffect(() => { const fetchData = async () => {
setPageTitle("Toutes les rooms :"); const roomsStatsResponse = await getRoomStats();
}, [setPageTitle]); setStats(roomsStatsResponse);
};
useEffect(() => { fetchData();
const fetchData = async () => { }, []);
const roomsStatsResponse = await getRoomStats();
setStats(roomsStatsResponse);
};
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">
</div>
</div> </div>
<div className="detailContainer"> <div className="listContainer">
<RoomStats statsParam={stats} /> <RoomList statsParam={stats} onRoomClick={handleRoomClick}></RoomList>
</div> </div>
</div>
<div className="detailContainer">
<RoomDetail
selectedRoom={selectedRoom}
onBack={handleRoomClick}
></RoomDetail>
</div>
</div> </div>
); );
}; };