init
This commit is contained in:
parent
a98bc17a7d
commit
7386f012aa
1
.env.example
Normal file
1
.env.example
Normal file
@ -0,0 +1 @@
|
|||||||
|
EXPO_BACKEND_BASE_URL=
|
||||||
4
.gitignore
vendored
4
.gitignore
vendored
@ -32,6 +32,7 @@ yarn-error.*
|
|||||||
|
|
||||||
# local env files
|
# local env files
|
||||||
.env*.local
|
.env*.local
|
||||||
|
.env
|
||||||
|
|
||||||
# typescript
|
# typescript
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
@ -41,3 +42,6 @@ app-example
|
|||||||
# generated native folders
|
# generated native folders
|
||||||
/ios
|
/ios
|
||||||
/android
|
/android
|
||||||
|
|
||||||
|
# Editors
|
||||||
|
.vscode/
|
||||||
25
api/axiosInstance.ts
Normal file
25
api/axiosInstance.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
const axiosInstance = axios.create({
|
||||||
|
baseURL: process.env.EXPO_PUBLIC_BACKEND_BASE_URL,
|
||||||
|
timeout: 30 * 1000
|
||||||
|
});
|
||||||
|
|
||||||
|
axiosInstance.interceptors.request.use(
|
||||||
|
(config) => {
|
||||||
|
const token = localStorage.getItem("access_token");
|
||||||
|
if (token) config.headers.Authorization = `Bearer ${token}`;
|
||||||
|
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
(error) => Promise.reject(error),
|
||||||
|
);
|
||||||
|
axiosInstance.interceptors.response.use(undefined, async (error) => {
|
||||||
|
if (error.response?.status === 401) {
|
||||||
|
localStorage.removeItem("access_token");
|
||||||
|
}
|
||||||
|
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
|
|
||||||
|
export default axiosInstance;
|
||||||
14
api/client.ts
Normal file
14
api/client.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import axiosInstance from "./axiosInstance";
|
||||||
|
import { Pagination, QuestionResponse } from "./types";
|
||||||
|
|
||||||
|
export const get_questions = async (page: number, test_id?: number, question_id?: number) => {
|
||||||
|
const response = await axiosInstance.get<Pagination<QuestionResponse>>("/api/questions/", {
|
||||||
|
params: {
|
||||||
|
page,
|
||||||
|
test_id,
|
||||||
|
question_id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
1
api/index.ts
Normal file
1
api/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './questions';
|
||||||
15
api/questions.ts
Normal file
15
api/questions.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import { get_questions } from "./client";
|
||||||
|
|
||||||
|
interface useQuestionsAttr {
|
||||||
|
page?: number;
|
||||||
|
test_id?: number;
|
||||||
|
question_id?: number;
|
||||||
|
}
|
||||||
|
export const useQuestions = ({ page = 1, test_id, question_id }: useQuestionsAttr = { }) => {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ['questions', page, test_id, question_id],
|
||||||
|
queryFn: () => get_questions(page, test_id, question_id)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
67
api/types.ts
Normal file
67
api/types.ts
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
export interface Pagination<T> {
|
||||||
|
data: T[];
|
||||||
|
links: {
|
||||||
|
first: string;
|
||||||
|
last: string;
|
||||||
|
};
|
||||||
|
meta: {
|
||||||
|
current_page: number;
|
||||||
|
from: number;
|
||||||
|
last_page: number;
|
||||||
|
per_page: number;
|
||||||
|
to: number;
|
||||||
|
total: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export interface QuestionVariant {
|
||||||
|
id: number;
|
||||||
|
text: string;
|
||||||
|
}
|
||||||
|
export enum QuestionTypes {
|
||||||
|
Single = "single",
|
||||||
|
Multiple = "multiple",
|
||||||
|
Text = "text"
|
||||||
|
}
|
||||||
|
export interface QuestionResponse {
|
||||||
|
id: number;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
type: QuestionTypes;
|
||||||
|
difficulty: number;
|
||||||
|
|
||||||
|
variants: QuestionVariant[];
|
||||||
|
correct_answers: number[];
|
||||||
|
|
||||||
|
category_id: number;
|
||||||
|
category: CategoryResponse;
|
||||||
|
|
||||||
|
author_id: number;
|
||||||
|
author: UserResponse;
|
||||||
|
|
||||||
|
created_at: string;
|
||||||
|
updated_at: string;
|
||||||
|
}
|
||||||
|
export interface CategoryResponse {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
questions_count: number;
|
||||||
|
user_tests_count: number;
|
||||||
|
|
||||||
|
created_at: string;
|
||||||
|
}
|
||||||
|
export enum UserTypes {
|
||||||
|
Admin = "admin",
|
||||||
|
Creator = "creator",
|
||||||
|
User = "user",
|
||||||
|
Banned = "banned"
|
||||||
|
}
|
||||||
|
export interface UserResponse {
|
||||||
|
id: number;
|
||||||
|
username: string;
|
||||||
|
email: string;
|
||||||
|
email_verified_at: string;
|
||||||
|
type: UserTypes;
|
||||||
|
created_at: string;
|
||||||
|
updated_at: string;
|
||||||
|
}
|
||||||
2
app.json
2
app.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"expo": {
|
"expo": {
|
||||||
"name": "ai_questions_app",
|
"name": "Hoshi AI",
|
||||||
"slug": "ai_questions_app",
|
"slug": "ai_questions_app",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"orientation": "portrait",
|
"orientation": "portrait",
|
||||||
|
|||||||
@ -2,9 +2,9 @@ import { Tabs } from 'expo-router';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { HapticTab } from '@/components/haptic-tab';
|
import { HapticTab } from '@/components/haptic-tab';
|
||||||
import { IconSymbol } from '@/components/ui/icon-symbol';
|
|
||||||
import { Colors } from '@/constants/theme';
|
import { Colors } from '@/constants/theme';
|
||||||
import { useColorScheme } from '@/hooks/use-color-scheme';
|
import { useColorScheme } from '@/hooks/use-color-scheme';
|
||||||
|
import { FontAwesome5 } from '@expo/vector-icons';
|
||||||
|
|
||||||
export default function TabLayout() {
|
export default function TabLayout() {
|
||||||
const colorScheme = useColorScheme();
|
const colorScheme = useColorScheme();
|
||||||
@ -20,14 +20,28 @@ export default function TabLayout() {
|
|||||||
name="index"
|
name="index"
|
||||||
options={{
|
options={{
|
||||||
title: 'Home',
|
title: 'Home',
|
||||||
tabBarIcon: ({ color }) => <IconSymbol size={28} name="house.fill" color={color} />,
|
tabBarIcon: ({ color }) => <FontAwesome5 name="home" size={22} color={color} />,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Tabs.Screen
|
<Tabs.Screen
|
||||||
name="explore"
|
name="questions"
|
||||||
options={{
|
options={{
|
||||||
title: 'Explore',
|
title: 'Questions',
|
||||||
tabBarIcon: ({ color }) => <IconSymbol size={28} name="paperplane.fill" color={color} />,
|
tabBarIcon: ({ color }) => <FontAwesome5 name="question" size={22} color={color} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="tests"
|
||||||
|
options={{
|
||||||
|
title: 'Tests',
|
||||||
|
tabBarIcon: ({ color }) => <FontAwesome5 name="file-alt" size={22} color={color} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="me"
|
||||||
|
options={{
|
||||||
|
title: 'Me',
|
||||||
|
tabBarIcon: ({ color }) => <FontAwesome5 name="user" size={22} color={color} />,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|||||||
@ -1,87 +1,46 @@
|
|||||||
import { Image } from 'expo-image';
|
import { Image } from "expo-image";
|
||||||
import { Platform, StyleSheet } from 'react-native';
|
import { StyleSheet } from "react-native";
|
||||||
|
|
||||||
import { HelloWave } from '@/components/hello-wave';
|
import { useQuestions } from "@/api";
|
||||||
import ParallaxScrollView from '@/components/parallax-scroll-view';
|
import { HelloWave } from "@/components/hello-wave";
|
||||||
import { ThemedText } from '@/components/themed-text';
|
import ParallaxScrollView from "@/components/parallax-scroll-view";
|
||||||
import { ThemedView } from '@/components/themed-view';
|
import Question from "@/components/question";
|
||||||
import { Link } from 'expo-router';
|
import { ThemedView } from "@/components/themed-view";
|
||||||
|
import { ThemedText } from "@/components/ui/themed-text";
|
||||||
|
|
||||||
export default function HomeScreen() {
|
export default function HomeScreen() {
|
||||||
|
const { data: questions, isLoading: isLoadingQuestions } = useQuestions();
|
||||||
|
|
||||||
|
const questionsLoaded =
|
||||||
|
!isLoadingQuestions && questions && questions.meta.total > 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ParallaxScrollView
|
<ParallaxScrollView
|
||||||
headerBackgroundColor={{ light: '#A1CEDC', dark: '#1D3D47' }}
|
headerBackgroundColor={{ light: "#A1CEDC", dark: "#1D3D47" }}
|
||||||
headerImage={
|
headerImage={
|
||||||
<Image
|
<Image
|
||||||
source={require('@/assets/images/partial-react-logo.png')}
|
source={require("@/assets/images/partial-react-logo.png")}
|
||||||
style={styles.reactLogo}
|
style={styles.reactLogo}
|
||||||
/>
|
/>
|
||||||
}>
|
}
|
||||||
|
>
|
||||||
<ThemedView style={styles.titleContainer}>
|
<ThemedView style={styles.titleContainer}>
|
||||||
<ThemedText type="title">Welcome!</ThemedText>
|
<ThemedText type="title">Questions!</ThemedText>
|
||||||
<HelloWave />
|
<HelloWave />
|
||||||
</ThemedView>
|
</ThemedView>
|
||||||
<ThemedView style={styles.stepContainer}>
|
|
||||||
<ThemedText type="subtitle">Step 1: Try it</ThemedText>
|
|
||||||
<ThemedText>
|
|
||||||
Edit <ThemedText type="defaultSemiBold">app/(tabs)/index.tsx</ThemedText> to see changes.
|
|
||||||
Press{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">
|
|
||||||
{Platform.select({
|
|
||||||
ios: 'cmd + d',
|
|
||||||
android: 'cmd + m',
|
|
||||||
web: 'F12',
|
|
||||||
})}
|
|
||||||
</ThemedText>{' '}
|
|
||||||
to open developer tools.
|
|
||||||
</ThemedText>
|
|
||||||
</ThemedView>
|
|
||||||
<ThemedView style={styles.stepContainer}>
|
|
||||||
<Link href="/modal">
|
|
||||||
<Link.Trigger>
|
|
||||||
<ThemedText type="subtitle">Step 2: Explore</ThemedText>
|
|
||||||
</Link.Trigger>
|
|
||||||
<Link.Preview />
|
|
||||||
<Link.Menu>
|
|
||||||
<Link.MenuAction title="Action" icon="cube" onPress={() => alert('Action pressed')} />
|
|
||||||
<Link.MenuAction
|
|
||||||
title="Share"
|
|
||||||
icon="square.and.arrow.up"
|
|
||||||
onPress={() => alert('Share pressed')}
|
|
||||||
/>
|
|
||||||
<Link.Menu title="More" icon="ellipsis">
|
|
||||||
<Link.MenuAction
|
|
||||||
title="Delete"
|
|
||||||
icon="trash"
|
|
||||||
destructive
|
|
||||||
onPress={() => alert('Delete pressed')}
|
|
||||||
/>
|
|
||||||
</Link.Menu>
|
|
||||||
</Link.Menu>
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
<ThemedText>
|
{questionsLoaded &&
|
||||||
{`Tap the Explore tab to learn more about what's included in this starter app.`}
|
questions.data.map((question) => (
|
||||||
</ThemedText>
|
<Question key={question.id} question={question} />
|
||||||
</ThemedView>
|
))}
|
||||||
<ThemedView style={styles.stepContainer}>
|
|
||||||
<ThemedText type="subtitle">Step 3: Get a fresh start</ThemedText>
|
|
||||||
<ThemedText>
|
|
||||||
{`When you're ready, run `}
|
|
||||||
<ThemedText type="defaultSemiBold">npm run reset-project</ThemedText> to get a fresh{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">app</ThemedText> directory. This will move the current{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">app</ThemedText> to{' '}
|
|
||||||
<ThemedText type="defaultSemiBold">app-example</ThemedText>.
|
|
||||||
</ThemedText>
|
|
||||||
</ThemedView>
|
|
||||||
</ParallaxScrollView>
|
</ParallaxScrollView>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
titleContainer: {
|
titleContainer: {
|
||||||
flexDirection: 'row',
|
flexDirection: "row",
|
||||||
alignItems: 'center',
|
alignItems: "center",
|
||||||
gap: 8,
|
gap: 8,
|
||||||
},
|
},
|
||||||
stepContainer: {
|
stepContainer: {
|
||||||
@ -93,6 +52,6 @@ const styles = StyleSheet.create({
|
|||||||
width: 290,
|
width: 290,
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
left: 0,
|
left: 0,
|
||||||
position: 'absolute',
|
position: "absolute",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
57
app/(tabs)/me.tsx
Normal file
57
app/(tabs)/me.tsx
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import { Image } from 'expo-image';
|
||||||
|
import { Platform, StyleSheet } from 'react-native';
|
||||||
|
|
||||||
|
import ParallaxScrollView from '@/components/parallax-scroll-view';
|
||||||
|
import { ThemedView } from '@/components/themed-view';
|
||||||
|
import { ThemedText } from '@/components/ui/themed-text';
|
||||||
|
|
||||||
|
export default function HomeScreen() {
|
||||||
|
return (
|
||||||
|
<ParallaxScrollView
|
||||||
|
headerBackgroundColor={{ light: '#A1CEDC', dark: '#1D3D47' }}
|
||||||
|
headerImage={
|
||||||
|
<Image
|
||||||
|
source={require('@/assets/images/partial-react-logo.png')}
|
||||||
|
style={styles.reactLogo}
|
||||||
|
/>
|
||||||
|
}>
|
||||||
|
<ThemedView style={styles.titleContainer}>
|
||||||
|
<ThemedText type="title">Welcome!</ThemedText>
|
||||||
|
</ThemedView>
|
||||||
|
<ThemedView style={styles.stepContainer}>
|
||||||
|
<ThemedText type="subtitle">Step 1: Try it</ThemedText>
|
||||||
|
<ThemedText>
|
||||||
|
Edit <ThemedText type="defaultSemiBold">app/(tabs)/index.tsx</ThemedText> to see changes.
|
||||||
|
Press{' '}
|
||||||
|
<ThemedText type="defaultSemiBold">
|
||||||
|
{Platform.select({
|
||||||
|
ios: 'cmd + d',
|
||||||
|
android: 'cmd + m',
|
||||||
|
web: 'F12',
|
||||||
|
})}
|
||||||
|
</ThemedText>{' '}
|
||||||
|
to open developer tools.
|
||||||
|
</ThemedText>
|
||||||
|
</ThemedView>
|
||||||
|
</ParallaxScrollView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
titleContainer: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: 8,
|
||||||
|
},
|
||||||
|
stepContainer: {
|
||||||
|
gap: 8,
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
reactLogo: {
|
||||||
|
height: 178,
|
||||||
|
width: 290,
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
position: 'absolute',
|
||||||
|
},
|
||||||
|
});
|
||||||
@ -1,12 +1,12 @@
|
|||||||
import { Image } from 'expo-image';
|
import { Image } from 'expo-image';
|
||||||
import { Platform, StyleSheet } from 'react-native';
|
import { Platform, StyleSheet } from 'react-native';
|
||||||
|
|
||||||
import { Collapsible } from '@/components/ui/collapsible';
|
|
||||||
import { ExternalLink } from '@/components/external-link';
|
import { ExternalLink } from '@/components/external-link';
|
||||||
import ParallaxScrollView from '@/components/parallax-scroll-view';
|
import ParallaxScrollView from '@/components/parallax-scroll-view';
|
||||||
import { ThemedText } from '@/components/themed-text';
|
|
||||||
import { ThemedView } from '@/components/themed-view';
|
import { ThemedView } from '@/components/themed-view';
|
||||||
|
import { Collapsible } from '@/components/ui/collapsible';
|
||||||
import { IconSymbol } from '@/components/ui/icon-symbol';
|
import { IconSymbol } from '@/components/ui/icon-symbol';
|
||||||
|
import { ThemedText } from '@/components/ui/themed-text';
|
||||||
import { Fonts } from '@/constants/theme';
|
import { Fonts } from '@/constants/theme';
|
||||||
|
|
||||||
export default function TabTwoScreen() {
|
export default function TabTwoScreen() {
|
||||||
57
app/(tabs)/tests.tsx
Normal file
57
app/(tabs)/tests.tsx
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import { Image } from 'expo-image';
|
||||||
|
import { Platform, StyleSheet } from 'react-native';
|
||||||
|
|
||||||
|
import ParallaxScrollView from '@/components/parallax-scroll-view';
|
||||||
|
import { ThemedView } from '@/components/themed-view';
|
||||||
|
import { ThemedText } from '@/components/ui/themed-text';
|
||||||
|
|
||||||
|
export default function HomeScreen() {
|
||||||
|
return (
|
||||||
|
<ParallaxScrollView
|
||||||
|
headerBackgroundColor={{ light: '#A1CEDC', dark: '#1D3D47' }}
|
||||||
|
headerImage={
|
||||||
|
<Image
|
||||||
|
source={require('@/assets/images/partial-react-logo.png')}
|
||||||
|
style={styles.reactLogo}
|
||||||
|
/>
|
||||||
|
}>
|
||||||
|
<ThemedView style={styles.titleContainer}>
|
||||||
|
<ThemedText type="title">Welcome!</ThemedText>
|
||||||
|
</ThemedView>
|
||||||
|
<ThemedView style={styles.stepContainer}>
|
||||||
|
<ThemedText type="subtitle">Step 1: Try it</ThemedText>
|
||||||
|
<ThemedText>
|
||||||
|
Edit <ThemedText type="defaultSemiBold">app/(tabs)/index.tsx</ThemedText> to see changes.
|
||||||
|
Press{' '}
|
||||||
|
<ThemedText type="defaultSemiBold">
|
||||||
|
{Platform.select({
|
||||||
|
ios: 'cmd + d',
|
||||||
|
android: 'cmd + m',
|
||||||
|
web: 'F12',
|
||||||
|
})}
|
||||||
|
</ThemedText>{' '}
|
||||||
|
to open developer tools.
|
||||||
|
</ThemedText>
|
||||||
|
</ThemedView>
|
||||||
|
</ParallaxScrollView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
titleContainer: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: 8,
|
||||||
|
},
|
||||||
|
stepContainer: {
|
||||||
|
gap: 8,
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
reactLogo: {
|
||||||
|
height: 178,
|
||||||
|
width: 290,
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
position: 'absolute',
|
||||||
|
},
|
||||||
|
});
|
||||||
@ -1,4 +1,5 @@
|
|||||||
import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
|
import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
|
||||||
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||||
import { Stack } from 'expo-router';
|
import { Stack } from 'expo-router';
|
||||||
import { StatusBar } from 'expo-status-bar';
|
import { StatusBar } from 'expo-status-bar';
|
||||||
import 'react-native-reanimated';
|
import 'react-native-reanimated';
|
||||||
@ -9,10 +10,13 @@ export const unstable_settings = {
|
|||||||
anchor: '(tabs)',
|
anchor: '(tabs)',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const queryClient = new QueryClient();
|
||||||
|
|
||||||
export default function RootLayout() {
|
export default function RootLayout() {
|
||||||
const colorScheme = useColorScheme();
|
const colorScheme = useColorScheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<QueryClientProvider client={queryClient}>
|
||||||
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
|
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
|
||||||
<Stack>
|
<Stack>
|
||||||
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
|
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
|
||||||
@ -20,5 +24,6 @@ export default function RootLayout() {
|
|||||||
</Stack>
|
</Stack>
|
||||||
<StatusBar style="auto" />
|
<StatusBar style="auto" />
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
|
</QueryClientProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { Link } from 'expo-router';
|
import { Link } from 'expo-router';
|
||||||
import { StyleSheet } from 'react-native';
|
import { StyleSheet } from 'react-native';
|
||||||
|
|
||||||
import { ThemedText } from '@/components/themed-text';
|
|
||||||
import { ThemedView } from '@/components/themed-view';
|
import { ThemedView } from '@/components/themed-view';
|
||||||
|
import { ThemedText } from '@/components/ui/themed-text';
|
||||||
|
|
||||||
export default function ModalScreen() {
|
export default function ModalScreen() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
32
components/question.tsx
Normal file
32
components/question.tsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { QuestionResponse } from "@/api/types";
|
||||||
|
import { Pressable, StyleSheet } from "react-native";
|
||||||
|
import Panel from "./ui/panel";
|
||||||
|
import { ThemedText } from "./ui/themed-text";
|
||||||
|
|
||||||
|
interface QuestionProps {
|
||||||
|
question: QuestionResponse;
|
||||||
|
onPress?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Question = ({ question, onPress }: QuestionProps) => {
|
||||||
|
return (
|
||||||
|
<Pressable onPress={onPress}>
|
||||||
|
<Panel>
|
||||||
|
<ThemedText style={styles.questionTitle}>{question.title}</ThemedText>
|
||||||
|
<ThemedText>{question.description}</ThemedText>
|
||||||
|
</Panel>
|
||||||
|
</Pressable>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
questionTitle: {
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: "600",
|
||||||
|
marginBottom: 10
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export default Question;
|
||||||
@ -1,9 +1,9 @@
|
|||||||
import { PropsWithChildren, useState } from 'react';
|
import { PropsWithChildren, useState } from 'react';
|
||||||
import { StyleSheet, TouchableOpacity } from 'react-native';
|
import { StyleSheet, TouchableOpacity } from 'react-native';
|
||||||
|
|
||||||
import { ThemedText } from '@/components/themed-text';
|
|
||||||
import { ThemedView } from '@/components/themed-view';
|
import { ThemedView } from '@/components/themed-view';
|
||||||
import { IconSymbol } from '@/components/ui/icon-symbol';
|
import { IconSymbol } from '@/components/ui/icon-symbol';
|
||||||
|
import { ThemedText } from '@/components/ui/themed-text';
|
||||||
import { Colors } from '@/constants/theme';
|
import { Colors } from '@/constants/theme';
|
||||||
import { useColorScheme } from '@/hooks/use-color-scheme';
|
import { useColorScheme } from '@/hooks/use-color-scheme';
|
||||||
|
|
||||||
|
|||||||
24
components/ui/not-found.tsx
Normal file
24
components/ui/not-found.tsx
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { StyleSheet, View } from "react-native";
|
||||||
|
import { ThemedText } from "./themed-text";
|
||||||
|
|
||||||
|
interface NotFoundProps {
|
||||||
|
text?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const NotFound = ({text = "Not Found"}: NotFoundProps) => {
|
||||||
|
return (
|
||||||
|
<View style={styles.notFound}>
|
||||||
|
<ThemedText>{text}</ThemedText>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
notFound: {
|
||||||
|
padding: 15,
|
||||||
|
textAlign: "center"
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
export default NotFound;
|
||||||
25
components/ui/panel.tsx
Normal file
25
components/ui/panel.tsx
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { ReactNode } from "react";
|
||||||
|
import { StyleSheet, View } from "react-native";
|
||||||
|
|
||||||
|
interface PanelProps {
|
||||||
|
children?: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Panel = ({children}: PanelProps) => {
|
||||||
|
return (
|
||||||
|
<View style={styles.panel}>
|
||||||
|
{children}
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
panel: {
|
||||||
|
padding: 15,
|
||||||
|
borderRadius: 5,
|
||||||
|
boxShadow: '0px 4px 5px 0px rgba(0,0,0,0.18)'
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
export default Panel;
|
||||||
178
package-lock.json
generated
178
package-lock.json
generated
@ -12,6 +12,8 @@
|
|||||||
"@react-navigation/bottom-tabs": "^7.4.0",
|
"@react-navigation/bottom-tabs": "^7.4.0",
|
||||||
"@react-navigation/elements": "^2.6.3",
|
"@react-navigation/elements": "^2.6.3",
|
||||||
"@react-navigation/native": "^7.1.8",
|
"@react-navigation/native": "^7.1.8",
|
||||||
|
"@tanstack/react-query": "^5.90.16",
|
||||||
|
"axios": "^1.13.2",
|
||||||
"expo": "~54.0.30",
|
"expo": "~54.0.30",
|
||||||
"expo-constants": "~18.0.12",
|
"expo-constants": "~18.0.12",
|
||||||
"expo-font": "~14.0.10",
|
"expo-font": "~14.0.10",
|
||||||
@ -31,6 +33,7 @@
|
|||||||
"react-native-reanimated": "~4.1.1",
|
"react-native-reanimated": "~4.1.1",
|
||||||
"react-native-safe-area-context": "~5.6.0",
|
"react-native-safe-area-context": "~5.6.0",
|
||||||
"react-native-screens": "~4.16.0",
|
"react-native-screens": "~4.16.0",
|
||||||
|
"react-native-vector-icons": "^10.3.0",
|
||||||
"react-native-web": "~0.21.0",
|
"react-native-web": "~0.21.0",
|
||||||
"react-native-worklets": "0.5.1"
|
"react-native-worklets": "0.5.1"
|
||||||
},
|
},
|
||||||
@ -3153,6 +3156,32 @@
|
|||||||
"@sinonjs/commons": "^3.0.0"
|
"@sinonjs/commons": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tanstack/query-core": {
|
||||||
|
"version": "5.90.16",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.16.tgz",
|
||||||
|
"integrity": "sha512-MvtWckSVufs/ja463/K4PyJeqT+HMlJWtw6PrCpywznd2NSgO3m4KwO9RqbFqGg6iDE8vVMFWMeQI4Io3eEYww==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/tannerlinsley"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tanstack/react-query": {
|
||||||
|
"version": "5.90.16",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.16.tgz",
|
||||||
|
"integrity": "sha512-bpMGOmV4OPmif7TNMteU/Ehf/hoC0Kf98PDc0F4BZkFrEapRMEqI/V6YS0lyzwSV6PQpY1y4xxArUIfBW5LVxQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@tanstack/query-core": "5.90.16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/tannerlinsley"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^18 || ^19"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@tybys/wasm-util": {
|
"node_modules/@tybys/wasm-util": {
|
||||||
"version": "0.10.1",
|
"version": "0.10.1",
|
||||||
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
|
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
|
||||||
@ -4236,6 +4265,12 @@
|
|||||||
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
|
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/asynckit": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/available-typed-arrays": {
|
"node_modules/available-typed-arrays": {
|
||||||
"version": "1.0.7",
|
"version": "1.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
|
||||||
@ -4252,6 +4287,17 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/axios": {
|
||||||
|
"version": "1.13.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz",
|
||||||
|
"integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"follow-redirects": "^1.15.6",
|
||||||
|
"form-data": "^4.0.4",
|
||||||
|
"proxy-from-env": "^1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/babel-jest": {
|
"node_modules/babel-jest": {
|
||||||
"version": "29.7.0",
|
"version": "29.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
|
||||||
@ -4681,7 +4727,6 @@
|
|||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||||
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"es-errors": "^1.3.0",
|
"es-errors": "^1.3.0",
|
||||||
@ -4907,6 +4952,18 @@
|
|||||||
"simple-swizzle": "^0.2.2"
|
"simple-swizzle": "^0.2.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/combined-stream": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"delayed-stream": "~1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/commander": {
|
"node_modules/commander": {
|
||||||
"version": "7.2.0",
|
"version": "7.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
|
||||||
@ -5235,6 +5292,15 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/delayed-stream": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/depd": {
|
"node_modules/depd": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||||
@ -5313,7 +5379,6 @@
|
|||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||||
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"call-bind-apply-helpers": "^1.0.1",
|
"call-bind-apply-helpers": "^1.0.1",
|
||||||
@ -5442,7 +5507,6 @@
|
|||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||||
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
@ -5452,7 +5516,6 @@
|
|||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||||
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
@ -5490,7 +5553,6 @@
|
|||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||||
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"es-errors": "^1.3.0"
|
"es-errors": "^1.3.0"
|
||||||
@ -5503,7 +5565,6 @@
|
|||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
||||||
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"es-errors": "^1.3.0",
|
"es-errors": "^1.3.0",
|
||||||
@ -6867,6 +6928,26 @@
|
|||||||
"integrity": "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==",
|
"integrity": "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/follow-redirects": {
|
||||||
|
"version": "1.15.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
|
||||||
|
"integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"debug": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fontfaceobserver": {
|
"node_modules/fontfaceobserver": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/fontfaceobserver/-/fontfaceobserver-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/fontfaceobserver/-/fontfaceobserver-2.3.0.tgz",
|
||||||
@ -6889,6 +6970,22 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/form-data": {
|
||||||
|
"version": "4.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
|
||||||
|
"integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"asynckit": "^0.4.0",
|
||||||
|
"combined-stream": "^1.0.8",
|
||||||
|
"es-set-tostringtag": "^2.1.0",
|
||||||
|
"hasown": "^2.0.2",
|
||||||
|
"mime-types": "^2.1.12"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/freeport-async": {
|
"node_modules/freeport-async": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/freeport-async/-/freeport-async-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/freeport-async/-/freeport-async-2.0.0.tgz",
|
||||||
@ -6999,7 +7096,6 @@
|
|||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||||
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"call-bind-apply-helpers": "^1.0.2",
|
"call-bind-apply-helpers": "^1.0.2",
|
||||||
@ -7042,7 +7138,6 @@
|
|||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
||||||
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dunder-proto": "^1.0.1",
|
"dunder-proto": "^1.0.1",
|
||||||
@ -7183,7 +7278,6 @@
|
|||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||||
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
@ -7253,7 +7347,6 @@
|
|||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||||
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
@ -7266,7 +7359,6 @@
|
|||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||||
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"has-symbols": "^1.0.3"
|
"has-symbols": "^1.0.3"
|
||||||
@ -8785,7 +8877,6 @@
|
|||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||||
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
@ -10027,7 +10118,6 @@
|
|||||||
"version": "15.8.1",
|
"version": "15.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.4.0",
|
"loose-envify": "^1.4.0",
|
||||||
@ -10039,7 +10129,12 @@
|
|||||||
"version": "16.13.1",
|
"version": "16.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||||
"dev": true,
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/proxy-from-env": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/punycode": {
|
"node_modules/punycode": {
|
||||||
@ -10309,6 +10404,61 @@
|
|||||||
"react-native": "*"
|
"react-native": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-native-vector-icons": {
|
||||||
|
"version": "10.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-vector-icons/-/react-native-vector-icons-10.3.0.tgz",
|
||||||
|
"integrity": "sha512-IFQ0RE57819hOUdFvgK4FowM5aMXg7C7XKsuGLevqXkkIJatc3QopN0wYrb2IrzUgmdpfP+QVIbI3S6h7M0btw==",
|
||||||
|
"deprecated": "react-native-vector-icons package has moved to a new model of per-icon-family packages. See the https://github.com/oblador/react-native-vector-icons/blob/master/MIGRATION.md on how to migrate",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
|
"yargs": "^16.1.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"fa-upgrade.sh": "bin/fa-upgrade.sh",
|
||||||
|
"fa5-upgrade": "bin/fa5-upgrade.sh",
|
||||||
|
"fa6-upgrade": "bin/fa6-upgrade.sh",
|
||||||
|
"generate-icon": "bin/generate-icon.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-native-vector-icons/node_modules/cliui": {
|
||||||
|
"version": "7.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
|
||||||
|
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"string-width": "^4.2.0",
|
||||||
|
"strip-ansi": "^6.0.0",
|
||||||
|
"wrap-ansi": "^7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-native-vector-icons/node_modules/yargs": {
|
||||||
|
"version": "16.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
|
||||||
|
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"cliui": "^7.0.2",
|
||||||
|
"escalade": "^3.1.1",
|
||||||
|
"get-caller-file": "^2.0.5",
|
||||||
|
"require-directory": "^2.1.1",
|
||||||
|
"string-width": "^4.2.0",
|
||||||
|
"y18n": "^5.0.5",
|
||||||
|
"yargs-parser": "^20.2.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-native-vector-icons/node_modules/yargs-parser": {
|
||||||
|
"version": "20.2.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
|
||||||
|
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-native-web": {
|
"node_modules/react-native-web": {
|
||||||
"version": "0.21.2",
|
"version": "0.21.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.21.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.21.2.tgz",
|
||||||
|
|||||||
11
package.json
11
package.json
@ -15,6 +15,8 @@
|
|||||||
"@react-navigation/bottom-tabs": "^7.4.0",
|
"@react-navigation/bottom-tabs": "^7.4.0",
|
||||||
"@react-navigation/elements": "^2.6.3",
|
"@react-navigation/elements": "^2.6.3",
|
||||||
"@react-navigation/native": "^7.1.8",
|
"@react-navigation/native": "^7.1.8",
|
||||||
|
"@tanstack/react-query": "^5.90.16",
|
||||||
|
"axios": "^1.13.2",
|
||||||
"expo": "~54.0.30",
|
"expo": "~54.0.30",
|
||||||
"expo-constants": "~18.0.12",
|
"expo-constants": "~18.0.12",
|
||||||
"expo-font": "~14.0.10",
|
"expo-font": "~14.0.10",
|
||||||
@ -31,17 +33,18 @@
|
|||||||
"react-dom": "19.1.0",
|
"react-dom": "19.1.0",
|
||||||
"react-native": "0.81.5",
|
"react-native": "0.81.5",
|
||||||
"react-native-gesture-handler": "~2.28.0",
|
"react-native-gesture-handler": "~2.28.0",
|
||||||
"react-native-worklets": "0.5.1",
|
|
||||||
"react-native-reanimated": "~4.1.1",
|
"react-native-reanimated": "~4.1.1",
|
||||||
"react-native-safe-area-context": "~5.6.0",
|
"react-native-safe-area-context": "~5.6.0",
|
||||||
"react-native-screens": "~4.16.0",
|
"react-native-screens": "~4.16.0",
|
||||||
"react-native-web": "~0.21.0"
|
"react-native-vector-icons": "^10.3.0",
|
||||||
|
"react-native-web": "~0.21.0",
|
||||||
|
"react-native-worklets": "0.5.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "~19.1.0",
|
"@types/react": "~19.1.0",
|
||||||
"typescript": "~5.9.2",
|
|
||||||
"eslint": "^9.25.0",
|
"eslint": "^9.25.0",
|
||||||
"eslint-config-expo": "~10.0.0"
|
"eslint-config-expo": "~10.0.0",
|
||||||
|
"typescript": "~5.9.2"
|
||||||
},
|
},
|
||||||
"private": true
|
"private": true
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user