Skip to content

Commit 89ce6bc

Browse files
committed
huge update on visuals
to make handleDeleteAnnouncement and more later
1 parent 468f4b4 commit 89ce6bc

File tree

4 files changed

+133
-33
lines changed

4 files changed

+133
-33
lines changed

index.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
<meta charset="UTF-8" />
66
<link rel="icon" href="/quarkFavicon.png" />
77
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
8+
<link rel="preconnect" href="https://fonts.googleapis.com">
9+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10+
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500&display=swap" rel="stylesheet">
811
<title>Quark</title>
912
</head>
1013

src/components/HomeAnnouncements.tsx

Lines changed: 71 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
11
import React, { useState, useEffect } from 'react';
2-
import { Card, List, Avatar, Form, Input, Button, Modal, DatePicker } from 'antd';
2+
import { Card, Avatar, Form, Input, Button, Modal, DatePicker, Pagination } from 'antd';
33
import { PlusOutlined } from '@ant-design/icons';
44
import { useSelector, useDispatch } from 'react-redux';
5-
6-
import { FormatDate } from '../shared/functions';
7-
8-
import styles from "../styles/Pages/UserSearch.module.css";
5+
import dayjs from 'dayjs';
6+
import type { RangePickerProps } from 'antd/es/date-picker';
7+
import customParseFormat from 'dayjs/plugin/customParseFormat';
8+
import styles from "../styles/Components/Announcements.module.css";
99
import { addAnnouncement, setAnnouncements } from '../app/slices/announcement.slice';
1010
import { useAddAnnouncementEndpointMutation, useGetAnnouncementsEndpointMutation } from '../app/slices/auth.api.slice';
1111

1212
interface Announcement {
13+
1314
title: string;
1415
content: string;
1516
email: string
1617
time: string;
1718
}
1819

