Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
e7fc232
Updated LoginScreen and Auth and AppNavigator
Tawanda21 May 7, 2025
8dd2149
new go maps api key
Modise-Kgosi May 7, 2025
9f83acd
hoe this doesnt fuck everything up
Modise-Kgosi May 7, 2025
8959260
meh
Tawanda21 May 8, 2025
e72ad5d
Logout button, bus stop search bar, and map view
Tawanda21 May 8, 2025
109ea49
no changes made, just tryna see if it will pull if i commit a comment
Modise-Kgosi May 8, 2025
22f0abb
Predictive searching
Modise-Kgosi May 8, 2025
d5b1da4
user authencation functionality
Modise-Kgosi May 8, 2025
3a6d9d1
just some dependencies
Modise-Kgosi May 8, 2025
d3225ab
google sign in functionality added
Modise-Kgosi May 8, 2025
7b75aaa
just more features
Modise-Kgosi May 8, 2025
0c641ab
sign up
Modise-Kgosi May 9, 2025
9f85cbe
major commit with a bunch of functionality, its 5am i am tired, hope …
Modise-Kgosi May 28, 2025
249f2dc
new commit
Modise-Kgosi May 28, 2025
5a300d4
icon
Modise-Kgosi May 28, 2025
418e299
29MAY
Tawanda21 May 29, 2025
02a6ca7
removing welcome on homescreen
Modise-Kgosi May 30, 2025
462bd5c
recent commit to adress routing error
Modise-Kgosi May 30, 2025
f1f5604
Added a CustomPopup
Tawanda21 May 30, 2025
77c5ca2
Merge branch '28MAY' of https://github.com/Tawanda21/LoetoLinkv2 into…
Tawanda21 May 30, 2025
bf69e6e
use my location fix
Modise-Kgosi May 30, 2025
b3d8fab
a few features
Modise-Kgosi May 30, 2025
8ee1de1
hamburger menu
Modise-Kgosi May 30, 2025
9dd27ab
show which combi customer is riding in show stop list
Modise-Kgosi May 30, 2025
48190c7
update the style for stop list modal, created a
Tawanda21 May 30, 2025
d7d117d
Fixed the glirching serach functionality
Tawanda21 May 31, 2025
65a7857
fixed bugs
Modise-Kgosi May 31, 2025
4fa930a
new changes
Modise-Kgosi May 31, 2025
c7c34a7
new api key=AlzaSy0csWCFtrxT-TmMw4adcHN41jNcy0mdvdf
Modise-Kgosi May 31, 2025
f9832ca
Updated BusStopScreen
Tawanda21 May 31, 2025
8bdefbe
Updated MapViewScreen and removed TransportInfo
Tawanda21 May 31, 2025
3476fa8
favorites creen logic
Modise-Kgosi May 31, 2025
758d4bf
favorites background change
Modise-Kgosi May 31, 2025
c4458af
profilescreen update
Modise-Kgosi May 31, 2025
0f386c4
Updated FavoritesScreen
Tawanda21 May 31, 2025
4ab700e
Merge branch '28MAY' of https://github.com/Tawanda21/LoetoLinkv2 into…
Tawanda21 May 31, 2025
85f25c9
reset password ui, that doesnt work
Modise-Kgosi Jun 1, 2025
bbfd33e
route color changing, final commit
Modise-Kgosi Jun 1, 2025
192481a
Added places to visit and screen names
Tawanda21 Jun 1, 2025
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
9 changes: 3 additions & 6 deletions App.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import React from 'react';
import { StatusBar, SafeAreaView } from 'react-native';
import AppNavigator from './navigation/AppNavigator';
import Auth from './components/Auth';
import { FavoriteProvider } from './contexts/FavoriteContext';

