Skip to content

Commit

Permalink
[App] Add presences list (#186)
Browse files Browse the repository at this point in the history
* Starting the presences list

* visual aspect done

* presences_list call api

* Presences list done

* correct some details

* correct some erros

* request changes done

* request changes done

* request changes done

* request changes done

* some details
  • Loading branch information
Afonso-santos authored Jul 6, 2023
1 parent 2e3f1a2 commit 0173124
Show file tree
Hide file tree
Showing 4 changed files with 312 additions and 2 deletions.
1 change: 1 addition & 0 deletions apps/app/components/AppMenu/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ function AppMenu({ hidePrimaryMenu, collapsed }: any) {
<SubMenu icon={<UsergroupAddOutlined />} title="Sessões">
<Item key="/admin/lectures">Listar sessões</Item>
<Item key="/admin/lectures/new">Criar sessão</Item>
<Item key="/admin/lectures/presences">Presenças</Item>
</SubMenu>
</>
)}
Expand Down
3 changes: 1 addition & 2 deletions apps/app/components/LectureForm/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Link from "next/link";
import { useRouter } from "next/router";
import { Button, Col, Form, Row, Select, Space, Typography } from "antd";
import { CloseOutlined, SaveOutlined } from "@ant-design/icons";

import {
getNinjaEvents,
listEvents,
Expand Down Expand Up @@ -33,7 +34,6 @@ export default function LectureForm({ id }) {
setEvents(response.data);
});
}, []);

