1
1
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' ;
3
3
import { PlusOutlined } from '@ant-design/icons' ;
4
4
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" ;
9
9
import { addAnnouncement , setAnnouncements } from '../app/slices/announcement.slice' ;
10
10
import { useAddAnnouncementEndpointMutation , useGetAnnouncementsEndpointMutation } from '../app/slices/auth.api.slice' ;
11
11
12
12
interface Announcement {
13
+
13
14
title : string ;
14
15
content : string ;
15
16
email : string
16
17
time : string ;
17
18
}
18
19
19
20
export interface AnnouncementResponse {
21
+ id : number ;
20
22
title : string
21
23
content : string ,
22
24
time : string ,
@@ -28,17 +30,21 @@ export interface AnnouncementResponse {
28
30
const Announcements : React . FC = ( ) => {
29
31
const [ form ] = Form . useForm ( ) ;
30
32
const [ showModal , setShowModal ] = useState ( false ) ;
31
-
33
+ const [ currentPage , setCurrentPage ] = useState ( 1 ) ;
34
+ const itemsPerPage = 8 ;
35
+ dayjs . extend ( customParseFormat ) ;
32
36
const dispatch = useDispatch ( ) ;
33
37
34
38
const [ AddAnnouncementEndpoint , { isError } ] = useAddAnnouncementEndpointMutation ( ) ; // Error alert/message if adding fails
35
39
const [ GetAnnouncementEndpoint , { isLoading } ] = useGetAnnouncementsEndpointMutation ( ) ; //Skeleton if the data is loading
36
40
41
+ const handlePageChange = ( page : number ) => {
42
+ setCurrentPage ( page ) ;
43
+ } ;
37
44
useEffect ( ( ) => {
38
45
const fetchAnnouncements = async ( ) => {
39
46
try {
40
47
const response = await GetAnnouncementEndpoint ( undefined ) . unwrap ( ) ;
41
- console . log ( response ) ;
42
48
dispatch ( setAnnouncements ( response ) ) ;
43
49
} catch ( error ) {
44
50
console . error ( error )
@@ -50,31 +56,42 @@ const Announcements: React.FC = () => {
50
56
const { announcements } = useSelector ( ( state : any ) => state . announcement ) ;
51
57
const { userState } = useSelector ( ( state : any ) => state . auth ) ;
52
58
const { user } = userState ;
59
+ const indexOfLastAnnouncement = currentPage * itemsPerPage ;
60
+ const indexOfFirstAnnouncement = indexOfLastAnnouncement - itemsPerPage ;
61
+ const currentAnnouncements = announcements . slice ( indexOfFirstAnnouncement , indexOfLastAnnouncement ) ;
53
62
54
63
const handleAddAnnouncement = ( ) => {
55
64
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
+
57
69
const newAnnouncement : Announcement = {
58
70
title : values . title ,
59
71
content : values . content ,
60
- time : values . date . toString ( ) ,
72
+ time : date ,
61
73
email : user . email
62
74
} ;
63
75
64
76
const response = await AddAnnouncementEndpoint ( newAnnouncement ) . unwrap ( ) ;
65
- console . log ( response ) ;
66
77
dispatch ( addAnnouncement ( response ) ) ;
67
78
form . resetFields ( ) ;
68
79
setShowModal ( false ) ;
69
80
} ) ;
70
81
} ;
82
+ const handleDeleteAnnouncement = async ( id : number ) => {
71
83
84
+ }
85
+ const disabledDate : RangePickerProps [ 'disabledDate' ] = ( current ) => {
86
+ // Can not select days before today and today
87
+ return current && current < dayjs ( ) . endOf ( 'day' ) ;
88
+ } ;
72
89
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' } } >
74
91
< Button type = "primary" shape = "circle" icon = { < PlusOutlined /> } onClick = { ( ) => setShowModal ( true ) } style = { { position : 'fixed' , bottom : '24px' , right : '24px' } } />
75
92
< Modal
76
93
title = "Add Announcement"
77
- visible = { showModal }
94
+ open = { showModal }
78
95
onCancel = { ( ) => setShowModal ( false ) }
79
96
onOk = { handleAddAnnouncement }
80
97
>
@@ -86,32 +103,54 @@ const Announcements: React.FC = () => {
86
103
< Input . TextArea placeholder = "Content" />
87
104
</ Form . Item >
88
105
< 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
+ />
90
114
</ Form . Item >
91
115
</ Form >
92
116
</ 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
+
104
140
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 }
112
151
/>
113
152
</ Card >
114
153
) ;
115
154
} ;
116
155
117
- export default Announcements ;
156
+ export default Announcements ;
0 commit comments