T'JAMPENS QUENTIN p2406187 committed 2025-12-09 09:41:17 +01:00
commit d5f8e16ec3
14 files changed
+433 -198

No files matched your search

+13 -10
View File
@@ -42,17 +42,20 @@ function Event({event}){
<div className={styles.eventInfos}>
<p className={styles.eventTitle}>{event.name}</p>
<p>{event.description}</p>
<ul className={eventMenu ? styles.eventMenuOpen : styles.eventMenuClose}>
{event.tasks.length > 0 && (
<>
{event.tasks.slice(0, 5).map((task, index) => (
<li key={index}> {task.name} </li>
{event.tasks != null ? (
<div className={eventMenu ? styles.eventMenuOpen : styles.eventMenuClose}>
<ul>
{event.tasks
.slice(0,5)
.map((task, index) => (
<li key={index}> - {task.name}</li>
))}
{event.tasks.length > 5 && <li>...</li>}
</>
)}
</ul>
{event.tasks.length > 5 ? (
<li>...</li>
) : null}
</ul>
</div>
) : null}
</div>
</div>
{windowSize.width > 768 ? (
+1
View File
@@ -8,6 +8,7 @@
.eventContainerTop {
display: flex;
justify-content: space-between;
}
.eventContainerBottom{
+75
View File
@@ -0,0 +1,75 @@
import styles from "./SearchBar.module.css"
import {Link} from "react-router";
import {useEffect, useState} from "react";
import searchEvents from "../../utils/searchEvents.js";
function SearchBar() {
const [searchQuery, setSearchQuery] = useState('');
const [searchResults, setSearchResults] = useState([]);
useEffect(() => {
const performSearch = async (query) => {
if (query.trim() === '') {
setSearchResults([]);
return;
}
const data = await searchEvents(query);
if (data) {
setSearchResults(data);
} else {
setSearchResults([]);
}
};
const handler = setTimeout(() => {
performSearch(searchQuery);
}, 300);
return () => {
clearTimeout(handler);
};
}, [searchQuery]);
return (
<div className={`${styles.searchBarContainer} glassCard`}>
<form className={styles.searchBarForm} onSubmit={(event) => event.preventDefault()}>
<svg xmlns="http://www.w3.org/2000/svg" width="24px" viewBox="0 -960 960 960" fill="#currentColor">
<path
d="M784-120 532-372q-30 24-69 38t-83 14q-109 0-184.5-75.5T120-580q0-109 75.5-184.5T380-840q109 0 184.5 75.5T640-580q0 44-14 83t-38 69l252 252-56 56ZM380-400q75 0 127.5-52.5T560-580q0-75-52.5-127.5T380-760q-75 0-127.5 52.5T200-580q0 75 52.5 127.5T380-400Z"/>
</svg>
<input
type="text"
placeholder="Rechercher un événement"
value={searchQuery}
onChange={(event) => setSearchQuery(event.target.value)}
/>
</form>
<div className={styles.lineContainer}>
{searchResults.length > 0 ? (
<div className={styles.line}></div>
) : null}
</div>
{searchResults.map((result, i) => (
<Link to={`/event/` + event.id}>
<div className={styles.searchedEvent} key={i}>
<div className={`${styles.eventImageDiv}`}>
{result.image == null ? (
<img src="empty.png" className={styles.eventImage} alt="Pas de photo de l'événement" />
) : (
<img src={result.image + `.png`} alt="Photo de l'événement" />
)}
</div>
<p>{result.name}</p>
</div>
</Link>
))}
</div>
);
}
export default SearchBar;
@@ -0,0 +1,73 @@
.searchBarContainer{
position: fixed;
top: 10rem;
z-index: 100;
width: 60%;
background: #fff;
}
.searchBarForm{
display: flex;
}
.eventImageDiv {
display: flex;
align-items: center;
justify-content: center;
margin-right: 1rem;
width: auto;
height: 2rem;
flex-shrink: 0;
}
.searchedEvent{
display: flex;
padding: 0.5rem;
border-radius: 15px;
align-items: center;
}
.searchedEvent:hover {
background: #afafaf;
cursor: pointer;
}
.searchedEvent p {
display: flex;
align-items: center;
text-decoration: none;
color: black;
}
.lineContainer{
display: flex;
justify-content: center;
align-items: center;
}
.line{
height: 0;
width: 96%;
border: #606060 solid 1px;
margin: 0.5rem 0;
}
.eventImage {
max-width: 100%;
max-height: 100%;
object-fit: contain;
border-radius: 20px;
}
.searchBarForm input{
background: none;
box-shadow: none;
height: 2em;
}
.searchBarForm input:focus{
outline: none;
}
+66
View File
@@ -0,0 +1,66 @@
import styles from "./ToolBar.module.css"
import {Link} from "react-router";
import Filter from "../Filter/Filter.jsx";
import {useEffect, useState} from "react";
import SearchBar from "../SearchBar/SearchBar.jsx";
function ToolBar({setFilters, filters}) {
const [isFilterVisible, setIsFilterVisible] = useState(false);
const [isSearchVisible, setIsSearchVisible] = useState(false);
const toggleFilters = () => {
setIsFilterVisible(prev => !prev);
};
useEffect(() => {
if (isSearchVisible) {
document.documentElement.style.overflow = 'hidden';
} else {
document.documentElement.style.overflow = '';
}
return () => {
document.documentElement.style.overflow = '';
};
}, [isSearchVisible]);
return (
<div>
{isSearchVisible ? (
<div className={styles.searchBarContainer}>
<div className={styles.searchBarOverlay} onClick={() => setIsSearchVisible(false)}></div>
<SearchBar/>
</div>
) : null}
<div className={styles.eventsButtons}>
<Link
to="/event/create"
className={`${styles.createButton} glassCard`}>
+
</Link>
<button className={`${styles.searchButton} glassCard`} onClick={() => setIsSearchVisible(true)}>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="#currentColor">
<path d="M784-120 532-372q-30 24-69 38t-83 14q-109 0-184.5-75.5T120-580q0-109 75.5-184.5T380-840q109 0 184.5 75.5T640-580q0 44-14 83t-38 69l252 252-56 56ZM380-400q75 0 127.5-52.5T560-580q0-75-52.5-127.5T380-760q-75 0-127.5 52.5T200-580q0 75 52.5 127.5T380-400Z"/>
</svg>
</button>
<div className={`${styles.filterContainer} ${isFilterVisible ? "glassCard" : ""}`}>
<button className={`${isFilterVisible ? "" : styles.mobileFilter} ${styles.sortButton} glassCard`} onClick={toggleFilters}>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="currentColor">
<path d="M440-160q-17 0-28.5-11.5T400-200v-240L168-736q-15-20-4.5-42t36.5-22h560q26 0 36.5 22t-4.5 42L560-440v240q0 17-11.5 28.5T520-160h-80Zm40-308 198-252H282l198 252Zm0 0Z"/>
</svg>
</button>
<div className={styles.filterMenu}>
<Filter isFilterVisible={isFilterVisible} filters={filters} setFilters={setFilters}/>
</div>
</div>
</div>
</div>
);
}
export default ToolBar;
+97
View File
@@ -0,0 +1,97 @@
.eventsButtons {
overflow: visible;
position: fixed;
top: 10rem;
right: 2rem;
display: flex;
flex-direction: column;
align-items: flex-end;
width: fit-content;
height: fit-content;
gap: 1rem;
}
.filterContainer{
padding: 0;
border-radius: 30px;
overflow: visible;
}
.filterMenu{
padding: 5px 5px 5px 5px;
}
.createButton, .searchButton, .sortButton {
display: flex;
align-items: center;
justify-content: center;
border: none;
border-radius: 50%;
width: 55px;
height: 55px;
transition: all 0.5s ease;
}
.createButton {
font-size: 2rem;
color: #019AFF;
}
.createButton:hover, .searchButton:hover, .mobileFilter:hover {
transform: translateY(-5px);
cursor: pointer;
}
.searchBarOverlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 100;
background-color: rgba(0, 0, 0, 0.3);
backdrop-filter: blur(4px);
}
.searchBarContainer{
display: flex;
justify-content: center;
}
.sortButton svg, .searchButton svg {
transform: scale(0.8);
fill: #019AFF;
}
.sortButton:focus, .searchButton:focus {
outline: none;
}
@media screen and (max-width: 768px) {
.eventsButtons {
flex-direction: row;
position: relative;
top: 0;
right: 0;
align-items: flex-start;
width: 100%;
margin-top: 16px;
}
.filterContainer{
display: flex;
width: fit-content;
}
.filterMenu{
width: fit-content;
}
.createButton:hover, .searchButton:hover, .mobileFilter:hover {
transform: none !important;
}
}