export default function App() {
return (
<>
<FavoriteProvider>
<StatusBar barStyle="dark-content" />
<SafeAreaView>
<Auth />
</SafeAreaView>
<AppNavigator />
</>
</FavoriteProvider>
);
}
12 changes: 6 additions & 6 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
"slug": "LoetoLink",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/icon.png",
"icon": "./assets/logo.jpg",
"userInterfaceStyle": "light",
"newArchEnabled": true,
"splash": {
"image": "./assets/splash-icon.png",
"image": "./assets/logo.jpg",
"resizeMode": "contain",
"backgroundColor": "#ffffff",
"updates": {
Expand All @@ -21,17 +21,17 @@
"android": {
"config": {
"googleMaps": {
"apiKey": "AlzaSya0Ll6laKMO06oO9lBmTdqQ6P_4Qo1_fEJ"
"apiKey": "AlzaSy0csWCFtrxT-TmMw4adcHN41jNcy0mdvdf"
}
},
"adaptiveIcon": {
"foregroundImage": "./assets/adaptive-icon.png",
"foregroundImage": "./assets/logo.jpg",
"backgroundColor": "#ffffff"
},
"package": "com.anonymous.LoetoLink"
},
"web": {
"favicon": "./assets/favicon.png"
"favicon": "./assets/logo.jpg"
}
}
}
}
Binary file added assets/avatar.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/background.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/background2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 4 additions & 37 deletions components/Auth.js
Original file line number Diff line number Diff line change
@@ -1,43 +1,10 @@
import React, { useState } from 'react';
import { Alert, StyleSheet, View } from 'react-native';
import { supabase } from '../lib/supabase'; // Adjust the import path as necessary
import { Button, Input } from '@rneui/themed';

export default function Auth() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');

const signInWithEmail = async () => {
const { error } = await supabase.auth.signInWithPassword({ email, password });
if (error) Alert.alert(error.message);
};

const signUpWithEmail = async () => {
const { error } = await supabase.auth.signUp({ email, password });
if (error) Alert.alert(error.message);
};
import React from 'react';
import { View, StyleSheet } from 'react-native';

export default function Auth({ navigation }) {
return (
<View style={styles.container}>
<Input
label="Email"
leftIcon={{ type: 'font-awesome', name: 'envelope' }}
onChangeText={setEmail}
value={email}
placeholder="email@address.com"
autoCapitalize="none"
/>
<Input
label="Password"
leftIcon={{ type: 'font-awesome', name: 'lock' }}
onChangeText={setPassword}
value={password}
secureTextEntry
placeholder="Password"
autoCapitalize="none"
/>
<Button title="Sign In" onPress={signInWithEmail} />
<Button title="Sign Up" onPress={signUpWithEmail} />

</View>
);
}
Expand Down
106 changes: 106 additions & 0 deletions components/CustomPopup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import React, { useEffect, useRef } from 'react';
import { Modal, View, Text, StyleSheet, TouchableOpacity, Animated, TouchableWithoutFeedback } from 'react-native';

const CustomPopup = ({
visible,
title,
message,
onClose,
confirmText = "OK",
onConfirm,
children,
}) => {
const scaleAnim = useRef(new Animated.Value(0.8)).current;
const opacityAnim = useRef(new Animated.Value(0)).current;

useEffect(() => {
if (visible) {
Animated.parallel([
Animated.spring(scaleAnim, { toValue: 1, useNativeDriver: true }),
Animated.timing(opacityAnim, { toValue: 1, duration: 200, useNativeDriver: true }),
]).start();
} else {
scaleAnim.setValue(0.8);
opacityAnim.setValue(0);
}
}, [visible]);

return (
<Modal transparent visible={visible} animationType="none">
<TouchableWithoutFeedback onPress={onClose}>
<View style={styles.overlay}>
<TouchableWithoutFeedback>
<Animated.View style={[styles.popup, { transform: [{ scale: scaleAnim }], opacity: opacityAnim }]}>
{title ? <Text style={styles.title}>{title}</Text> : null}
{message ? <Text style={styles.message}>{message}</Text> : null}
{children}
{!children && (
<TouchableOpacity style={styles.button} onPress={onConfirm || onClose}>
<Text style={styles.buttonText}>{confirmText}</Text>
</TouchableOpacity>
)}
</Animated.View>
</TouchableWithoutFeedback>
</View>
</TouchableWithoutFeedback>
</Modal>
);
};

