initial: add login

This commit is contained in:
Tran Anh Tuan
2025-10-29 17:47:45 +07:00
parent 45dc7d1ff8
commit 79959a3050
19 changed files with 864 additions and 67 deletions

View File

@@ -1,10 +1,10 @@
import { Tabs } from 'expo-router';
import React from 'react';
import { Tabs } from "expo-router";
import React from "react";
import { HapticTab } from '@/components/haptic-tab';
import { IconSymbol } from '@/components/ui/icon-symbol';
import { Colors } from '@/constants/theme';
import { useColorScheme } from '@/hooks/use-color-scheme';
import { HapticTab } from "@/components/haptic-tab";
import { IconSymbol } from "@/components/ui/icon-symbol";
import { Colors } from "@/constants/theme";
import { useColorScheme } from "@/hooks/use-color-scheme";
export default function TabLayout() {
const colorScheme = useColorScheme();
@@ -12,22 +12,36 @@ export default function TabLayout() {
return (
<Tabs
screenOptions={{
tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint,
tabBarActiveTintColor: Colors[colorScheme ?? "light"].tint,
headerShown: false,
tabBarButton: HapticTab,
}}>
}}
>
<Tabs.Screen
name="index"
options={{
title: 'Home',
tabBarIcon: ({ color }) => <IconSymbol size={28} name="house.fill" color={color} />,
title: "Home",
tabBarIcon: ({ color }) => (
<IconSymbol size={28} name="house.fill" color={color} />
),
}}
/>
<Tabs.Screen
name="explore"
options={{
title: 'Explore',
tabBarIcon: ({ color }) => <IconSymbol size={28} name="paperplane.fill" color={color} />,
title: "Explore",
tabBarIcon: ({ color }) => (
<IconSymbol size={28} name="paperplane.fill" color={color} />
),
}}
/>
<Tabs.Screen
name="setting"
options={{
title: "Setting",
tabBarIcon: ({ color }) => (
<IconSymbol size={28} name="gear" color={color} />
),
}}
/>
</Tabs>

View File

@@ -1,38 +1,42 @@
import { Image } from 'expo-image';
import { Platform, StyleSheet } from 'react-native';
import { Image } from "expo-image";
import { Platform, StyleSheet, TouchableOpacity } from "react-native";
import { HelloWave } from '@/components/hello-wave';
import ParallaxScrollView from '@/components/parallax-scroll-view';
import { ThemedText } from '@/components/themed-text';
import { ThemedView } from '@/components/themed-view';
import { Link } from 'expo-router';
import { HelloWave } from "@/components/hello-wave";
import ParallaxScrollView from "@/components/parallax-scroll-view";
import { ThemedText } from "@/components/themed-text";
import { ThemedView } from "@/components/themed-view";
import { Text } from "@react-navigation/elements";
import { Link, useRouter } from "expo-router";
export default function HomeScreen() {
const router = useRouter();
return (
<ParallaxScrollView
headerBackgroundColor={{ light: '#A1CEDC', dark: '#1D3D47' }}
headerBackgroundColor={{ light: "#A1CEDC", dark: "#1D3D47" }}
headerImage={
<Image
source={require('@/assets/images/partial-react-logo.png')}
source={require("@/assets/images/partial-react-logo.png")}
style={styles.reactLogo}
/>
}>
}
>
<ThemedView style={styles.titleContainer}>
<ThemedText type="title">Welcome!</ThemedText>
<ThemedText type="title">Nicce!</ThemedText>
<HelloWave />
</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{' '}
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',
ios: "cmd + d",
android: "cmd + m",
web: "F12",
})}
</ThemedText>{' '}
</ThemedText>{" "}
to open developer tools.
</ThemedText>
</ThemedView>
@@ -43,18 +47,22 @@ export default function HomeScreen() {
</Link.Trigger>
<Link.Preview />
<Link.Menu>
<Link.MenuAction title="Action" icon="cube" onPress={() => alert('Action pressed')} />
<Link.MenuAction
title="Action"
icon="cube"
onPress={() => alert("Action pressed")}
/>
<Link.MenuAction
title="Share"
icon="square.and.arrow.up"
onPress={() => alert('Share pressed')}
onPress={() => alert("Share pressed")}
/>
<Link.Menu title="More" icon="ellipsis">
<Link.MenuAction
title="Delete"
icon="trash"
destructive
onPress={() => alert('Delete pressed')}
onPress={() => alert("Delete pressed")}
/>
</Link.Menu>
</Link.Menu>
@@ -68,20 +76,29 @@ export default function HomeScreen() {
<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">
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>
<TouchableOpacity
onPress={() => router.replace("/auth/login")}
// disabled={loading}
>
<Text>Đăng nhập</Text>
</TouchableOpacity>
</ParallaxScrollView>
);
}
const styles = StyleSheet.create({
titleContainer: {
flexDirection: 'row',
alignItems: 'center',
flexDirection: "row",
alignItems: "center",
gap: 8,
},
stepContainer: {
@@ -93,6 +110,6 @@ const styles = StyleSheet.create({
width: 290,
bottom: 0,
left: 0,
position: 'absolute',
position: "absolute",
},
});

71
app/(tabs)/setting.tsx Normal file
View File

@@ -0,0 +1,71 @@
import { useRouter } from "expo-router";
import { StyleSheet } from "react-native";
import { ThemedText } from "@/components/themed-text";
import { ThemedView } from "@/components/themed-view";
import { api } from "@/config";
import { TOKEN } from "@/constants";
import { removeStorageItem } from "@/utils/storage";
import { useState } from "react";
type Todo = {
userId: number;
id: number;
title: string;
completed: boolean;
};
export default function SettingScreen() {
const router = useRouter();
const [data, setData] = useState<Todo | null>(null);
// useEffect(() => {
// getData();
// }, []);
const getData = async () => {
try {
const response = await api.get("/todos/1");
setData(response.data);
} catch (error) {
console.error("Error fetching data:", error);
}
};
return (
<ThemedView style={styles.container}>
<ThemedText type="title">Settings</ThemedText>
<ThemedView
style={styles.button}
onTouchEnd={() => {
removeStorageItem(TOKEN);
router.replace("/auth/login");
}}
>
<ThemedText type="defaultSemiBold">Đăng xuất</ThemedText>
</ThemedView>
{data && (
<ThemedView style={{ marginTop: 20 }}>
<ThemedText type="default">{data.title}</ThemedText>
<ThemedText type="default">{data.completed}</ThemedText>
<ThemedText type="default">{data.id}</ThemedText>
</ThemedView>
)}
</ThemedView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
padding: 20,
},
button: {
marginTop: 20,
padding: 10,
backgroundColor: "#007AFF",
borderRadius: 5,
},
});