import type { EntryKind } from "convex-feedback"; import { Stack, useLocalSearchParams, useRouter } from "expo-router"; import { Fragment, useEffect, useRef, useState } from "react"; import type { SearchBarCommands } from "react-native-screens"; import { useFeedbackBody } from "../../shared/context/FeedbackBodyProvider.js"; import { useFeedbackUi } from "../../shared/context/FeedbackProvider.js"; import { allowAuthenticatedAction, createEntryLabel, entryStatusChoices, } from "../../shared/helpers.js"; import { EntryDetail } from "../shared/ui/EntryDetail.js"; import { FeedbackScreenList } from "../shared/ui/FeedbackScreenList.js"; import { CreateEntryForm } from "../shared/ui/NewEntry.js"; import { FeedbackBoard } from "../shared/ui/primitives.js"; import { EditEntryStackScreen } from "./EditEntryScreen.js"; import { useRoutedFeedback } from "./RoutedFeedbackContext.js"; import { useRoutedFeedbackModal } from "./RoutedFeedbackModalContext.js"; import { feedbackBoardRouteHref, feedbackEditRouteHref, feedbackEntryRouteHref, feedbackRouteHref, } from "./routes.js"; export function FeedbackBoardScreen() { const { query, isSearching, setQuery, setIsSearching, enabledKinds, statusFilter, setStatusFilter, isAuthenticated, onUnauthenticated, } = useFeedbackBody(); const { messages, theme } = useFeedbackUi(); const { routes, colors, androidToolbarIcons, bottomToolbarWrapper: BottomToolbarWrapper, } = useRoutedFeedback(); const router = useRouter(); const searchRef = useRef(null); const BottomToolbarWrapperComponent = BottomToolbarWrapper ?? Fragment; useEffect(() => { const searching = query.trim().length > 0; if (searching !== isSearching) setIsSearching(searching); }, [query, isSearching, setIsSearching]); const openEntry = (entryId: string) => { if ((query || isSearching) && searchRef.current) { searchRef.current.blur(); } router.push(feedbackEntryRouteHref(routes.entry, { entryId }), { relativeToDirectory: true, }); }; return ( <> router.push(feedbackRouteHref(routes.create), { relativeToDirectory: true, }) } /> { if (!allowAuthenticatedAction(isAuthenticated, onUnauthenticated)) { return; } router.push(feedbackRouteHref(routes.create), { relativeToDirectory: true, }); }} tintColor={theme.colors.primary} > {createEntryLabel(enabledKinds, messages)} setQuery( (event as unknown as { nativeEvent: { text: string } }).nativeEvent .text, ) } onFocus={() => setIsSearching(true)} onBlur={() => setIsSearching(query.trim().length > 0)} obscureBackground={false} allowToolbarIntegration hideNavigationBar={false} textColor={theme.colors.text} /> {entryStatusChoices(messages).map(({ value, label }) => ( setStatusFilter(value)} > {label} ))} ); } export function FeedbackEntryScreen() { const params = useLocalSearchParams<{ entryId?: string | string[]; }>(); const entryId = Array.isArray(params.entryId) ? params.entryId[0] : params.entryId; if (!entryId) { throw new Error( 'FeedbackEntryScreen requires an "entryId" dynamic route parameter.', ); } return ; } export function FeedbackEditScreen() { const params = useLocalSearchParams<{ entryId?: string | string[]; }>(); const entryId = Array.isArray(params.entryId) ? params.entryId[0] : params.entryId; if (!entryId) { throw new Error( 'FeedbackEditScreen requires an "entryId" dynamic route parameter.', ); } return ; } function FeedbackEditRouteContent({ entryId }: { entryId: string }) { const { hooks } = useFeedbackBody(); const { androidToolbarIcons, colors } = useRoutedFeedback(); const router = useRouter(); const entry = hooks.useEntry(entryId); return ( router.back()} colors={colors} androidToolbarIcons={androidToolbarIcons} /> ); } function FeedbackEntryRouteContent({ entryId }: { entryId: string }) { const { hooks } = useFeedbackBody(); const { messages, theme } = useFeedbackUi(); const { routes, colors, androidToolbarIcons } = useRoutedFeedback(); const router = useRouter(); const entry = hooks.useEntry(entryId); const goBack = () => { if (router.canGoBack()) { router.back(); } else { router.replace(feedbackBoardRouteHref(routes.entry, routes.board), { relativeToDirectory: true, }); } }; return ( <> {messages.entry.back} {entry?.viewerIsAuthor === true && ( router.push(feedbackEditRouteHref(routes.edit), { relativeToDirectory: true, }) } tintColor={theme.colors.primary} > {messages.entry.edit} )} ); } export function CreateFeedbackScreen() { const { enabledKinds } = useFeedbackBody(); const { messages, theme } = useFeedbackUi(); const { routes, colors, androidToolbarIcons } = useRoutedFeedback(); const modal = useRoutedFeedbackModal(); const router = useRouter(); const [kind, setKind] = useState(enabledKinds[0] ?? "feedback"); const [title, setTitle] = useState(""); const [body, setBody] = useState(""); const entryHref = (entryId: string) => feedbackEntryRouteHref(`../${routes.entry}`, { entryId }); return ( <> router.push(entryHref(entryId), { relativeToDirectory: true }) } onCreated={(entryId) => { router.dismissTo(entryHref(entryId), { relativeToDirectory: true, }); }} /> (modal ? modal.dismiss() : router.dismiss())} tintColor={theme.colors.text} > {messages.form.cancel} ); }