1920
export interface AnnouncementResponse {
21+
id: number;
2022
title: string
2123
content: string,
2224
time: string,
@@ -28,17 +30,21 @@ export interface AnnouncementResponse {
2830
const Announcements: React.FC = () => {
2931
const [form] = Form.useForm();
3032
const [showModal, setShowModal] = useState(false);
31-
33+
const [currentPage, setCurrentPage] = useState(1);
34+
const itemsPerPage = 8;
35+
dayjs.extend(customParseFormat);
3236
const dispatch = useDispatch();
3337

3438
const [AddAnnouncementEndpoint, { isError }] = useAddAnnouncementEndpointMutation(); // Error alert/message if adding fails
3539
const [GetAnnouncementEndpoint, { isLoading }] = useGetAnnouncementsEndpointMutation(); //Skeleton if the data is loading
3640

41+
const handlePageChange = (page: number) => {
42+
setCurrentPage(page);
43+
};
3744
useEffect(() => {
3845
const fetchAnnouncements = async () => {
3946
try {
4047
const response = await GetAnnouncementEndpoint(undefined).unwrap();
41-
console.log(response);
4248
dispatch(setAnnouncements(response));
4349
} catch (error) {
4450
console.error(error)
@@ -50,31 +56,42 @@ const Announcements: React.FC = () => {
5056
const { announcements } = useSelector((state: any) => state.announcement);
5157
const { userState } = useSelector((state: any) => state.auth);
5258
const { user } = userState;
59+
const indexOfLastAnnouncement = currentPage * itemsPerPage;
60+
const indexOfFirstAnnouncement = indexOfLastAnnouncement - itemsPerPage;
61+
const currentAnnouncements = announcements.slice(indexOfFirstAnnouncement, indexOfLastAnnouncement);
5362

5463
const handleAddAnnouncement = () => {
5564
form.validateFields().then(async (values) => {
56-
values["date"] = FormatDate(values.date); // Change the default DatePicker format
65+
values["date1"] = dayjs(values.date[0]).format('YYYY-MM-DD HH:mm');
66+
values["date2"] = dayjs(values.date[1]).format('YYYY-MM-DD HH:mm');
67+
const date = values.date1 + " - " + values.date2;
68+
5769
const newAnnouncement: Announcement = {
5870
title: values.title,
5971
content: values.content,
60-
time: values.date.toString(),
72+
time: date,
6173
email: user.email
6274
};
6375

6476
const response = await AddAnnouncementEndpoint(newAnnouncement).unwrap();
65-
console.log(response);
6677
dispatch(addAnnouncement(response));
6778
form.resetFields();
6879
setShowModal(false);
6980
});
7081
};
82+
const handleDeleteAnnouncement = async (id: number) => {
7183

84+
}
85+
const disabledDate: RangePickerProps['disabledDate'] = (current) => {
86+
// Can not select days before today and today
87+
return current && current < dayjs().endOf('day');
88+
};
7289
return (
73-
<Card className={styles.user_search_container} style={{ background: '#FFFFFF', padding: '24px', minHeight: '360px' }}>
90+
<Card className={styles.announcement_first_container} style={{ background: '#FFFFFF', padding: '24px', minHeight: '360px' }}>
7491
<Button type="primary" shape="circle" icon={<PlusOutlined />} onClick={() => setShowModal(true)} style={{ position: 'fixed', bottom: '24px', right: '24px' }} />
7592
<Modal
7693
title="Add Announcement"
77-
visible={showModal}
94+
open={showModal}
7895
onCancel={() => setShowModal(false)}
7996
onOk={handleAddAnnouncement}
8097
>
@@ -86,32 +103,54 @@ const Announcements: React.FC = () => {
86103
<Input.TextArea placeholder="Content" />
87104
</Form.Item>
88105
<Form.Item name="date" rules={[{ required: true, message: 'Please select the date' }]}>
89-
<DatePicker />
106+
<DatePicker.RangePicker
107+
disabledDate={disabledDate}
108+
showTime={{
109+
hideDisabledOptions: true,
110+
defaultValue: [dayjs('00:00:00', 'HH:mm:ss'), dayjs('11:59:59', 'HH:mm:ss')],
111+
}}
112+
format="YYYY-MM-DD HH:mm"
113+
/>
90114
</Form.Item>
91115
</Form>
92116
</Modal>
93-
<List
94-
dataSource={announcements}
95-
renderItem={(item: AnnouncementResponse) => (
96-
<>
97-
<div style={{ fontFamily: 'monospace' }}>{item.userFirstName} {item.userLastName}</div>
98-
<List.Item>
99-
<List.Item.Meta
100-
avatar={<Avatar src={item.userPictureUrl} />}
101-
title={item.title}
102-
description={<div style={{ overflow: 'hidden', wordWrap: 'break-word' }}>{item.content}</div>}
103-
/>
117+
<div className={styles.announcement_grid}>
118+
<div className={styles.announcement_card_container}>
119+
{currentAnnouncements.map((item: AnnouncementResponse) => (
120+
<Card
121+
key={item.id}
122+
title={<div style={{ fontFamily: "Montserrat", fontSize: '22px' }}>{item.title}</div>}
123+
extra={
124+
<div style={{ display: 'flex', alignItems: 'center' }}>
125+
<div style={{ fontFamily: 'monospace' }}>{item.userFirstName} {item.userLastName}</div>
126+
<Avatar style={{ height: '3dvh', width: '3dvh', margin: '7px 0 7px 17px' }} src={item.userPictureUrl} />
127+
</div>
128+
}
129+
className={styles.announcement_card}
130+
>
131+
<div style={{ fontFamily: "Montserrat", textAlign: 'left', height: '100%', marginBottom: '15px' }}>
132+
<div style={{ wordWrap: 'break-word' }}>{item.content}</div>
133+
<div style={{ position: 'absolute', bottom: 10, textAlign: 'left', color: new Date(item.time) < new Date() ? 'red' : 'green', fontWeight: 'bold' }}>{item.time}</div>
134+
<div>
135+
<Button style={{ position: 'absolute', marginTop: '8px', bottom: 10, right: 10 }} type="default" onClick={() => handleDeleteAnnouncement(item.id)}>Delete</Button>
136+
</div>
137+
</div>
138+
139+
104140

105-
{new Date(item.time) < new Date() ?
106-
<div style={{ color: 'red', fontWeight: "bold" }}>{item.time}</div>
107-
:
108-
<div style={{ color: 'green', fontWeight: "bold" }}>{item.time}</div>}
109-
</List.Item>
110-
</>
111-
)}
141+
</Card>
142+
))}
143+
</div>
144+
</div>
145+
<Pagination
146+
style={{ marginTop: '16px', textAlign: 'center' }}
147+
total={announcements.length}
148+
pageSize={itemsPerPage}
149+
current={currentPage}
150+
onChange={handlePageChange}
112151
/>
113152
</Card>
114153
);
115154
};
116155

117-
export default Announcements;
156+
export default Announcements;

src/components/UserProfile.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const UserProfile = () => {
2727
</Tooltip>
2828
<Modal
2929
title="User Profile"
30-
visible={visible}
30+
open={visible}
3131
onCancel={handleCloseModal}
3232
footer={null}
3333
>
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
.announcement_first_container {
2+
overflow: unset;
3+
4+
}
5+
6+
.announcement_grid {
7+
display: grid;
8+
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
9+
gap: 16px;
10+
}
11+
12+
.announcement_card_container {
13+
display: flex;
14+
flex-wrap: wrap;
15+
justify-content: center;
16+
overflow: auto;
17+
height: 75vh;
18+
}
19+
20+
.announcement_card {
21+
width: 100%;
22+
margin: 0 15px 16px 0;
23+
24+
}
25+
26+
.announcement_card .ant-card {
27+
height: 100%;
28+
}
29+
30+
.announcement_card .ant-card-body {
31+
padding: 16px;
32+
}
33+
34+
.announcement_card .ant-card-extra {
35+
font-family: monospace;
36+
}
37+
38+
.announcement_card .ant-card-cover {
39+
display: flex;
40+
justify-content: center;
41+
align-items: center;
42+
height: 10vh;
43+
width: 10vh;
44+
}
45+
46+
47+
48+
49+
50+
/* Hide the scrollbar */
51+
.announcement_card_container::-webkit-scrollbar {
52+
width: 0.5em;
53+
background-color: transparent;
54+
}
55+
56+
.announcement_card_container::-webkit-scrollbar-thumb {
57+
background-color: transparent;
58+
}

0 commit comments

Comments
 (0)