as sessions ficarão estáticas no frontend? Se Sim, não precisa ser um estado e sim pode ser um arquivo de data separado.
Algo como data.js
export const sessions = [
{
name: "Farmacologia",
files: [
{
name: "Aula sobre medicamentos",
type: "video",
},
{
name: "Aula sobre absorção de medicamentos",
type: "video",
},
{
name: "Aula sobre os tipos de medicamentos",
type: "video",
},
{
name: "Aula sobre os tipos de medicamentos e suas ações no organismo",
type: "video",
},
],
},
{
name: "Farmacognosia",
files: [
{
name: "Aula sobre plantas medicinais",
type: "video",
},
{
name: "Aula sobre os tipos de extrações",
type: "video",
},
],
},
];
Vejo também que a maioria dos buttons se repetem. Logo pode ter um componente no próprio arquivo para não repetir o mesmo código css.
const CustomButton = ({text}) => (
<button className="w-full flex-1 px-4 py-2 text-start">{text}</button>
)
Tenho a prática de não deixar funções diretas no onClick, geralmente eu separo.
function toggleSummary ({isOpen, index}) {
if(!isOpen) {
setOpenSessions([...openSessions, index]);
return;
}
setOpenSessions(openSessions.filter((item) => item !== index));
}
Não é muita coisa, mas já ajuda um pouco. O tailwind tem como "contra" a verbosidade, mas seu arquivo ainda está bem pequeno.
O resultado final seria.
import React, { useState } from "react";
import { FcDownload, FcPlus, FcSettings } from "react-icons/fc";
import { CiCircleChevUp, CiCircleChevDown } from "react-icons/ci";
import Link from "next/link";
import { sessions } from "./data";
function CustomButton({ text }) {
return (
<button className="w-full flex-1 px-4 py-2 text-start">{text}</button>
);
}
export default function DashBoard() {
const [openSessions, setOpenSessions] = useState([]);
function toggleSummary({ isOpen, index }) {
if (!isOpen) {
setOpenSessions([...openSessions, index]);
return;
}
setOpenSessions(openSessions.filter((item) => item !== index));
}
return (
<div className="mx-left container max-w-xl">
<div className="h-max w-full p-6 ">
<h1 className="flex items-end pb-3 text-2xl font-bold text-gray-700">
<span className="flex-1">Minhas sessões</span>
<span className="flex-3 text-end text-sm">2/10</span>
<FcPlus className="flex-2 ml-4 h-5 cursor-pointer hover:scale-110" />
</h1>
{sessions.map((session, index) => {
const isOpen = openSessions.includes(index);
return (
<details
key={index}
className="my-2 rounded-lg border-[0.0125rem] border-gray-400 border-opacity-30 px-4 py-4 text-sm shadow-md"
>
<summary
className="flex w-full flex-1 cursor-pointer select-none flex-row justify-between font-bold"
onClick={() => toggleSummary({ isOpen, index })}
>
<button>
{isOpen ? (
<CiCircleChevDown className="h-4 w-4" />
) : (
<CiCircleChevUp className="h-4 w-4" />
)}
</button>
<p className="flex-1 px-5 text-start">{session.name}</p>
<p className="flex flex-1 flex-row items-center justify-end gap-2">
{session.files.length}/10
</p>
<details className="flex-3 relative ml-4 flex flex-row items-center justify-end gap-2">
<summary className="list-none">
<FcSettings />
</summary>
<div className="absolute right-0 top-[105%] z-10 flex w-40 flex-col items-start divide-y-[0.0125rem] rounded-lg border-[0.0125rem] bg-white shadow-md ">
<CustomButton text="Editar" />
<CustomButton text="Backup" />
<CustomButton text="Compartilhar" />
<CustomButton text="Excluir" />
</div>
</details>
</summary>
<div className="mt-2 flex flex-col divide-y-[0.0125rem] divide-gray-300 divide-opacity-30 ">
{session.files.map((file, index) => {
return (
<div
key={index}
className="my-1 flex flex-row items-center justify-center gap-2"
>
<div className="flex-1">{file.name}</div>
<Link
href="/dashboard"
className="flex-3 flex items-center justify-end"
>
<FcDownload />
</Link>
</div>
);
})}
</div>
</details>
);
})}
</div>
</div>
);
}
Obs.: Se a identação estiver toda errada, perdoe-me. Não tinha onde arrumar no momento.