commit final

This commit is contained in:
2024-05-13 01:42:15 +02:00
parent 6506d6817b
commit 1e3dcf340d
20 changed files with 103 additions and 53 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -11,6 +11,27 @@ Victor DESCAMPS
the tests sheet 'api/image-request.test.jsx' was commented out to avoid over-sending requests to the google API during development. Remember to uncomment the file if you want to run all the tests once, but remember to recomment the file if you want to run a series of tests.
An over-sending of requests could get us blocked for the day by google.
## Project summary (FR):
Nous n'avons pas r<>ussi <20> mettre en <20>uvre toutes les fonctionnalit<69>s de l'interface utilisateur <20> temps. Le d<>veloppement n'a pas non plus <20>t<EFBFBD> rigoureusement test-driven.
r<EFBFBD>sum<EFBFBD> des fonctionnalit<69>s :
En se connectant, l'utilisateur peut charger la liste des articleset les filtrer par pi<70>ce, date, nom, etc. Il est possible de cr<63>er et de mettre <20> jour des articles.
(Il n'y a pas de confirmation de r<>ussite ou d'<27>chec de cr<63>ation/update. La page doit <20>tre actualis<69>e pour voir les r<>sultats.)
Une page permet de consulter les statistiques des pi<70>ces et la liste des pi<70>ces. Il est possible d'y cr<63>er de nouvelles. La mise <20> jour des pi<70>cesn'est pas encore impl<70>ment<6E>e.
Les icones AntDesign provoquent syst<73>matiquement une exception dans la console. Nous n'avons pas <20>t<EFBFBD> en mesure de corriger ou <20>viter cette erreur. Les icones s'affichent bien, donc <20>a ne posera pas de probl<62>me <20> part la pollution de la console.
Nous avons voulu personnaliser un peu notre projet pour le diff<66>rencier des autres, nous avons donc mis en place un syst<73>me simple de recherche automatique d'images li<6C>es aux objets enregistr<74>s, et une requ<71>te <20> l'API Inspirobot <20> chaque rechargement de la page sur la page d'accueil pour un accueil chaleureux.
Nous sommes conscients que ce projet ne correspond pas exactement aux attentes d'un d<>veloppement full test-driven. Mais nous nous satisfaisons tout de m<>me de nous <20>tre familiaris<69>s avec js et React, avec les tests en g<>n<EFBFBD>ral, et d'avoir pris du plaisir <20> d<>velopper ce petit projet.
Nous vous souhaitons une bonne correction et vous remercions pour vos cours.
Traduit avec DeepL.com (version gratuite)
## Run Locally

View File

@@ -1,11 +1,11 @@
.diagram-container {
width: 100%; /* Utilise toute la largeur horizontale disponible */
width: 100%;
margin-bottom: 20px;
}
.row-container {
display: flex;
align-items: flex-end; /* Alignement des <20>l<EFBFBD>ments <20> la base */
align-items: flex-end;
margin-bottom: 10px;
}
@@ -20,9 +20,9 @@
.value {
position: absolute;
bottom: 50%; /* Alignement par rapport <20> la base de l'<27>l<EFBFBD>ment parent */
bottom: 50%;
right: 0;
transform: translate(50%, 50%); /* Ajustement de la position */
transform: translate(50%, 50%);
color: white;
font-size: 12px;
padding: 5px;
@@ -35,6 +35,6 @@
text-align: center;
font-size: 14px;
color: #333;
position: relative; /* Permet l'alignement des labels <20> la base */
bottom: 0; /* Alignement <20> la base */
position: relative;
bottom: 0;
}

View File