useEffect(() => {
if (id !== "new") {
listEvents().then((response) => {
Expand Down Expand Up @@ -137,7 +137,6 @@ export default function LectureForm({ id }) {
});
}
};

return (
<>
<Row justify="space-between">
Expand Down
309 changes: 309 additions & 0 deletions apps/app/pages/admin/lectures/presences/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,309 @@
import { useEffect, useState } from "react";
import { useRouter } from "next/router";
import { Button, Row, Select, Space, Table, Typography } from "antd";
import { CloseOutlined, EditOutlined, SaveOutlined } from "@ant-design/icons";

import {
getNinjaEvents,
listEvents,
listLectures,
listMentors,
} from "bokkenjs";
import * as api from "bokkenjs";
import { notifyError, notifyInfo } from "~/components/Notification";
import AppLayout from "~/layouts/AppLayout";
import { set } from "lodash-es";
const { Title } = Typography;

type Event = {
id: string;
title: string;
};

type Lecture = {
id: string;
event: Event;
attendance: string;
};

export default function Presences() {
const [editButtonVisible, setEditButtonVisible] = useState(true);
const [saveButtonVisible, setSaveButtonVisible] = useState(false);
const [cancelButtonVisible, setCancelButtonVisible] = useState(false);
const [data, setData] = useState<any[]>([]);
const [originalData, setOriginalData] = useState<any[]>([]);
const [events, setEvents] = useState<Event[]>([]);
const [selectedEvent, setSelectedEvent] = useState<string>("");
const [lectures, setLectures] = useState<Lecture[]>([]);
const [selectedLectures, setSelectedLectures] = useState<Lecture[]>([]);
const [locations, setLocations] = useState<any[]>([]);
const router = useRouter();
const onFinish = (values: any, lectureId: string) => {
api
.updateLecture(lectureId, values)
.then(() => {
notifyInfo("Os dados da sessão foram atualizados com sucesso", "");

// Update the corresponding lecture in lectures state with the new data
const updatedLectures = lectures.map((lecture) => {
if (lecture.id === lectureId) {
return {
...lecture,
attendance: values.attendance,
};
}
return lecture;
});

setLectures(updatedLectures);
})
.catch((error) => {
notifyError(
"Ocorreu um erro",
"Não foi possível atualizar os dados da sessão"
);
});
};

useEffect(() => {
api
.listEvents()
.then((response: any) => setEvents(response.data))
.catch((error) => {
notifyError(
"Ocorreu um erro",
"Não foi possível atualizar os dados da sessão"
);
});
}, []);

useEffect(() => {
api
.listLectures()
.then((response: any) => setLectures(response.data))

.catch((error) => {
notifyError(
"Ocorreu um erro",
"Não foi possível atualizar os dados da sessão"
);
});

selectedLectures.forEach((lecture) => {
if (lecture.attendance == null) {
lecture.attendance = "both_absent";
}
data.push({
presences: `${lecture.attendance}`,
key: lecture.id,
});
});
}, []);

useEffect(() => {
api
.getLocations()
.then((response: any) => setLocations(response.data))
.catch((error) => {
notifyError(
"Ocorreu um erro",
"Não foi possível atualizar os dados da sessão"
);
});
}, []);

useEffect(() => {
if (selectedEvent !== "") {
setSelectedLectures(
lectures.filter((lecture) => lecture.event.id === selectedEvent)
);
}
}, [selectedEvent, lectures]);

useEffect(() => {
generateData();
}, [selectedLectures]);

const generateData = () => {
const data: any[] = [];

selectedLectures.map((lecture: any) => {
if (lecture.attendance == null) {
lecture.attendance = "both_absent";
}
data.push({
ninja: `${lecture.ninja.first_name} ${lecture.ninja.last_name}`,
mentor: `${lecture.mentor.first_name} ${lecture.mentor.last_name}`,
presences: `${lecture.attendance}`,
key: lecture.id,
});
});

setData(data);
};

const handleEditButtonClick = () => {
setEditButtonVisible(false);
setSaveButtonVisible(true);
setCancelButtonVisible(true);
};

const handleSaveButtonClick = () => {
const hasChanges = JSON.stringify(data) !== JSON.stringify(originalData);

if (hasChanges) {
data.forEach((item) => {
const lectureId = item.key;
const values = { attendance: item.presences };

onFinish(values, lectureId);
});
}

setOriginalData([...data]);
setSaveButtonVisible(false);
setCancelButtonVisible(false);
setEditButtonVisible(true);
};

const handleCancelButtonClick = () => {
setSaveButtonVisible(false);
setCancelButtonVisible(false);
setEditButtonVisible(true);
};

const handleComboBoxChange = (key: string) => (value: string) => {
const updatedData = [...data];
const dataIndex = updatedData.findIndex((item) => item.key === key);
if (dataIndex > -1) {
updatedData[dataIndex].presences = value;
setData(updatedData);
}
};

const getPresencesLabel = (value: string) => {
switch (value) {
case "both_absent":
return "Nenhum";
case "ninja_absent":
return "Ninja Faltou";
case "mentor_absent":
return "Mentor Faltou";
case "both_present":
return "Presentes";
default:
return "";
}
};
const columns = [
{
title: "Ninja",
dataIndex: "ninja",
width: "33%",
},
{
title: "Mentor",
dataIndex: "mentor",
width: "33%",
},
{
title: "Presenças",
dataIndex: "presences",
width: "33%",
render: (_: any, record: any) => {
const label = getPresencesLabel(record.presences);
if (editButtonVisible) {
return <span>{label}</span>;
} else {
return (
<Select
value={record.presences}
onChange={handleComboBoxChange(record.key)}
style={{ width: 160 }}
>
<Select.Option value="both_absent">Nenhum</Select.Option>
<Select.Option value="ninja_absent">Ninja Faltou</Select.Option>
<Select.Option value="mentor_absent">Mentor Faltou</Select.Option>
<Select.Option value="both_present">Presentes</Select.Option>
</Select>
);
}
},
},
];

return (
<>
<AppLayout>
<Row justify="space-between">
<Title level={2}>Presenças</Title>
<Space>
{editButtonVisible && (
<Button
shape="circle"
type="primary"
size="large"
icon={<EditOutlined />}
onClick={handleEditButtonClick}
disabled={!editButtonVisible}
/>
)}
{saveButtonVisible && (
<Button
shape="circle"
type="primary"
size="large"
icon={<SaveOutlined />}
onClick={handleSaveButtonClick}
disabled={!saveButtonVisible}
/>
)}
{cancelButtonVisible && (
<Button
danger
shape="circle"
type="primary"
size="large"
icon={<CloseOutlined />}
onClick={handleCancelButtonClick}
disabled={!cancelButtonVisible}
/>
)}
</Space>
</Row>
<Row justify="space-around" gutter={[50, 50]}>
<Select
showSearch
defaultValue="Selecione um Evento"
style={{ width: 450 }}
onChange={setSelectedEvent}
filterOption={(input, option) =>
(option?.label ?? "").toLowerCase().includes(input.toLowerCase())
}
optionFilterProp="children"
options={events.map((event) => ({
label: event.title,
value: event.id,
}))}
value={selectedEvent == "" ? undefined : selectedEvent}
>
{events.map((event) => (
<Select.Option value={event.id}>{event.title}</Select.Option>
))}
</Select>
</Row>
<div style={{ marginBottom: 25 }} />
<Table
columns={columns}
dataSource={data}
pagination={{
pageSize: 40,
}}
scroll={{
y: 490,
}}
/>
</AppLayout>
</>
);
}
1 change: 1 addition & 0 deletions packages/bokkenjs/lib/lectures/lectures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export async function updateLecture(lecture_id: string, data: any) {
lecture: {
summary: data.summary,
notes: data.notes,
attendance: data.attendance,
},
},
{
Expand Down

0 comments on commit 0173124

Please sign in to comment.