mirror of
https://github.com/SrIzan10/featheroom.git
synced 2026-06-06 00:56:49 +00:00
feat: submit announcement posts
This commit is contained in:
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"editor.tabSize": 2,
|
||||
"editor.insertSpaces": true,
|
||||
"editor.detectIndentation": false
|
||||
}
|
||||
@@ -35,6 +35,13 @@ const DrawerLayout = () => {
|
||||
title: 'Courses',
|
||||
}}
|
||||
/>
|
||||
<Drawer.Screen
|
||||
name="courses/announcement/create/[id]"
|
||||
options={{
|
||||
drawerLabel: 'Create Announcement',
|
||||
title: 'Create Announcement',
|
||||
}}
|
||||
/>
|
||||
</Drawer>
|
||||
</GestureHandlerRootView>
|
||||
)
|
||||
|
||||
@@ -3,6 +3,7 @@ import { ScrollView } from 'react-native'
|
||||
import { Surface, Text, useTheme } from 'react-native-paper'
|
||||
|
||||
import { useCourse } from '@/lib/clients/classroom'
|
||||
import AddAnnouncement from '@/lib/ui/components/AddAnnouncement'
|
||||
import CourseBoard from '@/lib/ui/components/CourseBoard'
|
||||
import Loading from '@/lib/ui/components/Loading'
|
||||
|
||||
@@ -24,6 +25,7 @@ export default function Courses() {
|
||||
}}
|
||||
>
|
||||
<Surface className="flex-1">
|
||||
<AddAnnouncement />
|
||||
<Text>hi this is class with name {course?.name}</Text>
|
||||
<CourseBoard />
|
||||
</Surface>
|
||||
|
||||
37
app/(app)/drawer/courses/announcement/create/[id].tsx
Normal file
37
app/(app)/drawer/courses/announcement/create/[id].tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import { usePostAnnouncement } from '@/lib/clients/classroom'
|
||||
import { useLocalSearchParams, useRouter } from 'expo-router'
|
||||
import { useState } from 'react'
|
||||
import { ToastAndroid } from 'react-native'
|
||||
import { Button, Surface, TextInput } from 'react-native-paper'
|
||||
|
||||
export default function Page() {
|
||||
const { id } = useLocalSearchParams() as { id: string }
|
||||
const { mutate: postAnnouncement, isPending } = usePostAnnouncement(id)
|
||||
const [text, setText] = useState('')
|
||||
const router = useRouter()
|
||||
|
||||
return (
|
||||
<Surface className="flex-1">
|
||||
<TextInput
|
||||
label="Announcement"
|
||||
multiline
|
||||
numberOfLines={4}
|
||||
value={text}
|
||||
onChangeText={setText}
|
||||
/>
|
||||
<Button
|
||||
onPress={() => {
|
||||
postAnnouncement(text, {
|
||||
onSuccess: () => {
|
||||
ToastAndroid.show('Announcement posted', ToastAndroid.SHORT)
|
||||
router.push(`/drawer/courses/${id}`)
|
||||
},
|
||||
})
|
||||
}}
|
||||
loading={isPending}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</Surface>
|
||||
)
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable no-throw-literal */
|
||||
import { type classroom_v1 } from '@googleapis/classroom'
|
||||
import { GoogleSignin } from '@react-native-google-signin/google-signin'
|
||||
import { QueryClient, useQuery } from '@tanstack/react-query'
|
||||
import { QueryClient, useMutation, useQuery } from '@tanstack/react-query'
|
||||
|
||||
import { AnnouncementUserProfile } from '../types/Classroom'
|
||||
|
||||
@@ -162,6 +162,43 @@ export function useCourseWorkMaterials(courseId: string) {
|
||||
})
|
||||
}
|
||||
|
||||
async function postAnnouncement(courseId: string, text: string) {
|
||||
const token = await getAuthToken()
|
||||
const response = await fetch(
|
||||
`${BASE_URL}/v1/courses/${courseId}/announcements`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
text,
|
||||
state: 'PUBLISHED',
|
||||
}),
|
||||
},
|
||||
)
|
||||
|
||||
if (!response.ok) {
|
||||
throw { message: response.statusText, status: response.status } as ApiError
|
||||
}
|
||||
|
||||
return response.json()
|
||||
}
|
||||
|
||||
// Mutation hook
|
||||
export function usePostAnnouncement(courseId: string) {
|
||||
return useMutation({
|
||||
mutationFn: (text: string) => postAnnouncement(courseId, text),
|
||||
onSuccess: () => {
|
||||
// Invalidate announcements query to refetch
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: keys.courses.announcements(courseId),
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// various api utils from now on
|
||||
export function classroomDateTimeToISO(
|
||||
date: classroom_v1.Schema$Date,
|
||||
|
||||
23
lib/ui/components/AddAnnouncement.tsx
Normal file
23
lib/ui/components/AddAnnouncement.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { useLocalSearchParams, useRouter } from 'expo-router'
|
||||
import { View, Pressable } from 'react-native'
|
||||
import { Card, Avatar } from 'react-native-paper'
|
||||
|
||||
export default function AddAnnouncement() {
|
||||
const { id } = useLocalSearchParams() as { id: string }
|
||||
const router = useRouter()
|
||||
|
||||
return (
|
||||
<View className="m-2.5">
|
||||
<Pressable
|
||||
onPress={() => router.push(`/drawer/courses/announcement/create/${id}`)}
|
||||
>
|
||||
<Card className="border border-gray-200 dark:border-gray-700">
|
||||
<Card.Title
|
||||
title="Create a new announcement"
|
||||
left={(iP) => <Avatar.Icon {...iP} icon="plus" />}
|
||||
/>
|
||||
</Card>
|
||||
</Pressable>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@@ -15,9 +15,9 @@ export default function CourseBoard() {
|
||||
const { id } = useLocalSearchParams() as { id: string }
|
||||
const [organizedData, setOrganizedData] = useState<JSX.Element[]>([])
|
||||
|
||||
const { data: announcement, isLoading: annIsLoading } = useAnnouncements(id)
|
||||
const { data: courseWork, isLoading: cwIsLoading } = useCourseWork(id)
|
||||
const { data: courseWorkMaterial, isLoading: cwmIsLoading } =
|
||||
const { data: announcement, isFetching: annIsLoading } = useAnnouncements(id)
|
||||
const { data: courseWork, isFetching: cwIsLoading } = useCourseWork(id)
|
||||
const { data: courseWorkMaterial, isFetching: cwmIsLoading } =
|
||||
useCourseWorkMaterials(id)
|
||||
|
||||
useEffect(() => {
|
||||
@@ -74,25 +74,13 @@ export default function CourseBoard() {
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [announcement, courseWork, courseWorkMaterial])
|
||||
|
||||
if (annIsLoading || cwIsLoading || cwmIsLoading) {
|
||||
return <Loading />
|
||||
}
|
||||
// TODO: THIS DOESNT WORK RAHH SEND HELP
|
||||
// inside a useeffect to make the loading spinner appear when adding a new announcement for example
|
||||
useEffect(() => {
|
||||
if (annIsLoading || cwIsLoading || cwmIsLoading) {
|
||||
setOrganizedData([<Loading key="loading" />])
|
||||
}
|
||||
}, [annIsLoading, cwIsLoading, cwmIsLoading])
|
||||
|
||||
return (
|
||||
<Surface className="flex-1">
|
||||
{/* <Text>Announcements</Text>
|
||||
{announcement?.map((a) => <Announcement key={a.id} {...a} />)}
|
||||
<Text>Course Work</Text>
|
||||
{courseWork &&
|
||||
courseWork.map((cw) => (
|
||||
<CourseWorkCard key={cw.id} isCWM={false} data={cw} />
|
||||
))}
|
||||
<Text>Course Work Material</Text>
|
||||
{courseWorkMaterial &&
|
||||
courseWorkMaterial.map((cwm) => (
|
||||
<CourseWorkCard key={cwm.id} isCWM data={cwm} />
|
||||
))} */}
|
||||
{organizedData}
|
||||
</Surface>
|
||||
)
|
||||
return <Surface className="flex-1">{organizedData}</Surface>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user