@@ -87,12 +87,10 @@
}
/* Style pour les boutons de pagination */
.pagination button {
margin: 0 5px;
}
/* Style pour les ItemBox */
.item-container .item-list .ant-col {
display: flex;
justify-content: center;

View File

@@ -9,7 +9,7 @@
border-radius: 8px;
padding: 15px;
margin-bottom: 20px;
width: 250px; /* Largeur ajustable en fonction de votre mise en page */
width: 250px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

View File

@@ -1,4 +1,3 @@
/* CSS pour la fen<65>tre modale */
.modal {
display: flex;
justify-content: center;

View File

@@ -1,22 +1,22 @@
.list-container {
width: 100%;
max-height:500px;
overflow-y: auto; /* Activer le d<>filement vertical si n<>cessaire */
padding: 20px; /* Espace int<6E>rieur de la liste */
overflow-y: auto;
padding: 20px;
}
.room-details {
width: 100%; /* Largeur de chaque bo<62>te */
width: 100%;
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<62>te */
margin-bottom: 20px;
transition: transform 0.3s ease;
}
.room-details:hover {
transform: translateY(-5px); /* Effet d'<27>l<EFBFBD>vation au survol */
transform: translateY(-5px);
}
.room-details .title {

View File

@@ -15,8 +15,8 @@ const Diagram = ({ data }) => {
<div className="diagram-container">
<h2>Prix total par an</h2>
{diagramData.map(({ name, value }) => {
// Appliquer l'<27>chelle logarithmique <EFBFBD> la valeur
const scaledValue = Math.log(value + 1); // Ajouter 1 pour <20>viter le logarithme de z<>ro
// Appliquer l'<27>chelle logarithmique sur la valeur
const scaledValue = Math.log(value + 1);
const scaledMaxValue = Math.log(maxValue + 1);
return (
<div key={name} className="row-container">

View File

@@ -32,8 +32,7 @@ export const FormCreateItem = ({ onClose }) => {
values,
);
console.log(response.data);
// Fermer la fenêtre modale après soumission réussie
onClose();
} catch (error) {
console.error(error);
}

View File

@@ -75,8 +75,7 @@ export const FormUpdateItem = ({ itemId, onClose }) => {
values,
);
console.log(response.data);
// Fermer la fenêtre modale après soumission réussie
onClose();
} catch (error) {
console.error(error);
}
@@ -87,7 +86,7 @@ export const FormUpdateItem = ({ itemId, onClose }) => {
<Form
form={form}
onFinish={onFinish}
initialValues={item} // Initialise le formulaire avec les valeurs de l'élément
initialValues={item}
>
<h1>Update Item</h1>
<Form.Item label="Brand" name="brand">

View File

@@ -0,0 +1,58 @@
import React, { useState, useEffect } from "react";
import {getRoom } from '../../api/room'
import { Form, Input, Button } from "antd";
import axios from "axios";
export const FormUpdateRoom = ({_id}) => {
const [form] = Form.useForm();
const [room, setRoom] = useState();
//useEffect(() => {
// const fetchData = async () => {
// const roomsResponse = await getRoom(_id);
// setRoom(roomsResponse);
// console.log(roomsResponse);
// };
// fetchData();
//}, [_id]);
//useEffect(() => {
// if (room) {
// form.setFieldsValue({
// ...room
// });
// }
//}, [room, form]);
const onFinish = async (values) => {
try {
const response = await axios.post(
`${import.meta.env.VITE_API_URL}/room`,
values,
);
console.log(response.data);
} catch (error) {
console.error(error);
}
};
return (
<Form form={form} onFinish={onFinish}>
<Form.Item
label="Room Name"
name="name"
rules={[{ required: true, message: "Please input the room name!" }]}
>
<Input />
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
);
};
export default FormUpdateRoom;

View File

@@ -6,16 +6,13 @@ import { Image } from "../parts/image";
import { Description } from "../parts/description";
import { Characteristic } from "../parts/characteristic";
// Composant Détails du Produit
export const ItemBox = ({ model, brand, purchaseDate, price, _id }) => {
const [isModalOpen, setIsModalOpen] = useState(false);
// Fonction pour ouvrir la fenêtre modale
const openModal = () => {
setIsModalOpen(true);
};
// Fonction pour fermer la fenêtre modale
const closeModal = () => {
setIsModalOpen(false);
};

View File

@@ -25,9 +25,7 @@ function getItem(key, label) {
const { SubMenu } = Menu;
// Component
const Navbar = () => {
//Hook calls
const [rooms, setRooms] = useState([]);
useEffect(() => {
@@ -56,7 +54,6 @@ const Navbar = () => {
</Menu.Item>,
];
// Rendu du composant Navbar
try {
return (
<Menu

View File

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

View File

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

View File

@@ -2,7 +2,6 @@
import React, { useEffect, useState } from 'react';
import { searchAndResizeImage } from '../../api/image-request'
// Composant Image
export const Image = ({ src, alt, request, _id }) => {
const [cacheUrl, setCacheUrl] = useState(null);
@@ -28,7 +27,7 @@ export const Image = ({ src, alt, request, _id }) => {
return <img src={src} alt={alt} style={{ display: 'block', margin: 'auto' }} width='150px' height='150px' />;
} else if (cacheUrl) {
return <img src={cacheUrl} alt={alt} style={{ display: 'block', margin: 'auto' }} width='150px' height='150px' />;
} else {
return <img src={"https://media.discordapp.net/attachments/1164176196930637956/1167746303820840990/IMG_20231028_104620.jpg?ex=663ddefe&is=663c8d7e&hm=0985ce123fd1751f65388f7fefde5db6ce817e514e30f1d3c81eb28b15e78453&=&"} alt={alt} style={{ display: 'block', margin: 'auto' }} width='150px' height='150px' />;
} else {//default image
return <img src={"https://cdn.discordapp.com/attachments/1164176196930637956/1213857681362784266/dinorundiscord.gif?ex=6642258f&is=6640d40f&hm=cf0ca54df3e002a15049618a6654b22c5d0c7943dc420e84936635725aceb90f&"} alt={alt} style={{ display: 'block', margin: 'auto' }} width='150px' height='150px' />;
}
}

View File

@@ -1,11 +1,10 @@
import React, { useEffect, useState } from "react";
import { FormCreateRoom } from "../../components/form/formCreateRoom";
//import { RoomUpdateForm } from './RoomUpdateForm';
import { FormUpdateRoom } from "../../components/form/formUpdateRoom";
export const RoomDetail = ({
selectedRoom,
onCreateFormSubmit,
onUpdateFormSubmit,
onBack,
}) => {
const [isUpdateFormVisible, setIsUpdateFormVisible] = useState(false);
@@ -16,12 +15,6 @@ export const RoomDetail = ({
}
}, [selectedRoom]);
// Afficher le formulaire de mise <20> jour lorsqu'une chambre est s<>lectionn<6E>e
const handleRoomClick = () => {
setIsUpdateFormVisible(true);
};
// Afficher le formulaire de cr<63>ation lorsqu'on revient en arri<72>re
const handleBackClick = () => {
setIsUpdateFormVisible(false);
onBack(null);
@@ -31,9 +24,9 @@ export const RoomDetail = ({
<div className="room-detail">
{isUpdateFormVisible ? (
<div>
<h2>Modifier une chambre</h2>
<h2>Modifier une chambre (non fonctionnel)</h2>
<FormCreateRoom onSubmit={onCreateFormSubmit} />
<FormUpdateRoom />
</div>
) : (
<div>

View File

@@ -3,16 +3,8 @@ import "../../assets/styles/room-list.css";
import { RoomBox } from "../../components/rooms/roomBox";
import { formatRoomStats } from "../../api/room";
// Fonction pour diviser le tableau d'items en rang<6E>es
const chunkArray = (arr, size) => {
const chunkedArr = [];
for (let i = 0; i < arr.length; i += size) {
chunkedArr.push(arr.slice(i, i + size));
}
return chunkedArr;
};
// Composant d'affichage de la page
export const RoomList = ({ statsParam, onRoomClick }) => {
const [rooms, setRooms] = useState([]);
const [selectedRoom, setSelectedRoom] = useState("all");

View File

@@ -21,7 +21,7 @@ const RoomStats = ({statsParam}) => {
useEffect(() => {
if (stats) {
let table = Object.entries(stats.years)
.filter(([year, value]) => value !== 0) // Filtrer les entr<74>es o<> Y n'est pas <20>gal <20> 0
.filter(([year, value]) => value !== 0)
.map(([year, value]) => ({ name: year, value: value }));
setDiagramValues(table);
}