resolve conflicts btw ts interface
This commit is contained in:
@@ -1,56 +0,0 @@
|
||||
import styles from "./Filter.module.css";
|
||||
import Button from "../ui/button/button.tsx"
|
||||
|
||||
function Filter({isFilterVisible, filters, setFilters}){
|
||||
const setAlphabeticalOrder = (order) => {
|
||||
setFilters(prev => ({
|
||||
...prev,
|
||||
alphabetical : prev.alphabetical === order ? null : order
|
||||
}));
|
||||
};
|
||||
|
||||
const setYearOrder = (order) => {
|
||||
setFilters(prev => ({
|
||||
...prev,
|
||||
yearOrder: prev.yearOrder === order ? null : order
|
||||
}));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`${styles.filterContainer} ${isFilterVisible ? styles.filterOpen : styles.filterClose}`}>
|
||||
<abbr title="Tri alphabétique croissant (A à Z)">
|
||||
<Button className={`${styles.filterTag} glassCard ${filters.alphabetical !== "asc" ? "" : styles.active}`}
|
||||
variant={"default"}
|
||||
onClick={() => setAlphabeticalOrder("asc")}>
|
||||
<img src={"sortByAlpha.svg"} alt="Tri alphabétique croissant (A à Z)"/>
|
||||
</Button>
|
||||
</abbr>
|
||||
|
||||
<abbr title="Tri alphabétique décroissant (Z à A)">
|
||||
<Button className={`${styles.filterTag} glassCard ${filters.alphabetical !== "desc" ? "" : styles.active}`}
|
||||
variant={"default"}
|
||||
onClick={() => setAlphabeticalOrder("desc")}>
|
||||
<img src={"sortByAntiAlpha.svg"} alt="Tri alphabétique décroissant (Z à A)"/>
|
||||
</Button>
|
||||
</abbr>
|
||||
|
||||
<abbr title="Tri chronologique décroissant (du plus récent au plus ancien)">
|
||||
<Button className={`${styles.filterTag} glassCard ${filters.yearOrder !== "desc" ? "" : styles.active}`}
|
||||
variant={"default"}
|
||||
onClick={() => setYearOrder("desc")}>
|
||||
<img src={"timerArrowUp.svg"} alt="Tri chronologique décroissant (du plus récent au plus ancien)"/>
|
||||
</Button>
|
||||
</abbr>
|
||||
|
||||
<abbr title="Tri chronologique croissant (du plus ancien au plus récent)">
|
||||
<Button className={`${styles.filterTag} glassCard ${filters.yearOrder !== "asc" ? "" : styles.active}`}
|
||||
variant={"default"}
|
||||
onClick={() => setYearOrder("asc")}>
|
||||
<img src={"timerArrowDown.svg"} alt="Tri chronologique croissant (du plus ancien au plus récent)"/>
|
||||
</Button>
|
||||
</abbr>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Filter;
|
||||
@@ -0,0 +1,78 @@
|
||||
import styles from "./Filter.module.css";
|
||||
import Button from "../ui/button/button";
|
||||
import React from "react";
|
||||
|
||||
type FiltersType = {
|
||||
alphabetical: "asc" | "desc" | null;
|
||||
yearOrder: "asc" | "desc" | null;
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
type FilterProps = {
|
||||
isFilterVisible: boolean;
|
||||
filters: FiltersType;
|
||||
setFilters: React.Dispatch<React.SetStateAction<FiltersType>>;
|
||||
};
|
||||
|
||||
function Filter({ isFilterVisible, filters, setFilters }: FilterProps): any {
|
||||
|
||||
const setAlphabeticalOrder = (order: "asc" | "desc"): void => {
|
||||
setFilters((prev) => ({
|
||||
...prev,
|
||||
alphabetical: prev.alphabetical === order ? null : order
|
||||
}));
|
||||
};
|
||||
|
||||
const setYearOrder = (order: "asc" | "desc"): void => {
|
||||
setFilters((prev) => ({
|
||||
...prev,
|
||||
yearOrder: prev.yearOrder === order ? null : order
|
||||
}));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`${styles.filterContainer} ${isFilterVisible ? styles.filterOpen : styles.filterClose}`}>
|
||||
<abbr title="Tri alphabétique croissant (A à Z)">
|
||||
<Button
|
||||
className={`${styles.filterTag} glassCard ${filters.alphabetical !== "asc" ? "" : styles.active}`}
|
||||
variant={"default"}
|
||||
onClick={() => setAlphabeticalOrder("asc")}
|
||||
>
|
||||
<img src={"sortByAlpha.svg"} alt="Tri alphabétique croissant (A à Z)" />
|
||||
</Button>
|
||||
</abbr>
|
||||
|
||||
<abbr title="Tri alphabétique décroissant (Z à A)">
|
||||
<Button
|
||||
className={`${styles.filterTag} glassCard ${filters.alphabetical !== "desc" ? "" : styles.active}`}
|
||||
variant={"default"}
|
||||
onClick={() => setAlphabeticalOrder("desc")}
|
||||
>
|
||||
<img src={"sortByAntiAlpha.svg"} alt="Tri alphabétique décroissant (Z à A)" />
|
||||
</Button>
|
||||
</abbr>
|
||||
|
||||
<abbr title="Tri chronologique décroissant (du plus récent au plus ancien)">
|
||||
<Button
|
||||
className={`${styles.filterTag} glassCard ${filters.yearOrder !== "desc" ? "" : styles.active}`}
|
||||
variant={"default"}
|
||||
onClick={() => setYearOrder("desc")}
|
||||
>
|
||||
<img src={"timerArrowUp.svg"} alt="Tri chronologique décroissant (du plus récent au plus ancien)" />
|
||||
</Button>
|
||||
</abbr>
|
||||
|
||||
<abbr title="Tri chronologique croissant (du plus ancien au plus récent)">
|
||||
<Button
|
||||
className={`${styles.filterTag} glassCard ${filters.yearOrder !== "asc" ? "" : styles.active}`}
|
||||
variant={"default"}
|
||||
onClick={() => setYearOrder("asc")}
|
||||
>
|
||||
<img src={"timerArrowDown.svg"} alt="Tri chronologique croissant (du plus ancien au plus récent)" />
|
||||
</Button>
|
||||
</abbr>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Filter;
|
||||
@@ -10,6 +10,7 @@ import { userNotificationsListener } from "../../utils/echo/listeners/userNotifi
|
||||
import NotificationCard from "../NotificationCard/NotificationCard.jsx";
|
||||
import { EventContext } from "../../contexts/events/EventContext.js";
|
||||
import {AuthContext} from "../../contexts/auth/AuthContext.js";
|
||||
import { PendingMembersContext } from "../../contexts/pendingMembers/PendingMembersContext";
|
||||
|
||||
function Header() {
|
||||
|
||||
@@ -20,6 +21,7 @@ function Header() {
|
||||
const [mobileMenu, setMobileMenu] = useState(false);
|
||||
const [notifications, setNotifications] = useState([]);
|
||||
const notificationRef = useRef(null);
|
||||
const { updatePendingMembers } = useContext(PendingMembersContext);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -41,7 +43,7 @@ function Header() {
|
||||
echoInstance = echo;
|
||||
|
||||
const activeChannels = [
|
||||
userCreatedListener(echo, user, setNotifications, setunreadNotification),
|
||||
userCreatedListener(echo, user, setNotifications, setunreadNotification, updatePendingMembers),
|
||||
userNotificationsListener(echo, user, setNotifications, setunreadNotification),
|
||||
];
|
||||
channelsToLeave = activeChannels.filter(name => name !== null);
|
||||
@@ -86,7 +88,7 @@ function Header() {
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Erreur suppression notification :', err);
|
||||
console.error('Erreur pour ouvrir/fermer le menu de notifications :', err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
import styles from "./SearchBar.module.css"
|
||||
import {Link} from "react-router";
|
||||
import {useEffect, useState} from "react";
|
||||
import searchEvents from "../../utils/events/searchEvents.js";
|
||||
import searchUsers from "../../utils/users/searchUsers.js";
|
||||
import { useLocation } from "react-router";
|
||||
|
||||
|
||||
function SearchBar() {
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [searchResults, setSearchResults] = useState([]);
|
||||
const location = useLocation();
|
||||
|
||||
useEffect(() => {
|
||||
const performSearch = async (query) => {
|
||||
if (query.trim() === '') {
|
||||
setSearchResults([]);
|
||||
return;
|
||||
}
|
||||
|
||||
let data;
|
||||
|
||||
if (location.pathname.includes("events")) {
|
||||
data = await searchEvents(query);
|
||||
} else if (location.pathname.includes("volunteers")) {
|
||||
data = await searchUsers(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={(element) => element.preventDefault()}>
|
||||
<img src="search.svg" alt="Rechercher"/>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Rechercher un événement"
|
||||
value={searchQuery}
|
||||
onChange={(element) => setSearchQuery(element.target.value)}
|
||||
/>
|
||||
</form>
|
||||
|
||||
<div className={styles.lineContainer}>
|
||||
{searchResults.length > 0 ? (
|
||||
<div className={styles.line}></div>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div className={styles.elementList}>
|
||||
{searchResults.map((result, i) => (
|
||||
(location.pathname.includes("events")) ? (
|
||||
<Link to={`/events/` + result.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>
|
||||
) : location.pathname.includes("volunteers") ? (
|
||||
<Link to={`/profile/` + result.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} {result.lastname}</p>
|
||||
</div>
|
||||
</Link>
|
||||
) : null
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default SearchBar;
|
||||
@@ -1,6 +1,8 @@
|
||||
.searchBarContainer{
|
||||
position: fixed;
|
||||
top: 4rem;
|
||||
top: 20vh;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
z-index: 100;
|
||||
width: 60%;
|
||||
background: #fff;
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
import styles from "./SearchBar.module.css";
|
||||
import { Link } from "react-router";
|
||||
import { useEffect, useState } from "react";
|
||||
import searchEvents from "../../utils/events/searchEvents.js";
|
||||
import searchUsers from "../../utils/users/searchUsers.js";
|
||||
import { useLocation } from "react-router";
|
||||
|
||||
function SearchBar(): any {
|
||||
const [searchQuery, setSearchQuery] = useState<string>("");
|
||||
const [searchResults, setSearchResults] = useState<any[]>([]);
|
||||
const location: any = useLocation();
|
||||
|
||||
useEffect(() => {
|
||||
const performSearch = async (query: string): Promise<void> => {
|
||||
if (query.trim() === "") {
|
||||
setSearchResults([]);
|
||||
return;
|
||||
}
|
||||
|
||||
let data: any;
|
||||
|
||||
if (location.pathname.includes("events")) {
|
||||
data = await searchEvents(query);
|
||||
} else if (location.pathname.includes("volunteers")) {
|
||||
data = await searchUsers(query);
|
||||
}
|
||||
|
||||
if (data) {
|
||||
setSearchResults(data);
|
||||
} else {
|
||||
setSearchResults([]);
|
||||
}
|
||||
};
|
||||
|
||||
const handler: ReturnType<typeof setTimeout> = setTimeout(() => {
|
||||
performSearch(searchQuery);
|
||||
}, 300);
|
||||
|
||||
return () => {
|
||||
clearTimeout(handler);
|
||||
};
|
||||
}, [searchQuery, location.pathname]);
|
||||
|
||||
return (
|
||||
<div className={`${styles.searchBarContainer} glassCard`}>
|
||||
<form
|
||||
className={styles.searchBarForm}
|
||||
onSubmit={(element: React.FormEvent<HTMLFormElement>) =>
|
||||
element.preventDefault()
|
||||
}
|
||||
>
|
||||
<img src="search.svg" alt="Rechercher" />
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Rechercher un événement"
|
||||
value={searchQuery}
|
||||
onChange={(element: React.ChangeEvent<HTMLInputElement>) =>
|
||||
setSearchQuery(element.target.value)
|
||||
}
|
||||
/>
|
||||
</form>
|
||||
|
||||
<div className={styles.lineContainer}>
|
||||
{searchResults.length > 0 ? (
|
||||
<div className={styles.line}></div>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div className={styles.elementList}>
|
||||
{searchResults.map((result: any, i: number) =>
|
||||
location.pathname.includes("events") ? (
|
||||
<Link to={`/events/` + result.id} key={i}>
|
||||
<div className={styles.searchedEvent}>
|
||||
<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>
|
||||
) : location.pathname.includes("volunteers") ? (
|
||||
<Link to={`/profile/` + result.id} key={i}>
|
||||
<div className={styles.searchedEvent}>
|
||||
<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} {result.lastname}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
) : null
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default SearchBar;
|
||||
@@ -1,29 +0,0 @@
|
||||
import React, {useEffect, useState} from "react";
|
||||
import getEventById from "../../utils/events/getEventById.js";
|
||||
import styles from "./Task.module.css";
|
||||
import formatDate from "../../utils/date/formatDate.js";
|
||||
|
||||
const Task = ({ task }) => {
|
||||
const [event, setEvent] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const e = await getEventById(task.id);
|
||||
setEvent(e.data);
|
||||
}) ()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className={`${styles.task} glassCard`}>
|
||||
<div className={styles.content}>
|
||||
<div>
|
||||
<h2> {event && event.name} - {task.name}</h2>
|
||||
<p className={styles.desc}> {task.description} </p>
|
||||
<p className={styles.date}> {formatDate(task.start)} </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Task;
|
||||
@@ -0,0 +1,71 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import getEventById from "../../utils/events/getEventById.js";
|
||||
import styles from "./Task.module.css";
|
||||
import formatDate from "../../utils/date/formatDate";
|
||||
|
||||
interface TaskType {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
location: string;
|
||||
start: string;
|
||||
end: string;
|
||||
max_participants: number;
|
||||
events_id: number;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
pivot: {
|
||||
user_id: number;
|
||||
task_id: number;
|
||||
};
|
||||
}
|
||||
|
||||
interface EventType {
|
||||
id: number;
|
||||
name: string;
|
||||
description?: string;
|
||||
location?: string;
|
||||
start?: string;
|
||||
end?: string;
|
||||
created_at?: string;
|
||||
updated_at?: string;
|
||||
}
|
||||
|
||||
interface TaskProps {
|
||||
task: TaskType;
|
||||
}
|
||||
|
||||
const Task: React.FC<TaskProps> = ({ task }) => {
|
||||
const [event, setEvent] = useState<EventType | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchEvent = async (): Promise<void> => {
|
||||
try {
|
||||
const e = await getEventById(task.events_id);
|
||||
setEvent(e.data as EventType);
|
||||
} catch (error) {
|
||||
console.error("Erreur lors du chargement de l'événement", error);
|
||||
}
|
||||
};
|
||||
|
||||
fetchEvent();
|
||||
}, [task.events_id]);
|
||||
|
||||
return (
|
||||
<div className={`${styles.task} glassCard`}>
|
||||
<div className={styles.content}>
|
||||
<div>
|
||||
<h2>
|
||||
{event?.name} - {task.name}
|
||||
</h2>
|
||||
<p className={styles.desc}>{task.description}</p>
|
||||
<p className={styles.date}>
|
||||
{formatDate(task.start)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Task;
|
||||
@@ -1,59 +1,16 @@
|
||||
import styles from "./ToolBar.module.css"
|
||||
import Filter from "../Filter/Filter.jsx";
|
||||
import {useContext, useEffect, useState} from "react";
|
||||
import SearchBar from "../SearchBar/SearchBar.jsx";
|
||||
import CreateEventBtn from "../createEventBtn/CreateEventBtn.jsx";
|
||||
import Button from "../ui/button/button.tsx";
|
||||
import {AuthContext} from "../../contexts/auth/AuthContext.js";
|
||||
import CreateEventBtn from "./tools/createEventBtn/CreateEventBtn.jsx";
|
||||
import SearchBtn from "./tools/SearchBtn.tsx";
|
||||
import FilterBtn from "./tools/FilterBtn.tsx";
|
||||
|
||||
function ToolBar({setFilters, filters, showCreate = true}) {
|
||||
const { user } = useContext(AuthContext);
|
||||
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}>
|
||||
{showCreate && user.isAdmin ? (
|
||||
<CreateEventBtn />
|
||||
) : null}
|
||||
|
||||
<Button className={`${styles.searchButton} glassCard`} variant={"default"} onClick={() => setIsSearchVisible(true)}>
|
||||
<img src="search.svg" alt="Rechercher"/>
|
||||
</Button>
|
||||
|
||||
<div className={`${styles.filterContainer} ${isFilterVisible ? "glassCard" : ""}`}>
|
||||
<Button className={`${isFilterVisible ? "" : styles.mobileFilter} ${styles.sortButton} glassCard`} variant={"default"} onClick={toggleFilters}>
|
||||
<img src="filter.svg" alt="Filtrer"/>
|
||||
</Button>
|
||||
<div className={styles.filterMenu}>
|
||||
<Filter isFilterVisible={isFilterVisible} filters={filters} setFilters={setFilters}/>
|
||||
</div>
|
||||
</div>
|
||||
{showCreate && <CreateEventBtn />}
|
||||
<SearchBtn />
|
||||
<FilterBtn setFilters={setFilters} filters={filters} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import styles from "../ToolBar.module.css"
|
||||
import Button from "../../ui/button/button";
|
||||
import { useState } from "react";
|
||||
import Filter from "../../Filter/Filter";
|
||||
|
||||
interface Filters {
|
||||
alphabetical: "asc" | "desc";
|
||||
yearOrder: "asc" | "desc";
|
||||
}
|
||||
|
||||
interface FilterBtnProps {
|
||||
setFilters: any
|
||||
filters: Filters
|
||||
}
|
||||
|
||||
export default function FilterBtn({ setFilters, filters }: FilterBtnProps) {
|
||||
|
||||
const [isFilterVisible, setIsFilterVisible] = useState(false);
|
||||
|
||||
const toggleFilters = () => {
|
||||
setIsFilterVisible(prev => !prev);
|
||||
};
|
||||
|
||||
return <div className={`${styles.filterContainer} ${isFilterVisible ? "glassCard" : ""}`}>
|
||||
<Button className={`${isFilterVisible ? "" : styles.mobileFilter} ${styles.sortButton} glassCard`} variant={"default"} onClick={toggleFilters}>
|
||||
<img src="filter.svg" alt="Filtrer"/>
|
||||
</Button>
|
||||
<div className={styles.filterMenu}>
|
||||
<Filter isFilterVisible={isFilterVisible} filters={filters} setFilters={setFilters}/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import styles from "../ToolBar.module.css"
|
||||
import Button from "../../ui/button/button";
|
||||
import { useEffect, useState } from "react";
|
||||
import SearchBar from "../../SearchBar/SearchBar";
|
||||
|
||||
export default function SearchBtn() {
|
||||
|
||||
const [isSearchVisible, setIsSearchVisible] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (isSearchVisible) {
|
||||
document.documentElement.style.overflow = 'hidden';
|
||||
} else {
|
||||
document.documentElement.style.overflow = '';
|
||||
}
|
||||
|
||||
return () => {
|
||||
document.documentElement.style.overflow = '';
|
||||
};
|
||||
}, [isSearchVisible]);
|
||||
|
||||
return <>
|
||||
|
||||
{isSearchVisible ? (
|
||||
<div className={styles.searchBarContainer}>
|
||||
<div className={styles.searchBarOverlay} onClick={() => setIsSearchVisible(false)}></div>
|
||||
<SearchBar/>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<div>
|
||||
<Button className={`${styles.searchButton} glassCard`} variant={"default"} onClick={() => setIsSearchVisible(true)}>
|
||||
<img src="search.svg" alt="Rechercher"/>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
</>
|
||||
}
|
||||
+8
-4
@@ -1,14 +1,16 @@
|
||||
import styles from "./createEventBtn.module.css"
|
||||
import { useState, useContext } from "react";
|
||||
import Modal from "../ui/modal/modal.tsx";
|
||||
import Button from "../ui/button/button.tsx";
|
||||
import TextInput from "../ui/input/input.tsx";
|
||||
import { EventContext } from "../../contexts/events/EventContext.js";
|
||||
import Modal from "../../../ui/modal/modal.tsx";
|
||||
import Button from "../../../ui/button/button.tsx";
|
||||
import TextInput from "../../../ui/input/input.tsx";
|
||||
import { EventContext } from "../../../../contexts/events/EventContext.js";
|
||||
import {AuthContext} from "../../../../contexts/auth/AuthContext.ts";
|
||||
|
||||
|
||||
export default function CreateEventBtn() {
|
||||
|
||||
const { addEvent } = useContext(EventContext);
|
||||
const { user } = useContext(AuthContext);
|
||||
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [name, setName] = useState("");
|
||||
@@ -24,6 +26,8 @@ export default function CreateEventBtn() {
|
||||
setIsOpen(false);
|
||||
}
|
||||
|
||||
if(!user.isAdmin) return null;
|
||||
|
||||
return <>
|
||||
<Button className={`${styles.createButton} glassCard`} variant={"default"} onClick={() => setIsOpen(true)}> + </Button>
|
||||
|
||||
@@ -7,7 +7,7 @@ interface ButtonProps {
|
||||
children: ReactNode;
|
||||
variant?: ButtonVariant;
|
||||
onClick?: MouseEventHandler<HTMLDivElement>;
|
||||
className?: string;
|
||||
className?: string | undefined;
|
||||
}
|
||||
|
||||
const Button = ({
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
.wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
width: 100%;
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
|
||||
border: 5px solid #e0e0e0;
|
||||
border-top: 5px solid #3498db;
|
||||
|
||||
border-radius: 50%;
|
||||
animation: spin 0.8s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import React from "react";
|
||||
import styles from "./loading.module.css";
|
||||
|
||||
const Loading: React.FC = () => {
|
||||
return (
|
||||
<div className={styles.wrapper}>
|
||||
<div className={styles.spinner} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Loading;
|
||||
Reference in New Issue
Block a user