diff --git a/README.md b/README.md index 86710cd1..0550132b 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,24 @@ This project is designed and developed by a team of UC Berkeley students through Learn more about [Girls Write Now](https://girlswritenow.org/) and [Cal Blueprint](https://calblueprint.org/). +## App Preview + +### Story Search/Filtering + +https://github.com/calblueprint/girls-write-now/assets/34043950/6277c625-fa8a-495d-b2eb-ba70807cfd87 + +### Story Recommendation + +![Simulator Screen Recording - iPhone 15 - 2024-04-25 at 14 09 19](https://github.com/calblueprint/girls-write-now/assets/34043950/6a92dbf7-be0e-4210-8a66-35fddd578fee) + +### Saving/Favoriting Stories + +![saved stories](https://github.com/calblueprint/girls-write-now/assets/34043950/e40b5a50-d53c-497a-8b70-433def6dde67) + +### Reacting To Stories + +![reactions](https://github.com/calblueprint/girls-write-now/assets/34043950/32d5c54e-5a4e-4517-8475-ea38b2e4cf69) + --- ## Getting Started diff --git a/src/app/(tabs)/author/index.tsx b/src/app/(tabs)/author/index.tsx index 1feee80a..ba6ea4b6 100644 --- a/src/app/(tabs)/author/index.tsx +++ b/src/app/(tabs)/author/index.tsx @@ -16,6 +16,11 @@ import { import { Author, StoryPreview } from '../../../queries/types'; import globalStyles from '../../../styles/globalStyles'; +/* + * This screen displays information about an author. + * When redirecting to this page, you must supply the parameter `{ author: string }`, which is the string of a number representing the id of the author. + * This id is parsed to get the integer id, used to fetch the author's data. + */ function AuthorScreen() { const [authorInfo, setAuthorInfo] = useState(); const [authorStoryPreview, setAuthorStoryPreview] = diff --git a/src/app/(tabs)/genre/index.tsx b/src/app/(tabs)/genre/index.tsx index 924cbabf..601d304c 100644 --- a/src/app/(tabs)/genre/index.tsx +++ b/src/app/(tabs)/genre/index.tsx @@ -21,6 +21,12 @@ import { StoryPreview, GenreStories } from '../../../queries/types'; import globalStyles from '../../../styles/globalStyles'; import { FilterDropdown } from '../../../components/FilterDropdown/FilterDropdown'; +/* + * This screen allows the user to filter stories based on the tone and topic for a specific genre. + * When redirecting to this page, you must supply the parameters `{ genreId: string; genreType: GenreType; genreName: string }` + * genreType is a enum, which can either be a Parent or Child. Parent genre's are genre's with children. Ex. Filter is a parent of Children's Fiction. + * useEffects are triggered when a dropdown tone/topic is selected, and updates the screen with the correct filtered stories. + */ function GenreScreen() { const [genreStoryData, setGenreStoryData] = useState(); const [genreStoryIds, setGenreStoryIds] = useState([]); diff --git a/src/app/(tabs)/home/index.tsx b/src/app/(tabs)/home/index.tsx index 62a11c92..c4bb4081 100644 --- a/src/app/(tabs)/home/index.tsx +++ b/src/app/(tabs)/home/index.tsx @@ -22,6 +22,11 @@ import { StoryCard, StoryPreview } from '../../../queries/types'; import globalStyles from '../../../styles/globalStyles'; import { useSession } from '../../../utils/AuthContext'; +/* + * This screen displays the home screen of the app. + * It displays the featured stories, recommended stories, and new stories. Note: recommended stories are only displayed if there are recent stories (that the user read, from the search screen) + * The featured stories header and description can be edited via the admin dashboard. Links in the description are automatically converted to hyperlinks + */ function HomeScreen() { const { user } = useSession(); const [username, setUsername] = useState(''); diff --git a/src/app/(tabs)/library/index.tsx b/src/app/(tabs)/library/index.tsx index 3d50558a..95228306 100644 --- a/src/app/(tabs)/library/index.tsx +++ b/src/app/(tabs)/library/index.tsx @@ -15,6 +15,10 @@ import { import { FlatList } from 'react-native-gesture-handler'; import { Channel, usePubSub } from '../../../utils/PubSubContext'; +/* + * This screen displays the user's saved and favorited stories. + * The screen recieves updates from PreviewCard and ContentCard from the PubSubContext via the usePubSub hook. If a story is favorited, the channel will be updated, and a useEffect is triggered. The screen is updated after 4 seconds of the update. This is to give the user time to resave a story on the library page if they accidently unsave it. + */ function LibraryScreen() { const { user } = useSession(); const [favoritesSelected, setFavoritesSelected] = useState(true); diff --git a/src/app/(tabs)/search/index.tsx b/src/app/(tabs)/search/index.tsx index 8020b954..a8070f07 100644 --- a/src/app/(tabs)/search/index.tsx +++ b/src/app/(tabs)/search/index.tsx @@ -68,6 +68,13 @@ const setRecentStory = async (recentStories: StoryPreview[]) => { } }; +/* + * This screen handles all the story searching. It initially loads all stories, and functions to filter the stories. + * When the user first lands on the page, or if the "cancel" button on the search bar is clicked, all the genres tiles are shown. Using the genre dropdown is equivilent to clicking on a genre tile in this state. + * When a genre tile is selected, the user is redirected to the genre screen. + * When the user starts using the search bar, the stories are filtered based on the search. The user can further filter down the search based on the genre/topic/tone dropdowns. All filters must match for a story to be shown. Only genres/topics/tones that return results based on ONLY the text search are shown in the dropdown. Selected genre/topic/tone dropdowns will not affect the options in the dropdowns, only changing the search text. Selecting an option changes the color of the dropdown. + * Stories are preloaded with reaction to reduce the amount of network requests sent to supabase. + */ function SearchScreen() { const [allStories, setAllStories] = useState< StoryPreviewWithPreloadedReactions[] diff --git a/src/app/(tabs)/settings/index.tsx b/src/app/(tabs)/settings/index.tsx index 5bbc0009..acafa68e 100644 --- a/src/app/(tabs)/settings/index.tsx +++ b/src/app/(tabs)/settings/index.tsx @@ -7,6 +7,7 @@ import { Platform, Pressable, Appearance, + TouchableOpacity, } from 'react-native'; import { Icon } from 'react-native-elements'; import { ScrollView } from 'react-native-gesture-handler'; @@ -22,7 +23,13 @@ import colors from '../../../styles/colors'; import globalStyles from '../../../styles/globalStyles'; import { useSession } from '../../../utils/AuthContext'; import supabase from '../../../utils/supabase'; +import { deleteUser } from '../../../queries/auth'; +/* + * This screen shows the user's profile information, and allows the user to edit profile information. + * If the user starts updating their information, the "log out" button will become a "save edits" button. + * The birthday can only be set once per account. Once it is set, it cannot be changed again. + */ function SettingsScreen() { const { session, signOut } = useSession(); const [loading, setLoading] = useState(true); @@ -109,6 +116,37 @@ function SettingsScreen() { if (!session) resetAndPushToRouter('/auth/login'); }, [session]); + const showAlert = () => + Alert.alert( + 'Are you sure you want to delete your account?', + '', + [ + { + text: 'OK', + onPress: onDelete, + style: 'destructive', + }, + { + text: 'Cancel', + onPress: () => {}, + style: 'cancel', + }, + ], + { + cancelable: true, + onDismiss: () => {}, + }, + ); + + const onDelete = async () => { + const uuid = session?.user.id; + + if (uuid) { + deleteUser(uuid); + signOut(); + } + }; + const updateProfile = async () => { try { setLoading(true); @@ -201,7 +239,39 @@ function SettingsScreen() { Settings - Account + + Account + + + ( + + + + Delete account + + + + ) + + + diff --git a/src/app/(tabs)/story/index.tsx b/src/app/(tabs)/story/index.tsx index 60cc41a8..b13fb46d 100644 --- a/src/app/(tabs)/story/index.tsx +++ b/src/app/(tabs)/story/index.tsx @@ -22,6 +22,12 @@ import globalStyles, { fonts } from '../../../styles/globalStyles'; import BackButton from '../../../components/BackButton/BackButton'; import OptionBar from '../../../components/OptionBar/OptionBar'; +/* + * This screen displays the story based on the params `{ storyId: string }` + * It loads the story from supabase based on the storyId. + * It uses the `react-native-render-html` to render the stories HTML from wordpress. + * The user can also add the story to favorites/reading, and react to the story from this screen. + */ function StoryScreen() { const [isLoading, setLoading] = useState(true); const scrollRef = React.useRef(null); @@ -84,9 +90,9 @@ function StoryScreen() { horizontal showsHorizontalScrollIndicator={false} data={[ - ...story.genre_medium, - ...story.tone, - ...story.topic, + ...(story.genre_medium ?? []), + ...(story.tone ?? []), + ...(story.topic ?? []), ].filter(tag => tag != null)} keyExtractor={(_, index) => index.toString()} // Add a key extractor for performance optimization renderItem={({ item, index }) => ( diff --git a/src/app/auth/forgotPassword/index.tsx b/src/app/auth/forgotPassword/index.tsx index 34eace9d..8026e988 100644 --- a/src/app/auth/forgotPassword/index.tsx +++ b/src/app/auth/forgotPassword/index.tsx @@ -15,6 +15,11 @@ import colors from '../../../styles/colors'; import globalStyles from '../../../styles/globalStyles'; import { useSession } from '../../../utils/AuthContext'; +/* + * Handles the user's request to reset their password. + * Redirects to the verify page if the username/email is valid + * Uses `useDebounce` to check if the username/email is valid only when the user stops typing + */ function ForgotPasswordScreen() { const { resetPassword } = useSession(); const [email, setEmail] = useState(''); diff --git a/src/app/auth/login/index.tsx b/src/app/auth/login/index.tsx index 9dd4e71a..7340f334 100644 --- a/src/app/auth/login/index.tsx +++ b/src/app/auth/login/index.tsx @@ -13,6 +13,9 @@ import colors from '../../../styles/colors'; import globalStyles from '../../../styles/globalStyles'; import { useSession } from '../../../utils/AuthContext'; +/* + * The screen to handle a user's login request + */ function LoginScreen() { const sessionHandler = useSession(); const [emailOrUsername, setEmailOrUsername] = useState(''); diff --git a/src/app/auth/onboarding/index.tsx b/src/app/auth/onboarding/index.tsx index 8667173f..a85696ab 100644 --- a/src/app/auth/onboarding/index.tsx +++ b/src/app/auth/onboarding/index.tsx @@ -21,6 +21,10 @@ import { useSession } from '../../../utils/AuthContext'; import supabase from '../../../utils/supabase'; import { SafeAreaView } from 'react-native-safe-area-context'; +/* + * The screen that lets the user enter information about themselves that will be associated to their account + * The birthday can only be changed once, so a warning is shown if the user sets a birthday. If a birthday is not set, it can be set on the setting screen + */ function OnboardingScreen() { const { session, user } = useSession(); const [loading, setLoading] = useState(true); diff --git a/src/app/auth/resetPassword/index.tsx b/src/app/auth/resetPassword/index.tsx index 19a193bd..badcac2d 100644 --- a/src/app/auth/resetPassword/index.tsx +++ b/src/app/auth/resetPassword/index.tsx @@ -12,6 +12,10 @@ import { useSession } from '../../../utils/AuthContext'; import PasswordComplexityText from '../../../components/PasswordComplexityText/PasswordComplexityText'; import { isPasswordSameAsBefore } from '../../../queries/profiles'; +/* + * The screen where the user enters their new password, after verifying their email. + * The user can only reset their password once all requirements are met. + */ function ResetPasswordScreen() { const { session, updateUser, signOut } = useSession(); const [password, setPassword] = useState(''); diff --git a/src/app/auth/signup/index.tsx b/src/app/auth/signup/index.tsx index 17608b48..a8cabe37 100644 --- a/src/app/auth/signup/index.tsx +++ b/src/app/auth/signup/index.tsx @@ -16,6 +16,10 @@ import globalStyles from '../../../styles/globalStyles'; import { useSession } from '../../../utils/AuthContext'; import supabase from '../../../utils/supabase'; +/* + * The screen where users can create a new account + * The user can only sign up once all the requirement are met + */ function SignUpScreen() { const { signUp } = useSession(); diff --git a/src/app/auth/verify/index.tsx b/src/app/auth/verify/index.tsx index a14cf766..cdb5969d 100644 --- a/src/app/auth/verify/index.tsx +++ b/src/app/auth/verify/index.tsx @@ -11,6 +11,13 @@ import colors from '../../../styles/colors'; import globalStyles from '../../../styles/globalStyles'; import { useSession } from '../../../utils/AuthContext'; +/* + * The OTP verification screen. This is where the user can enter the 6-digit code from their email. + * When redirecting to this screen, you need to pass in the parameters `{ finalRedirect: string, userEmail: string }` + * The final redirect is the path to redirect to if the verification is successful. The userEmail is for display purposes. + * The user can resend the code, and a `Toast` will appear if the resend was successful. + * If the code is invalid, a red error message under the OTP text input will be displayed + */ function VerificationScreen() { const { user, verifyOtp, resendVerification } = useSession(); const [errorMessage, setErrorMessage] = useState(''); diff --git a/src/app/index.tsx b/src/app/index.tsx index 2f132cba..176d24c6 100644 --- a/src/app/index.tsx +++ b/src/app/index.tsx @@ -3,6 +3,7 @@ import { useEffect, useState } from 'react'; import SplashScreen from '../components/SplashScreen/SplashScreen'; import { useSession } from '../utils/AuthContext'; + import { useFonts, Manrope_700Bold, @@ -10,6 +11,11 @@ import { Manrope_600SemiBold, } from '@expo-google-fonts/manrope'; +/** + * The entry point to the app. While the app is loading, it shows the SplashScreen. + * It loads the fonts used in the app, and, if the user is signed it, it redirects the user to home. + * Otherwise, it redirects the user to the login page + */ function StartPage() { const { session, isLoading } = useSession(); const [delay, setDelay] = useState(true); diff --git a/src/components/AccountDataDisplay/AccountDataDisplay.tsx b/src/components/AccountDataDisplay/AccountDataDisplay.tsx index 4faccfff..f0648bc6 100644 --- a/src/components/AccountDataDisplay/AccountDataDisplay.tsx +++ b/src/components/AccountDataDisplay/AccountDataDisplay.tsx @@ -8,6 +8,10 @@ type AccountDataDisplayProps = { value: string | React.ReactNode; }; +/* + * Used on the setting page. Displays information about the user's account. + * For example label="First Name" value="John" + */ function AccountDataDisplay({ label, value }: AccountDataDisplayProps) { return ( diff --git a/src/components/AuthorCard/AuthorCard.tsx b/src/components/AuthorCard/AuthorCard.tsx index edec4725..fd878823 100644 --- a/src/components/AuthorCard/AuthorCard.tsx +++ b/src/components/AuthorCard/AuthorCard.tsx @@ -9,6 +9,7 @@ type AuthorCardProps = { bio: string; artist_statement: string; }; + function AuthorCard({ name, pronouns, diff --git a/src/components/AuthorImage/AuthorImage.tsx b/src/components/AuthorImage/AuthorImage.tsx index 92b1dc88..a4cf0475 100644 --- a/src/components/AuthorImage/AuthorImage.tsx +++ b/src/components/AuthorImage/AuthorImage.tsx @@ -12,6 +12,10 @@ type AuthorImageProps = { // pressFunction: (event: GestureResponderEvent) => void; }; +/* + * Displays the author's profile picture in a circle with the text "Authors:" before it, followed by the author's name + * Used exclusively on the story screen + */ function AuthorImage({ author_name, author_id, diff --git a/src/components/BackButton/BackButton.tsx b/src/components/BackButton/BackButton.tsx index 75fc5ec0..34fc6f0c 100644 --- a/src/components/BackButton/BackButton.tsx +++ b/src/components/BackButton/BackButton.tsx @@ -12,6 +12,10 @@ type BackButtonProps = { pressFunction: (event: GestureResponderEvent) => void; }; +/* + * Universal pre styled back button + * pressFunction will usually be `router.back()` + */ function BackButton({ pressFunction }: BackButtonProps) { return ( diff --git a/src/components/ContentCard/ContentCard.tsx b/src/components/ContentCard/ContentCard.tsx index 181d0b9a..360e6561 100644 --- a/src/components/ContentCard/ContentCard.tsx +++ b/src/components/ContentCard/ContentCard.tsx @@ -24,6 +24,11 @@ type ContentCardProps = { pressFunction: (event: GestureResponderEvent) => void; }; +/* + * Displays a story for use in horizontal ScrollView + * Includes options to save the story, and see the reactions to a story + * Uses the PubSubContext to update its icons based on user interaction + */ function ContentCard({ id, title, diff --git a/src/components/FavoriteStoryButton/FavoriteStoryButton.tsx b/src/components/FavoriteStoryButton/FavoriteStoryButton.tsx index ff8113cc..e27993dd 100644 --- a/src/components/FavoriteStoryButton/FavoriteStoryButton.tsx +++ b/src/components/FavoriteStoryButton/FavoriteStoryButton.tsx @@ -14,6 +14,11 @@ type FavoriteStoryButtonProps = { storyId: number; }; +/* + * A button that handles the state of the favorite story icon. + * Automatically updates using PubSubContext based on user interaction. + * Changes the icon displayed based on if the story is already favorited + */ export default function FavoriteStoryButton({ storyId, }: FavoriteStoryButtonProps) { diff --git a/src/components/FilterDropdown/FilterDropdown.tsx b/src/components/FilterDropdown/FilterDropdown.tsx index 2ba8c7e6..2806681d 100644 --- a/src/components/FilterDropdown/FilterDropdown.tsx +++ b/src/components/FilterDropdown/FilterDropdown.tsx @@ -14,6 +14,11 @@ type FilterDropdownProps = { setter: React.Dispatch>; }; +/* + * Dropdown used for filtering stories + * Will change the border color to `selectedBorderColor` if an option is selected + * Primarily used on the search and genre screens + */ function FilterDropdown({ placeholder, value, diff --git a/src/components/GenreCard/GenreCard.tsx b/src/components/GenreCard/GenreCard.tsx index 016fb9af..a13f44a8 100644 --- a/src/components/GenreCard/GenreCard.tsx +++ b/src/components/GenreCard/GenreCard.tsx @@ -15,6 +15,9 @@ type GenreCardProps = { pressFunction: (event: GestureResponderEvent) => void; }; +/* + * Card displayed on the search screen, representing a single clickable genre tile. + */ function GenreCard({ subgenres, pressFunction, cardColor }: GenreCardProps) { return ( diff --git a/src/components/HorizontalLine/HorizontalLine.tsx b/src/components/HorizontalLine/HorizontalLine.tsx index b29a1f73..d756852b 100644 --- a/src/components/HorizontalLine/HorizontalLine.tsx +++ b/src/components/HorizontalLine/HorizontalLine.tsx @@ -2,6 +2,10 @@ import { View } from 'react-native'; import styles from './styles'; +/* + * A line used to divide information + * Primarily used on the author page + */ function HorizontalLine() { return ; } diff --git a/src/components/LibraryHeader/LibraryHeader.tsx b/src/components/LibraryHeader/LibraryHeader.tsx index e9e4a191..9f3f3651 100644 --- a/src/components/LibraryHeader/LibraryHeader.tsx +++ b/src/components/LibraryHeader/LibraryHeader.tsx @@ -8,6 +8,10 @@ import globalStyles from '../../styles/globalStyles'; import colors from '../../styles/colors'; import { useSession } from '../../utils/AuthContext'; +/* + * The header of the library screen + * Displays the settings button, and the user's username + */ export default function LibraryHeader() { const { user } = useSession(); diff --git a/src/components/OptionBar/OptionBar.tsx b/src/components/OptionBar/OptionBar.tsx index 783dae66..03eff821 100644 --- a/src/components/OptionBar/OptionBar.tsx +++ b/src/components/OptionBar/OptionBar.tsx @@ -12,6 +12,9 @@ type OptionBarProps = { story: Story; }; +/* + * Contains the reaction picker, saved story button, favorite story button, and share button to be displayed on the story screen. + */ function OptionBar({ storyId, story }: OptionBarProps) { const onShare = async () => { try { diff --git a/src/components/PasswordComplexityText/PasswordComplexityText.tsx b/src/components/PasswordComplexityText/PasswordComplexityText.tsx index 23268e4e..f9cbca72 100644 --- a/src/components/PasswordComplexityText/PasswordComplexityText.tsx +++ b/src/components/PasswordComplexityText/PasswordComplexityText.tsx @@ -10,6 +10,9 @@ type PasswordComplexityTextProps = { condition: boolean; }; +/* + * Used to represent a password requirement + */ export default function PasswordComplexityText({ condition, message, diff --git a/src/components/PreviewCard/PreviewCard.tsx b/src/components/PreviewCard/PreviewCard.tsx index 53164d4e..16be8ac1 100644 --- a/src/components/PreviewCard/PreviewCard.tsx +++ b/src/components/PreviewCard/PreviewCard.tsx @@ -31,6 +31,11 @@ type PreviewCardProps = { pressFunction: (event: GestureResponderEvent) => void; }; +/* + * Displays the preview of a story. + * Shows author, title, story image, and excerpt. + * Allows the user to see the current reaction count, and add the story to their saved list + */ function PreviewCard({ title, image, diff --git a/src/components/ReactionDisplay/ReactionDisplay.tsx b/src/components/ReactionDisplay/ReactionDisplay.tsx index 22f490b0..34ee652d 100644 --- a/src/components/ReactionDisplay/ReactionDisplay.tsx +++ b/src/components/ReactionDisplay/ReactionDisplay.tsx @@ -18,6 +18,10 @@ const reactionColors: Record = { muscle: '#eddcf7', }; +/* + * Displays the reactions for a story. + * Automatically updates based on user interaction using the PubSubContext. + */ function ReactionDisplay({ reactions, storyId }: ReactionDisplayProps) { const { channels, getPubSubValue } = usePubSub(); const [reactionCount, setReactionCount] = useState(0); diff --git a/src/components/ReactionPicker/ReactionPicker.tsx b/src/components/ReactionPicker/ReactionPicker.tsx index 71f1455d..302680c8 100644 --- a/src/components/ReactionPicker/ReactionPicker.tsx +++ b/src/components/ReactionPicker/ReactionPicker.tsx @@ -16,6 +16,10 @@ type ReactionPickerProps = { storyId: number; }; +/* + * Allows the user to select a reaction to a story. + * Published the update using the PubSubContext to update ReactionDisplays + */ const ReactionPicker = ({ storyId }: ReactionPickerProps) => { const { user } = useSession(); const { publish } = usePubSub(); diff --git a/src/components/RecentSearchCard/RecentSearchCard.tsx b/src/components/RecentSearchCard/RecentSearchCard.tsx index e142baee..e1e371c5 100644 --- a/src/components/RecentSearchCard/RecentSearchCard.tsx +++ b/src/components/RecentSearchCard/RecentSearchCard.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import { GestureResponderEvent, Pressable, View, Text } from 'react-native'; import Icon from 'react-native-vector-icons/AntDesign'; @@ -11,6 +10,10 @@ type RecentSearchCardProps = { pressFunction: (event: GestureResponderEvent) => void; }; +/* + * Represents a search made by the user in the past + * Will only show up if the user clicks "enter" or "done" on their keyboard when searching + */ function RecentSearchCard({ value, numResults, diff --git a/src/components/SaveStoryButton/SaveStoryButton.tsx b/src/components/SaveStoryButton/SaveStoryButton.tsx index 3e22084e..66239664 100644 --- a/src/components/SaveStoryButton/SaveStoryButton.tsx +++ b/src/components/SaveStoryButton/SaveStoryButton.tsx @@ -15,6 +15,11 @@ type SaveStoryButtonProps = { defaultState?: boolean | null; }; +/* + * Keeps state of a story's saved story button. + * Changes the icon of the component based on whether the story is saved or not. + * Updates live based on the PubSubContext + */ export default function SaveStoryButton({ storyId, defaultState = null, diff --git a/src/components/SplashScreen/SplashScreen.tsx b/src/components/SplashScreen/SplashScreen.tsx index d9585ce9..8368a1e5 100644 --- a/src/components/SplashScreen/SplashScreen.tsx +++ b/src/components/SplashScreen/SplashScreen.tsx @@ -4,6 +4,10 @@ import { Image } from 'expo-image'; import styles from './styles'; +/* + * Used as the loading screen for the app + * The source of the image can be changed to any image to be displayed when the app intially loads + */ export default function SplashScreen() { return ( diff --git a/src/components/StyledButton/StyledButton.tsx b/src/components/StyledButton/StyledButton.tsx index 18960a9c..c91c2431 100644 --- a/src/components/StyledButton/StyledButton.tsx +++ b/src/components/StyledButton/StyledButton.tsx @@ -9,6 +9,10 @@ type StyledButtonProps = { onPress: () => void; }; +/* + * A pre styled button + * Used throughout the auth flow, and on the setting screen + */ function StyledButton({ disabled, onPress, text }: StyledButtonProps) { return (