const styles = StyleSheet.create({
overlay: {
flex: 1,
backgroundColor: 'rgba(0,0,0,0.18)',
justifyContent: 'center',
alignItems: 'center',
},
popup: {
width: 300,
backgroundColor: '#fff',
borderRadius: 14,
paddingVertical: 22,
paddingHorizontal: 14,
alignItems: 'center',
shadowColor: '#000',
shadowOpacity: 0.10,
shadowRadius: 10,
shadowOffset: { width: 0, height: 4 },
elevation: 6,
},
title: {
fontSize: 18,
fontWeight: '600',
marginBottom: 6,
color: '#222',
textAlign: 'center',
backgroundColor: 'transparent',
padding: 0,
},
message: {
fontSize: 15,
color: '#444',
marginBottom: 14,
textAlign: 'center',
backgroundColor: 'transparent',
padding: 0,
},
button: {
backgroundColor: '#418EDA',
borderRadius: 100,
paddingVertical: 9,
paddingHorizontal: 32,
alignItems: 'center',
marginTop: 8,
shadowColor: '#418EDA',
shadowOpacity: 0.13,
shadowRadius: 6,
elevation: 3,
},
buttonText: {
color: '#fff',
fontWeight: 'bold',
fontSize: 15,
},
});

export default CustomPopup;
145 changes: 145 additions & 0 deletions components/StopListComponent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import React from 'react';
import { View, Text, StyleSheet, FlatList } from 'react-native';
import { Ionicons } from '@expo/vector-icons';

const formatDistance = (meters) => {
if (meters == null) return '';
if (meters < 1000) return `${meters} m`;
return `${(meters / 1000).toFixed(1)} km`;
};

const StopListComponent = ({ routeWaypoints }) => {
if (!routeWaypoints || routeWaypoints.length === 0) {
return <Text style={{ textAlign: 'center', color: '#888' }}>No stops available.</Text>;
}

return (
<FlatList
data={routeWaypoints}
keyExtractor={(item, idx) => idx.toString()}
renderItem={({ item, index }) => (
<View style={styles.row}>
{/* Timeline */}
<View style={styles.timeline}>
{/* Top line */}
{index !== 0 && <View style={styles.line} />}
{/* Circle */}
<View
style={[
styles.circle,
index === 0 ? styles.circleActive : null,
index === routeWaypoints.length - 1 ? styles.circleTerminal : null,
]}
/>
{/* Bottom line */}
{index !== routeWaypoints.length - 1 && <View style={styles.line} />}
</View>
{/* Stop info */}
<View style={styles.info}>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<Text style={styles.time}>{item.time || '--:--'}</Text>
{item.eta && (
<Text style={styles.eta}> ({item.eta})</Text>
)}
{item.delay && (
<Text style={styles.delay}> +{item.delay} min</Text>
)}
</View>
<Text style={styles.name}>{item.name}</Text>
{item.platform && (
<Text style={styles.platform}>Platform: {item.platform}</Text>
)}
{item.distance != null && (
<Text style={styles.distance}>
<Ionicons name="navigate" size={14} color="#018abe" /> {formatDistance(item.distance)} from you
</Text>
)}
</View>
</View>
)}
/>
);
};

const styles = StyleSheet.create({
row: {
flexDirection: 'row',
alignItems: 'flex-start',
marginBottom: 32, // Increased spacing between stops
minHeight: 56, // Increased minimum height for each row
},
timeline: {
width: 40, // Increased width for timeline area
alignItems: 'center',
position: 'relative',
},
line: {
width: 3, // Thicker line
height: 28, // Longer line for more spacing
backgroundColor: '#018abe',
position: 'absolute',
left: 18.5, // Centered for bigger circle
zIndex: 0,
},
circle: {
width: 28, // Larger icon
height: 28,
borderRadius: 14,
backgroundColor: '#fff',
borderWidth: 5,
borderColor: '#018abe',
marginVertical: 0,
zIndex: 1,
marginTop: 0,
marginBottom: 0,
},
circleActive: {
backgroundColor: '#018abe',
},
circleTerminal: {
borderColor: '#43a047',
},
info: {
marginLeft: 18, // More space between icon and text
flex: 1,
borderBottomWidth: 1,
borderBottomColor: '#f0f0f0',
paddingBottom: 10,
},
time: {
fontSize: 18,
fontWeight: 'bold',
color: '#018abe',
},
eta: {
fontSize: 15,
color: '#888',
marginLeft: 4,
},
delay: {
fontSize: 15,
color: '#d32f2f',
marginLeft: 4,
fontWeight: 'bold',
},
name: {
fontSize: 18,
fontWeight: '500',
color: '#222',
marginTop: 4,
},
platform: {
fontSize: 14,
color: '#888',
marginTop: 2,
},
distance: {
fontSize: 13,
color: '#018abe',
marginTop: 2,
flexDirection: 'row',
alignItems: 'center',
},
});

export default StopListComponent;
Loading