diff --git a/api/models/postModel.js b/api/models/postModel.js index a73642d..4e4c553 100644 --- a/api/models/postModel.js +++ b/api/models/postModel.js @@ -20,8 +20,8 @@ const postSchema = new mongoose.Schema({ }, status: { type: String, - enum: ['created', 'denied', 'approved'], - default: 'created' + enum: ['open', 'denied', 'approved'], + default: 'open' } }) diff --git a/app/(tabs)/posts/details.tsx b/app/(tabs)/posts/details.tsx index 2515d18..4277ac3 100644 --- a/app/(tabs)/posts/details.tsx +++ b/app/(tabs)/posts/details.tsx @@ -1,123 +1,125 @@ - -import { initialState, Post, StatusEnum } from '@/app/models/postModel'; -import { useFocusEffect, useLocalSearchParams } from 'expo-router'; -import React, { useState } from 'react'; -import { Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; - - - +import { initialState, Post, StatusEnum } from '@/app/models/postModel' +import Ionicons from '@expo/vector-icons/Ionicons' +import { router, useFocusEffect, useLocalSearchParams } from 'expo-router' +import React, { useState } from 'react' +import { Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native' export default function DetailsScreen() { const isProfileView = window.location.href.includes('/profile') - const [post, setPost] = useState(initialState); - const {id} = useLocalSearchParams() - console.log(id); + const [post, setPost] = useState(initialState) + const { id } = useLocalSearchParams() + console.log(id) useFocusEffect( - React.useCallback(() => { - // Do something when the screen is focused - // TODO: add endpoint to get only non approved or denied status posts - fetch(`http://localhost:3000/api/v1/posts/${id}`) - .then((res) => res.json()) - .then((json) => { - console.log(json) - setPost(json.data) - }) - return () => { - // Do something when the screen is unfocused - // Useful for cleanup functions - } - }, []) - ) + React.useCallback(() => { + // Do something when the screen is focused + // TODO: add endpoint to get only non approved or denied status posts + fetch(`http://localhost:3000/api/v1/posts/${id}`) + .then((res) => res.json()) + .then((json) => { + console.log(json) + setPost(json.data) + }) + return () => { + // Do something when the screen is unfocused + // Useful for cleanup functions + } + }, []) + ) async function approvePost(postID: string) { - console.log('Approving post ' + postID) - await fetch(`http://localhost:3000/api/v1/posts/${postID}`, { - method: 'PATCH', - headers: { - Accept: 'application/json, text/plain, */*', - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - status: 'approved' - }) - }).then(() => { - // Nav back to posts page + console.log('Approving post ' + postID) + await fetch(`http://localhost:3000/api/v1/posts/${postID}`, { + method: 'PATCH', + headers: { + Accept: 'application/json, text/plain, */*', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + status: 'approved' }) - } - - async function denyPost(postID: string) { - console.log('Denying post ' + postID) - await fetch(`http://localhost:3000/api/v1/posts/${postID}`, { - method: 'PATCH', - headers: { - Accept: 'application/json, text/plain, */*', - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - status: 'denied' - }) - }).then(() => { - // Nav back to posts page + }).then(() => { + router.back() + }) + } + + async function denyPost(postID: string) { + console.log('Denying post ' + postID) + await fetch(`http://localhost:3000/api/v1/posts/${postID}`, { + method: 'PATCH', + headers: { + Accept: 'application/json, text/plain, */*', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + status: 'denied' }) - } + }).then(() => { + router.back() + }) + } return ( - - {post._id} - - - - {post.notes} - {isProfileView ? ( - - {post.status === StatusEnum.Created && ( - Created - )} - {post.status === StatusEnum.Pending && ( - Pending - )} - {post.status === StatusEnum.Denied && Denied} - {post.status === StatusEnum.Approved && ( - Approved - )} - - ) : null} - {!isProfileView ? ( - - denyPost(post._id)}> - - Deny - - - approvePost(post._id)}> - - Approve - - - - ) : null} + + + router.back()}> + + + + {post._id} + + + + {post.notes} + {isProfileView ? ( + + {post.status === StatusEnum.Created && ( + Created + )} + {post.status === StatusEnum.Pending && ( + Pending + )} + {post.status === StatusEnum.Denied && Denied} + {post.status === StatusEnum.Approved && ( + Approved + )} + ) : null} + {!isProfileView ? ( + + denyPost(post._id)}> + + Deny + + + approvePost(post._id)}> + + Approve + + + + ) : null} + ) } @@ -126,11 +128,14 @@ const styles = StyleSheet.create({ color: '#fff', justifyContent: 'center' }, - constainer: { + container: { backgroundColor: '#373d44ff', padding: 10, flex: 1 }, + header: { + height: 30 + }, statusTag: { paddingVertical: 3, paddingHorizontal: 10, borderRadius: 6 }, created: { backgroundColor: '#0d6efd', color: '#ffffff' }, pending: { backgroundColor: '#ffc107', color: '#000000' }, diff --git a/app/(tabs)/posts/index.tsx b/app/(tabs)/posts/index.tsx index 6b1f448..f29045b 100644 --- a/app/(tabs)/posts/index.tsx +++ b/app/(tabs)/posts/index.tsx @@ -1,7 +1,79 @@ -import { Redirect } from 'expo-router' +import { useFocusEffect } from 'expo-router' +import React, { useState } from 'react' +import { StyleSheet, Text, View } from 'react-native' +import { CompactPostComponent } from '../../components/CompactPostComponent' +import { Post } from '../../models/postModel' + +// TODO: +// Overhaul posts display to use compact posts - once you click in you should see +// all the details provided by the user as well as buttons to approve or deny. +// Eventually I will also add the user to this page so the reviewer can click into +// the posters account and see their history. I would like to make a point system as well. +// When the buttons are pressed the user will be prompted to enter information +// on WHY the post was approved or denied. + +export default function OverviewScreen() { + const [posts, setPosts] = useState() + + useFocusEffect( + React.useCallback(() => { + // Do something when the screen is focused + // TODO: add endpoint to get only non approved or denied status posts + fetchData() + return () => { + // Do something when the screen is unfocused + // Useful for cleanup functions + } + }, []) + ) + + async function fetchData() { + fetch('http://localhost:3000/api/v1/posts/status/created') + .then((res) => res.json()) + .then((json) => { + setPosts(json.data) + }) + } -export default function Page() { return ( - + + Posts + {posts?.length ? ( + posts.map((el) => ) + ) : ( + + All caught up! + + )} + ) } + +const styles = StyleSheet.create({ + wrapper: { + flex: 1, + backgroundColor: '#25292e', + padding: 16, + alignItems: 'center', + overflow: 'scroll' + }, + title: { + color: '#fff', + justifyContent: 'center' + }, + posts: { + marginTop: 10, + backgroundColor: '#363c43ff', + padding: 10, + width: '90%', + borderRadius: 5 + }, + caughtUpContainer: { + flex: 1, + alignContent: 'center', + justifyContent: 'center' + }, + caughtUpText: { + color: '#787b80ff' + } +}) diff --git a/app/(tabs)/posts/overview.tsx b/app/(tabs)/posts/overview.tsx deleted file mode 100644 index f29045b..0000000 --- a/app/(tabs)/posts/overview.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { useFocusEffect } from 'expo-router' -import React, { useState } from 'react' -import { StyleSheet, Text, View } from 'react-native' -import { CompactPostComponent } from '../../components/CompactPostComponent' -import { Post } from '../../models/postModel' - -// TODO: -// Overhaul posts display to use compact posts - once you click in you should see -// all the details provided by the user as well as buttons to approve or deny. -// Eventually I will also add the user to this page so the reviewer can click into -// the posters account and see their history. I would like to make a point system as well. -// When the buttons are pressed the user will be prompted to enter information -// on WHY the post was approved or denied. - -export default function OverviewScreen() { - const [posts, setPosts] = useState() - - useFocusEffect( - React.useCallback(() => { - // Do something when the screen is focused - // TODO: add endpoint to get only non approved or denied status posts - fetchData() - return () => { - // Do something when the screen is unfocused - // Useful for cleanup functions - } - }, []) - ) - - async function fetchData() { - fetch('http://localhost:3000/api/v1/posts/status/created') - .then((res) => res.json()) - .then((json) => { - setPosts(json.data) - }) - } - - return ( - - Posts - {posts?.length ? ( - posts.map((el) => ) - ) : ( - - All caught up! - - )} - - ) -} - -const styles = StyleSheet.create({ - wrapper: { - flex: 1, - backgroundColor: '#25292e', - padding: 16, - alignItems: 'center', - overflow: 'scroll' - }, - title: { - color: '#fff', - justifyContent: 'center' - }, - posts: { - marginTop: 10, - backgroundColor: '#363c43ff', - padding: 10, - width: '90%', - borderRadius: 5 - }, - caughtUpContainer: { - flex: 1, - alignContent: 'center', - justifyContent: 'center' - }, - caughtUpText: { - color: '#787b80ff' - } -}) diff --git a/app/(tabs)/profile/_layout.tsx b/app/(tabs)/profile/_layout.tsx new file mode 100644 index 0000000..a360ed9 --- /dev/null +++ b/app/(tabs)/profile/_layout.tsx @@ -0,0 +1,5 @@ +import { Stack } from 'expo-router' + +export default function ProfilLayout() { + return +} diff --git a/app/(tabs)/profile.tsx b/app/(tabs)/profile/index.tsx similarity index 94% rename from app/(tabs)/profile.tsx rename to app/(tabs)/profile/index.tsx index 324d697..3c6caf4 100644 --- a/app/(tabs)/profile.tsx +++ b/app/(tabs)/profile/index.tsx @@ -2,9 +2,9 @@ import { useUser } from '@clerk/clerk-react' import { useFocusEffect } from 'expo-router' import React, { useState } from 'react' import { Image, StyleSheet, Text, View } from 'react-native' -import { CompactPostComponent } from '../components/CompactPostComponent' -import { SignOutButton } from '../components/SignOutButton' -import { Post } from '../models/postModel' +import { CompactPostComponent } from '../../components/CompactPostComponent' +import { SignOutButton } from '../../components/SignOutButton' +import { Post } from '../../models/postModel' export default function PostsScreen() { const { user } = useUser() diff --git a/app/components/CompactPostComponent.tsx b/app/components/CompactPostComponent.tsx index 6e50aa4..5d1f896 100644 --- a/app/components/CompactPostComponent.tsx +++ b/app/components/CompactPostComponent.tsx @@ -5,22 +5,23 @@ import { StyleSheet, Text, TouchableOpacity, View } from 'react-native' import { Post, StatusEnum } from '../models/postModel' export const CompactPostComponent: React.FC = (post) => { - return ( - { - router.push({ - pathname: '/posts/details', - params: { - id: post._id, - } - }) - }}> + { + router.push({ + pathname: '/posts/details', + params: { + id: post._id + } + }) + }} + > - {post.notes} + {post.notes} - {post.status === StatusEnum.Created && ( - Created - )} + {post.status === StatusEnum.Created && Open} {post.status === StatusEnum.Pending && ( Pending )} @@ -31,7 +32,7 @@ export const CompactPostComponent: React.FC = (post) => { - {post.address} + {post.address} {new Date(post.date).toLocaleDateString()} @@ -64,14 +65,18 @@ const styles = StyleSheet.create({ marginBottom: 16 }, footer: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }, - date: { + title: { paddingVertical: 3, borderRadius: 6, color: '#ffffff', - fontSize: 16 + fontSize: 16, + paddingRight: 10 + }, + address: { + paddingRight: 15 }, statusTag: { paddingVertical: 3, paddingHorizontal: 10, borderRadius: 6, fontSize: 16 }, - created: { backgroundColor: '#0d6efd', color: '#ffffff' }, + open: { backgroundColor: '#0d6efd', color: '#ffffff' }, pending: { backgroundColor: '#ffc107', color: '#000000' }, denied: { backgroundColor: '#dc3545', color: '#ffffff' }, approved: { backgroundColor: '#198754', color: '#ffffff' }