Generateurv2/frontend/components/room/RoomView.jsx
2022-06-24 13:42:16 +02:00

742 lines
25 KiB
JavaScript

import { useRouter } from "next/router";
import { useContext, useEffect, useState } from "react";
import {
AiFillEyeInvisible,
AiFillUnlock,
AiOutlineCheck,
AiOutlineClose,
} from "react-icons/ai";
import ReconnectingWebSocket from "reconnecting-websocket";
import { AlertType, useAlert } from "../../context/alert.context.js";
import { useWebsocketContext } from "../../context/websocket.context.js";
import {
changeRoomName,
deleteParcours,
deleteRoom,
getRoom,
togglePublicResult,
toggleRoomLock,
} from "../../requests/requests.room.js";
import styles from "../../styles/room/roomView.module.scss";
import { isBrowser, isEmpty, parseClassName } from "../../utils/utils.js";
import Layout from "../Layout.js";
import { BsCheckLg } from "react-icons/bs";
import { BiTrash } from "react-icons/bi";
import { MdRefresh, MdExitToApp, MdEdit } from "react-icons/md";
import { IoMdExit, IoMdReturnLeft } from "react-icons/io";
import { BiEdit, BiUndo } from "react-icons/bi";
import { notificationService } from "../../services/notification.service.js";
import { AiFillLock, AiFillEye } from "react-icons/ai";
export default function RoomView({ user, id_code }) {
const [dataRoom, setDataRoom] = useState();
useEffect(() => {
if (user != undefined && (dataRoom == undefined || isEmpty(dataRoom))) {
getRoom(id_code, user.clientId)
.then((res) => {
setDataRoom(res.room);
})
.catch((err) => {
if (err.response.data.code == 111) {
setJoined(false);
router.push({ pathname: "/room/join" });
}
});
}
}, [user, dataRoom]);
const router = useRouter();
const {
ws,
send,
connect,
addMessageHandler,
removeMessageHandler,
isConnected,
disconnect,
} = useWebsocketContext();
useEffect(() => {
let handler = (e) => {
let data = JSON.parse(e.data);
let type = data.type;
switch (type) {
case "joined": {
if (dataRoom) {
let nick = data.nick;
let owner = data.owner;
let online = data.online;
let code = data.code;
let oldParticipants = dataRoom.participants;
let oldWaiters = dataRoom.waiters;
setDataRoom({
...dataRoom,
participants: [
...oldParticipants,
{ nick: nick, owner: owner, online: online, code: code },
],
waiters: [...oldWaiters.filter((w) => w.code != code)],
});
}
break;
}
case "disconnect_participant": {
if (dataRoom) {
let oldParticipants = dataRoom.participants;
let nick = data.nick;
setDataRoom({
...dataRoom,
participants: [
...oldParticipants.map((p) => {
if (p.nick == nick) {
return { ...p, online: false };
}
return p;
}),
],
});
}
break;
}
case "reconnect_participant": {
if (dataRoom) {
let oldParticipants = dataRoom.participants;
let nick = data.nick;
let participant = oldParticipants.filter((p) => p.nick == nick)[0];
participant.online = true;
setDataRoom({
...dataRoom,
participants: [
...oldParticipants.filter((p) => p.nick != nick),
participant,
],
});
}
break;
}
case "add_waiter": {
if (dataRoom) {
let nick = data.nick;
let code = data.code;
let status = data.status;
let oldWaiters = dataRoom.waiters;
setDataRoom({
...dataRoom,
waiters: [
...oldWaiters,
{ nick: nick, code: code, status: status },
],
});
}
break;
}
case "del_waiter": {
if (dataRoom) {
let code = data.code;
let oldWaiters = dataRoom.waiters;
setDataRoom({
...dataRoom,
waiters: [...oldWaiters.filter((w) => w.code != code)],
});
}
break;
}
case "banned": {
if (dataRoom) {
let nick = data.nick;
let code = data.code;
if (user.user.code != code) {
let oldParticipants = dataRoom.participants;
let oldParcours = dataRoom.parcours;
setDataRoom({
...dataRoom,
participants: [
...oldParticipants.filter((p) => p.nick != nick),
],
});
} else if (user.user.code == code) {
router.push({ pathname: "/room/join" });
}
}
break;
}
case "add_parcours": {
if (dataRoom) {
let new_parcours = data.parcours;
let id_code = dataRoom.id_code;
let oldParcours = dataRoom.parcours;
setDataRoom({
...dataRoom,
parcours: [...oldParcours, new_parcours],
});
}
break;
}
case "delete_parcours": {
if (dataRoom) {
setDataRoom({
...dataRoom,
parcours: [
...dataRoom.parcours.filter((p) => p.id_code != data.id_code),
],
});
}
break;
}
case "edit_parcours": {
if (dataRoom) {
let new_parcours = data.parcours;
let id_code = dataRoom.id_code;
let oldParcours = dataRoom.parcours;
setDataRoom({
...dataRoom,
parcours: [
...oldParcours.map((p) => {
if (p.id_code == new_parcours.id_code) {
return new_parcours;
}
return p;
}),
],
});
}
break;
}
default:
break;
}
};
addMessageHandler(handler);
return () => {
removeMessageHandler(handler);
};
}, [dataRoom]);
const alert = useAlert();
const [edit, setEdit] = useState(null);
useEffect(() => {
window.addEventListener("click", () => {
if (edit) {
setEdit(null);
}
});
});
useEffect(() => {
return () => {
disconnect();
};
}, []);
return (
<Layout page={dataRoom && dataRoom.name ? dataRoom.name : "..."}>
{isEmpty(dataRoom) && <><span className='loader'></span></>}
{dataRoom && !isEmpty(dataRoom) && (
<div className={styles["full-container"]}>
<div className={styles["head"]}>
{(edit === null || edit == false) && edit != "" && (
<h1
onClick={() => {
if (navigator.clipboard) {
navigator.clipboard.write(router.asPath).then((res) => {
notificationService.success("Lien", "Lien copié !");
});
}
}}
>
<p
className={styles.title}
onDoubleClick={(e) => {
if (user.user.owner) {
setEdit(dataRoom.name);
}
}}
title={"Double click pour modifier"}
>
{dataRoom.name}
</p>
<span>#{dataRoom.id_code}</span>
</h1>
)}
{((edit !== null && edit != false) || edit == "") && (
<div
className={styles["title-form"]}
onClick={(e) => {
e.stopPropagation();
}}
>
<input
type="text"
className="exo-input"
value={edit}
onChange={(e) => {
if (e.target.value == "") {
setEdit("");
} else {
setEdit(e.target.value);
}
}}
onKeyDown={(e) => {
if (e.code == "Enter") {
changeRoomName({
id_code: dataRoom.id_code,
clientId: sessionStorage.getItem("clientId"),
name: edit,
})
.then((res) => {
setDataRoom({ ...dataRoom, name: res.name });
setEdit(null);
})
.catch((err) => {
notificationService.error(
"Erreur",
"Erreur lors de la modification"
);
});
} else if (e.code == "Escape") {
setEdit(null);
}
}}
autoFocus={true}
/>
</div>
)}
<div className={styles["icons-container"]}>
<MdRefresh
title={"Actualiser"}
onClick={() => {
setDataRoom();
if (!isConnected) {
connect("ws://192.168.1.18:8000/ws/room/" + id_code);
}
}}
className={styles.refresh}
/>
<BiUndo
onClick={() => {
disconnect();
router.push("/room", undefined, {shallow:true});
}}
className={styles.exit}
title={"Retour à l'acceuil"}
/>
{!user.user.owner && (
<IoMdExit
className={styles.exit}
title={"Quitter"}
onClick={() => {
alert.alert({
title: "Êtes-vous sûr ?",
active: true,
message: `Voulez vous quitter le salle ? Cela effacera toute vos données sur les parcours`,
type: AlertType.Warning,
validate: () => {
send({
data: {
type: "leave",
code: user.user.code,
nick: user.user.nick,
clientId: sessionStorage.getItem("clientId"),
},
});
},
});
}}
/>
)}
{user.user.owner && (
<BiTrash
className={styles.exit}
onClick={() => {
alert.alert({
title: "Êtes-vous sûr ?",
active: true,
message: `Voulez vous supprimer le salle ?`,
type: AlertType.Warning,
validate: () => {
deleteRoom({
clientId:
isBrowser && sessionStorage.getItem("clientId"),
id_code,
})
.then((res) => {
router.push("/room/", undefined, { shallow: true });
notificationService.success(
"Suppression",
`Salle "${dataRoom.name}" supprimée`,
{ keepAfterRouteChange: true }
);
})
.catch((err) => {
notificationService.error(
"Suppression",
`Erreur lors de la suppression de la salle "${dataRoom.name}"`,
{ keepAfterRouteChange: true }
);
});
},
});
}}
/>
)}
</div>
</div>
<div className={styles["parcours-container"]}>
<div className={styles["cat-title"]}>
<p className={styles["parcours-title"]}>
{" "}
{user.user.owner &&
(dataRoom.public_result ? (
<AiFillEye
onClick={() => {
togglePublicResult({
id_code: dataRoom.id_code,
clientId: sessionStorage.getItem("clientId"),
})
.then((res) => {
setDataRoom({
...dataRoom,
public_result: res.private,
});
})
.catch((err) => {
notificationService.error(
"Erreur",
"Erreur lors de la modification"
);
});
}}
title="Appuyer pour rendre les résultats privé (les membres ne pourront voir que leurs propres résultats)"
/>
) : (
<AiFillEyeInvisible
onClick={() => {
togglePublicResult({
id_code: dataRoom.id_code,
clientId: sessionStorage.getItem("clientId"),
})
.then((res) => {
setDataRoom({
...dataRoom,
public_result: res.private,
});
})
.catch((err) => {
notificationService.error(
"Erreur",
"Erreur lors de la modification"
);
});
}}
title="Appuyer pour rendre les résultats public (les membres pourront voir les résultats des autres)"
/>
))}
Parcours{" "}
</p>
{user.user.owner && (
<button
className="exo-btn"
onClick={() => {
router.push(
{
pathname: `/room/${dataRoom.id_code}/new_parcours`,
},
undefined,
{ shallow: true }
);
}}
>
Nouveau
</button>
)}
</div>
{dataRoom.parcours.map((p) => {
return (
<div
className={styles["parcours-item"]}
onClick={() => {
router.push(
{
pathname: `/room/${dataRoom.id_code}/${p.id_code}`,
},
undefined,
{ shallow: true }
);
}}
>
<div>
{p.is_validate && <BsCheckLg />}
<p>{p.name}</p>{" "}
</div>
{user.user.owner == true && (
<BiTrash
onClick={(e) => {
e.stopPropagation();
console.log("CLICK SVG");
alert.alert({
title: "Êtes-vous sûr ?",
active: true,
message: `Voulez vous supprimer le parcours "${p.name}"`,
type: AlertType.Warning,
validate: () => {
deleteParcours({
id_code: p.id_code,
code: user.user.code,
}).then((r) => {
setDataRoom({
...dataRoom,
parcours: [
...dataRoom.parcours.filter(
(pp) => pp.id_code != r.id_code
),
],
});
});
},
});
}}
/>
)}
</div>
);
})}
{dataRoom.parcours.length == 0 && (
<p className={styles["no-parcours"]}>Aucun parcours</p>
)}
</div>
<div className={styles["participants-container"]}>
<div className={styles["cat-title"]}>
Participants{" "}
{user.user.owner &&
(dataRoom.private ? (
<AiFillLock
className={styles.lock}
title={"Rendre la salle publique"}
onClick={() => {
toggleRoomLock({
id_code: dataRoom.id_code,
clientId: sessionStorage.getItem("clientId"),
})
.then((res) => {
setDataRoom({ ...dataRoom, private: res.private });
})
.catch((err) => {
notificationService.error(
"Erreur",
"Erreur lors de la modification"
);
});
}}
/>
) : (
<AiFillUnlock
className={styles.lock}
title={"Rendre la salle privée"}
onClick={() => {
toggleRoomLock({
id_code: dataRoom.id_code,
clientId: sessionStorage.getItem("clientId"),
})
.then((res) => {
setDataRoom({ ...dataRoom, private: res.private });
})
.catch((err) => {
notificationService.error(
"Erreur",
"Erreur lors de la modification"
);
});
}}
/>
))}
</div>
<p className={parseClassName([styles.owner, styles.partCat])}>
En ligne :
</p>
{dataRoom.participants
.filter((p) => p.online)
.map((p) => {
return (
<p
className={
p.nick == user.user.nick ? styles["owner"] : undefined
}
>
<span
onClick={() => {
if (user.user.owner && p.nick != user.user.nick) {
alert.alert({
title: "Êtes-vous sûr ?",
active: true,
message: `Vous aller bannir ${p.nick}`,
type: AlertType.Warning,
validate: () => {
send({
data: {
type: "ban",
code: p.code,
nick: p.nick,
status: p.status,
},
});
},
});
}
}}
title="Bannir"
className={parseClassName([
user.user.owner ? styles["nick"] : undefined,
p.owner || user.user.nick == p.nick
? styles["isOwner"]
: undefined,
])}
>
{p.nick}
</span>
{p.nick == user.user.nick &&
isBrowser &&
localStorage.getItem("token") == null && (
<span className={styles["code"]}>
#{user.user.code}
</span>
)}
{p.owner == true && (
<span className={styles["admin"]}>Administrateur</span>
)}
{user.user.owner &&
p.nick != user.user.nick &&
p.code.length == 6 && (
<span className={styles["code"]}>#{p.code}</span>
)}
</p>
);
})}
<p className={parseClassName([styles.owner, styles.partCat])}>
Hors-ligne :
</p>
{dataRoom.participants
.filter((p) => !p.online)
.map((p) => {
return (
<p
className={
p.nick == user.user.nick ? styles["owner"] : undefined
}
>
<span
onClick={() => {
if (user.user.owner && p.nick != user.user.nick) {
alert.alert({
title: "Êtes-vous sûr ?",
active: true,
message: `Vous aller bannir ${p.nick}`,
type: AlertType.Warning,
validate: () => {
send({
data: {
type: "ban",
code: p.code,
nick: p.nick,
status: p.status,
},
});
},
});
}
}}
title="Bannir"
className={parseClassName([
user.user.owner ? styles["nick"] : undefined,
p.owner || user.user.nick == p.nick
? styles["isOwner"]
: undefined,
])}
>
{p.nick}
</span>
{p.nick == user.user.nick &&
isBrowser &&
localStorage.getItem("token") == null && (
<span className={styles["code"]}>
#{user.user.code}
</span>
)}
{p.owner == true && (
<span className={styles["admin"]}>Administrateur</span>
)}
{user.user.owner &&
p.nick != user.user.nick &&
p.code.length == 6 && (
<span className={styles["code"]}>#{p.code}</span>
)}
</p>
);
})}
{dataRoom.waiters.length != 0 && (
<>
<p className={parseClassName([styles.owner, styles.partCat])}>
En attente :
</p>
{dataRoom.waiters.map((p) => {
return (
<p>
{p.nick}
<AiOutlineCheck
className={styles["accept"]}
onClick={() => {
send({
data: {
type: "acceptParticipant",
code: p.code,
nick: p.nick,
status: p.status,
},
});
setDataRoom({
...dataRoom,
waiters: dataRoom.waiters.filter(
(w) => w.code != p.code
),
});
}}
/>
<AiOutlineClose
className={styles["refuse"]}
onClick={() => {
send({
data: { type: "refusedParticipant", code: p.code },
});
setDataRoom({
...dataRoom,
waiters: dataRoom.waiters.filter(
(w) => w.code != p.code
),
});
}}
/>
</p>
);
})}{" "}
</>
)}
</div>
</div>
)}
</Layout>
);
}