Skip to content

Commit d0866b1

Browse files
committed
expanded view full functionality
1 parent 35aa7ef commit d0866b1

File tree

7 files changed

+172
-42
lines changed

7 files changed

+172
-42
lines changed

backend/resolvers/announcementResolver.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { PrismaClient, Announcement, Priority } from "@prisma/client";
1+
import { PrismaClient, Announcement, Priority, UserAnnouncement } from "@prisma/client";
22
import { getNow } from "../utils/formatDateTime";
33

44
const prisma = new PrismaClient();
@@ -83,21 +83,19 @@ const announcementResolver = {
8383
{
8484
participant_id,
8585
}: { participant_id: number; }
86-
): Promise<Announcement[]> => {
86+
): Promise<UserAnnouncement[]> => {
8787
try {
88-
return await prisma.announcement.findMany({
88+
return await prisma.userAnnouncement.findMany({
8989
orderBy: {
90-
creation_date: "desc",
90+
announcement: {
91+
creation_date: "desc"
92+
},
9193
},
9294
where: {
93-
user_announcements: {
94-
some: {
95-
participant_id,
96-
},
97-
},
95+
participant_id,
9896
},
9997
include: {
100-
user_announcements: true,
98+
announcement: true,
10199
},
102100
});
103101
} catch (err) {

backend/types/resolvers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const resolvers = gql`
1616
getAllAnnouncements: [Announcement]
1717
getAnnouncementsInDateRange(start: String!, end: String!): [Announcement]
1818
getAnnouncementsByParticipants(participant_ids: [Int!]!): [Announcement]
19-
getAnnouncementsByParticipantId(participant_id: Int!): [Announcement]
19+
getAnnouncementsByParticipantId(participant_id: Int!): [UserAnnouncement]
2020
getAssignedTasks(participant_id: Int!): GetAssignedTaskResponse!
2121
getTasksByType(type: [TaskType!]!): [Task]
2222
getCustomBadges: [Badge]

frontend/src/gql/mutations.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,22 @@ export const SET_MARILLAC_BUCKS_GOAL = gql`
308308
}
309309
`;
310310

311+
export const UPDATE_PIN_READ_ANNOUNCEMENTS = gql`
312+
mutation UpdatePinReadAnnouncement(
313+
$announcement_id: Int!
314+
$participant_id: Int!
315+
$pinned: Boolean
316+
$read: Boolean
317+
) {
318+
updatePinReadAnnouncement(
319+
announcement_id: $announcement_id
320+
participant_id: $participant_id
321+
pinned: $pinned
322+
read: $read
323+
)
324+
}
325+
`
326+
311327
export const UPDATE_MARILLAC_BUCKS_GOAL = gql`
312328
mutation updateMarillacBucksGoal($participant_id: Int!, $new_goal_value: Int!) {
313329
updateMarillacBucksGoal(participant_id: $participant_id, new_goal_value: $new_goal_value)

frontend/src/gql/queries.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,13 @@ export const GET_ANNOUNCEMENTS_BY_PARTICIPANT_ID = gql`
164164
participant_id: $participant_id
165165
) {
166166
announcement_id
167-
priority
168-
creation_date
169-
message
170-
user_announcements {
171-
participant_id
167+
participant_id
168+
read
169+
pinned
170+
announcement {
171+
priority
172+
creation_date
173+
message
172174
}
173175
}
174176
}

frontend/src/participant/pages/announcements/Main.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import { Priority } from "../../../types/AnnouncementTypes";
1111
import GreenButton from "../../common/GreenButton";
1212
import AnnouncementsExpandedView from "./components/AnnouncementsExpandedView";
1313

14-
// Keep labels stable
1514
const FILTER_LABELS = ["ALL", "UNREAD", "PINNED", "IMPORTANT"] as const;
1615

1716
export default function ParticipantsAnnouncementsPage() {
@@ -91,13 +90,15 @@ export default function ParticipantsAnnouncementsPage() {
9190
Most Recent
9291
</Text>
9392
{data.map((a: any, i: number) => {
94-
const uaid = a.announcement_id;
93+
const {
94+
announcement_id: uaid,
95+
read,
96+
pinned,
97+
announcement: { message, priority, creation_date: date },
98+
} = a;
99+
95100
const allRooms = false;
96-
const message = isAll ? a.message : a.announcement.message
97-
const importance = Object.values(Priority).indexOf(isAll ? a.priority : a.announcement.priority)
98-
const read = isAll ? a.user_announcements.read : a.read
99-
const pinned = isAll ? a.user_announcements.pinned : a.pinned
100-
const date = isAll ? a.creation_date : a.announcement.creation_date
101+
const importance = Object.values(Priority).indexOf(priority);
101102

102103
return (
103104
<Flex key={i} cursor="pointer" onClick={() => {

frontend/src/participant/pages/announcements/components/AnnouncementsExpandedView.tsx

Lines changed: 129 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import { Divider, Flex, Text } from "@chakra-ui/react";
2-
import React from "react";
2+
import React, { useContext, useEffect, useState } from "react";
3+
import { useMutation } from "@apollo/client";
34
import { displayDate2 } from "../../../../utils/formatDateTime";
45
import Icon from "../../../common/Icon";
56
import important from "../../../icons/announcements/important.svg"
67
import orangepin from "../../../icons/announcements/orangepin.svg"
78
import greenpin from "../../../icons/announcements/greenpin.svg"
89
import unread from "../../../icons/announcements/unread.svg"
910
import GreenButton from "../../../common/GreenButton";
11+
import { UPDATE_PIN_READ_ANNOUNCEMENTS } from "../../../../gql/mutations";
12+
import { ParticipantContext } from "../../../common/ParticipantContext";
1013

1114
type AnnouncementInfo = {
1215
uaid: number;
@@ -23,40 +26,151 @@ type AnnouncementsExpandedViewProps = {
2326
}
2427

2528
export default function AnnouncementsExpandedView({ announcement }: AnnouncementsExpandedViewProps) {
29+
const participant = useContext(ParticipantContext);
30+
const participantId = participant?.id;
31+
32+
const [pinned, setPinned] = useState<boolean>(announcement.pinned);
33+
const [prevPinned, setPrevPinned] = useState<boolean>(announcement.pinned);
34+
const [updating, setUpdating] = useState(false);
35+
const [error, setError] = useState("");
36+
37+
const [updatePinRead] = useMutation(UPDATE_PIN_READ_ANNOUNCEMENTS);
38+
39+
useEffect(() => {
40+
let active = true;
41+
const cleanup = () => {
42+
active = false;
43+
};
44+
45+
if (!participantId || pinned === prevPinned) {
46+
return cleanup;
47+
}
48+
49+
setUpdating(true);
50+
(async () => {
51+
try {
52+
await updatePinRead({
53+
variables: {
54+
announcement_id: announcement.uaid,
55+
participant_id: participantId,
56+
pinned,
57+
},
58+
});
59+
60+
if (active) {
61+
setPrevPinned(pinned);
62+
}
63+
} catch (err) {
64+
if (active) setPinned(prevPinned);
65+
} finally {
66+
if (active) setUpdating(false);
67+
}
68+
})();
69+
70+
return cleanup;
71+
}, [pinned]);
72+
73+
useEffect(() => {
74+
let active = true;
75+
const cleanup = () => {
76+
active = false;
77+
};
78+
79+
if (!participantId || announcement.read) {
80+
return cleanup;
81+
}
82+
83+
setUpdating(true);
84+
(async () => {
85+
try {
86+
await updatePinRead({
87+
variables: {
88+
announcement_id: announcement.uaid,
89+
participant_id: participantId,
90+
read: true,
91+
},
92+
});
93+
} catch (err) {
94+
if (active) setError("Unable to mark as read");
95+
} finally {
96+
if (active) setUpdating(false);
97+
}
98+
})();
99+
100+
return cleanup;
101+
}, []);
102+
103+
const handleMarkAsUnread = async () => {
104+
if (!participantId || updating) return;
105+
try {
106+
setUpdating(true);
107+
await updatePinRead({
108+
variables: {
109+
announcement_id: announcement.uaid,
110+
participant_id: participantId,
111+
read: false,
112+
},
113+
});
114+
} catch (err) {
115+
setError("Unable to mark as unread")
116+
} finally {
117+
setUpdating(false);
118+
window.location.reload()
119+
}
120+
};
121+
26122
return (
27123
<>
28124
<Flex alignItems="center" justify="space-between">
29125
<Text textStyle="mobile.h2">{announcement.allRooms ? "Admin To All Rooms" : "Admin To Your Room"}</Text>
30-
<Text textStyle="mobile.b0" color="text.light.secondary">{displayDate2(new Date(announcement.date))}</Text>
126+
<Text
127+
onClick={() => window.location.reload()}
128+
textStyle="mobile.b1"
129+
textDecoration="underline"
130+
cursor="pointer"
131+
_hover={{
132+
textDecoration: "none"
133+
}}
134+
>
135+
Back to Announcements
136+
</Text>
31137
</Flex>
32138

33-
<Flex gap="12px">
34-
<Flex gap="8px">
35-
<Icon icon={important} width="3px" height="3px" />
36-
<Text textStyle="mobile.s1" color="#D34C5C">Priority</Text>
37-
</Flex>
38-
<Flex gap="8px">
39-
<Icon icon={orangepin} width="8px" height="8px" />
40-
<Text textStyle="mobile.s1" color="#E67D4F">Pinned</Text>
139+
<Flex alignItems="center" justify="space-between">
140+
<Flex gap="12px">
141+
{announcement.importance !== 0 && (
142+
<Flex gap="8px">
143+
<Icon icon={important} width="3px" height="3px" />
144+
<Text textStyle="mobile.b1" color="#D34C5C">Priority</Text>
145+
</Flex>
146+
)}
147+
148+
{pinned && (
149+
<Flex gap="8px">
150+
<Icon icon={orangepin} width="8px" height="8px" />
151+
<Text textStyle="mobile.b1" color="#E67D4F">Pinned</Text>
152+
</Flex>
153+
)}
41154
</Flex>
155+
<Text textStyle="mobile.b1" color="text.light.secondary">{displayDate2(new Date(announcement.date))}</Text>
42156
</Flex>
43157

44158
<Divider borderColor="neutral.300" />
45159

46-
<Text>{announcement.message}</Text>
160+
<Text textStyle="mobile.b1">{announcement.message}</Text>
47161

48162
<Flex marginTop="8px" gap="12px">
49163
<GreenButton
50164
text="Mark as Unread"
51165
is_active={false}
52-
action={() => {}}
166+
action={() => handleMarkAsUnread()}
53167
icon={<Icon icon={unread} width="14px" height="14px" />}
54168
/>
55169
<GreenButton
56-
text="Pin"
170+
text={pinned ? "Unpin" : "Pin"}
57171
is_active={false}
58-
action={() => {}}
59-
icon={<Icon icon={greenpin} width="8px" height="8px" />}
172+
action={() => setPinned(!pinned)}
173+
icon={<Icon icon={pinned ? orangepin : greenpin} width="8px" height="8px" />}
60174
/>
61175
</Flex>
62176
</>

frontend/src/participant/pages/home/components/AnnouncementWidget.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { useQuery } from "@apollo/client";
44
import { useNavigate } from "react-router-dom";
55
import WidgetContainer from "../../../common/WidgetContainer";
66
import { GET_ANNOUNCEMENTS_BY_PARTICIPANT_ID } from "../../../../gql/queries";
7-
import { AnnouncementDisplayInfo } from "../../../../types/AnnouncementTypes";
87
import { displayDate2, getNow, getRecentDate } from "../../../../utils/formatDateTime";
98
import { ParticipantContext } from "../../../common/ParticipantContext";
109
import * as ROUTES from "../../../../constants/routes";
@@ -43,7 +42,7 @@ export default function AnnouncementWidget() {
4342
</Flex>
4443

4544
{announcementData.getAnnouncementsByParticipantId.map(
46-
(announcement: AnnouncementDisplayInfo) => (
45+
(announcement: any) => (
4746
<Flex
4847
width="100%"
4948
flexDir="column"
@@ -52,10 +51,10 @@ export default function AnnouncementWidget() {
5251
>
5352
<Divider borderColor="neutral.300" />
5453
<Text paddingTop="4px" textStyle="mobile.b1">
55-
{announcement.message}
54+
{announcement.announcement.message}
5655
</Text>
5756
<Text textStyle="mobile.b1" color="text.light.secondary">
58-
{displayDate2(new Date(announcement.creation_date))}
57+
{displayDate2(new Date(announcement.announcement.creation_date))}
5958
</Text>
6059
</Flex>
6160
)

0 commit comments

Comments
 (0)