Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY=YOUR_CLERK_PUBLISHABLE_KEY
36 changes: 36 additions & 0 deletions app/(tabs)/_layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { BottomTabBar } from "@/components/bottom-tab-bar";
import { useLanguageStore } from "@/store/UseLanguageStore";
import { useAuth } from "@clerk/expo";
import { Redirect, Tabs } from "expo-router";

export default function TabsLayout() {
const { isLoaded, isSignedIn } = useAuth();
const hasHydratedLanguage = useLanguageStore((state) => state.hasHydrated);
const selectedLanguageId = useLanguageStore((state) => state.selectedLanguageId);

if (!isLoaded || !hasHydratedLanguage) {
return null;
}

if (!isSignedIn) {
return <Redirect href="/onboarding" />;
}

if (!selectedLanguageId) {
return <Redirect href="/LanguageSelection" />;
}

return (
<Tabs
initialRouteName="home"
screenOptions={{ headerShown: false }}
tabBar={(props) => <BottomTabBar {...props} />}
>
<Tabs.Screen name="home" options={{ title: "Home" }} />
<Tabs.Screen name="learn" options={{ title: "Learn" }} />
<Tabs.Screen name="ai-teacher" options={{ title: "AI Teacher" }} />
<Tabs.Screen name="chat" options={{ title: "Chat" }} />
<Tabs.Screen name="profile" options={{ title: "Profile" }} />
</Tabs>
);
}
10 changes: 10 additions & 0 deletions app/(tabs)/ai-teacher.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { TabPlaceholderScreen } from "@/components/tab-placeholder-screen";

export default function AiTeacherScreen() {
return (
<TabPlaceholderScreen
title="AI Teacher"
subtitle="Video teacher sessions will live here."
/>
);
}
10 changes: 10 additions & 0 deletions app/(tabs)/chat.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { TabPlaceholderScreen } from "@/components/tab-placeholder-screen";

export default function ChatScreen() {
return (
<TabPlaceholderScreen
title="Chat"
subtitle="AI tutor conversations will live here."
/>
);
}
10 changes: 10 additions & 0 deletions app/(tabs)/home.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { TabPlaceholderScreen } from "@/components/tab-placeholder-screen";

export default function HomeScreen() {
return (
<TabPlaceholderScreen
title="Home"
subtitle="Home content will be implemented in the next step."
/>
);
}
10 changes: 10 additions & 0 deletions app/(tabs)/learn.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { TabPlaceholderScreen } from "@/components/tab-placeholder-screen";

export default function LearnScreen() {
return (
<TabPlaceholderScreen
title="Learn"
subtitle="Lesson browsing and practice will live here."
/>
);
}
10 changes: 10 additions & 0 deletions app/(tabs)/profile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { TabPlaceholderScreen } from "@/components/tab-placeholder-screen";

export default function ProfileScreen() {
return (
<TabPlaceholderScreen
title="Profile"
subtitle="Account details and learning stats will live here."
/>
);
}
20 changes: 19 additions & 1 deletion app/language-selection.tsx → app/LanguageSelection.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { images } from "@/constants/images";
import { defaultLanguageId, languages } from "@/data/languages";
import { useLanguageStore } from "@/store/UseLanguageStore";
import type { SupportedLanguage } from "@/types/learning";
import { Ionicons } from "@expo/vector-icons";
import { router } from "expo-router";
Expand All @@ -19,8 +20,14 @@ import { useSafeAreaInsets } from "react-native-safe-area-context";
export default function LanguageSelectionScreen() {
const insets = useSafeAreaInsets();
const { width } = useWindowDimensions();
const persistedLanguageId = useLanguageStore((state) => state.selectedLanguageId);
const setSelectedLanguage = useLanguageStore(
(state) => state.setSelectedLanguageId,
);
const [searchQuery, setSearchQuery] = useState("");
const [selectedLanguageId, setSelectedLanguageId] = useState(defaultLanguageId);
const [selectedLanguageId, setSelectedLanguageId] = useState(
persistedLanguageId ?? defaultLanguageId,
);
const earthWidth = Math.min(width * 0.95, 520);
const earthHeight = earthWidth * (828 / 1127);

Expand Down Expand Up @@ -51,6 +58,15 @@ export default function LanguageSelectionScreen() {
[selectedLanguageId],
);

const handleConfirmLanguage = () => {
if (!selectedLanguage) {
return;
}

setSelectedLanguage(selectedLanguage.id);
router.replace("/");
};

return (
<View className="flex-1 bg-white">
<ScrollView
Expand Down Expand Up @@ -133,6 +149,8 @@ export default function LanguageSelectionScreen() {
<Pressable
accessibilityLabel={`Confirm ${selectedLanguage.name}`}
className="mt-[24px] flex-row items-center justify-center gap-[12px] rounded-[26px] bg-lingua-deep-purple px-[22px] py-[18px]"
disabled={!selectedLanguage}
onPress={handleConfirmLanguage}
style={({ pressed }) => [styles.confirmButton, pressed && styles.pressed]}
>
<Ionicons name="checkmark-circle" size={26} color="#FFFFFF" />
Expand Down
Loading