docs: README.md and docs
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import AsyncStorage from "@react-native-async-storage/async-storage";
|
||||
import { Picker } from "@react-native-picker/picker";
|
||||
import * as LocalAuthentication from "expo-local-authentication";
|
||||
import * as Location from "expo-location";
|
||||
import { useRouter } from "expo-router";
|
||||
@@ -10,6 +11,7 @@ import {
|
||||
KeyboardAvoidingView,
|
||||
Platform,
|
||||
SafeAreaView,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TextInput,
|
||||
@@ -24,7 +26,12 @@ interface User {
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
residence: string;
|
||||
residenceStreet: string;
|
||||
residenceNumber: string;
|
||||
workplace: string;
|
||||
workplaceStreet: string;
|
||||
workplaceNumber: string;
|
||||
transportMode: string;
|
||||
latitude: string;
|
||||
longitude: string;
|
||||
createdAt: string;
|
||||
@@ -43,11 +50,18 @@ export default function AuthScreen() {
|
||||
const [firstName, setFirstName] = useState("");
|
||||
const [lastName, setLastName] = useState("");
|
||||
const [residence, setResidence] = useState("");
|
||||
const [residenceStreet, setResidenceStreet] = useState("");
|
||||
const [residenceNumber, setResidenceNumber] = useState("");
|
||||
const [workplace, setWorkplace] = useState("");
|
||||
const [workplaceStreet, setWorkplaceStreet] = useState("");
|
||||
const [workplaceNumber, setWorkplaceNumber] = useState("");
|
||||
const [latitude, setLatitude] = useState<string | null>(null);
|
||||
const [longitude, setLongitude] = useState<string | null>(null);
|
||||
const [biometricSupported, setBiometricSupported] = useState(false);
|
||||
const [showCalendar, setShowCalendar] = useState(false);
|
||||
const [transportMode, setTransportMode] = useState("auto");
|
||||
const [editMode, setEditMode] = useState(false);
|
||||
const [showOnlyName, setShowOnlyName] = useState(false);
|
||||
|
||||
// Database
|
||||
const [db, setDb] = useState<SQLite.SQLiteDatabase | null>(null);
|
||||
@@ -71,7 +85,12 @@ export default function AuthScreen() {
|
||||
lastName TEXT NOT NULL,
|
||||
password TEXT NOT NULL,
|
||||
residence TEXT,
|
||||
residenceStreet TEXT,
|
||||
residenceNumber TEXT,
|
||||
workplace TEXT,
|
||||
workplaceStreet TEXT,
|
||||
workplaceNumber TEXT,
|
||||
transportMode TEXT,
|
||||
latitude TEXT,
|
||||
longitude TEXT,
|
||||
createdAt TEXT NOT NULL
|
||||
@@ -104,7 +123,11 @@ export default function AuthScreen() {
|
||||
!firstName ||
|
||||
!lastName ||
|
||||
!residence ||
|
||||
!workplace
|
||||
!residenceStreet ||
|
||||
!residenceNumber ||
|
||||
!workplace ||
|
||||
!workplaceStreet ||
|
||||
!workplaceNumber
|
||||
) {
|
||||
Alert.alert("Fehler", "Bitte füllen Sie alle Felder aus.");
|
||||
return;
|
||||
@@ -125,14 +148,19 @@ export default function AuthScreen() {
|
||||
|
||||
const createdAt = new Date().toISOString();
|
||||
const result = await db.runAsync(
|
||||
"INSERT INTO users (email, firstName, lastName, password, residence, workplace, latitude, longitude, createdAt) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
"INSERT INTO users (email, firstName, lastName, password, residence, residenceStreet, residenceNumber, workplace, workplaceStreet, workplaceNumber, transportMode, latitude, longitude, createdAt) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
[
|
||||
email,
|
||||
firstName,
|
||||
lastName,
|
||||
password,
|
||||
residence,
|
||||
residenceStreet,
|
||||
residenceNumber,
|
||||
workplace,
|
||||
workplaceStreet,
|
||||
workplaceNumber,
|
||||
transportMode,
|
||||
latitude ?? "",
|
||||
longitude ?? "",
|
||||
createdAt,
|
||||
@@ -145,7 +173,12 @@ export default function AuthScreen() {
|
||||
firstName,
|
||||
lastName,
|
||||
residence,
|
||||
residenceStreet,
|
||||
residenceNumber,
|
||||
workplace,
|
||||
workplaceStreet,
|
||||
workplaceNumber,
|
||||
transportMode,
|
||||
latitude: latitude ?? "",
|
||||
longitude: longitude ?? "",
|
||||
createdAt,
|
||||
@@ -201,6 +234,11 @@ export default function AuthScreen() {
|
||||
latitude: result.latitude,
|
||||
longitude: result.longitude,
|
||||
createdAt: result.createdAt,
|
||||
residenceStreet: result.residenceStreet,
|
||||
residenceNumber: result.residenceNumber,
|
||||
workplaceStreet: result.workplaceStreet,
|
||||
workplaceNumber: result.workplaceNumber,
|
||||
transportMode: result.transportMode,
|
||||
};
|
||||
|
||||
// Save session
|
||||
@@ -245,6 +283,11 @@ export default function AuthScreen() {
|
||||
latitude: user.latitude,
|
||||
longitude: user.longitude,
|
||||
createdAt: user.createdAt,
|
||||
residenceStreet: user.residenceStreet,
|
||||
residenceNumber: user.residenceNumber,
|
||||
workplaceStreet: user.workplaceStreet,
|
||||
workplaceNumber: user.workplaceNumber,
|
||||
transportMode: user.transportMode,
|
||||
};
|
||||
|
||||
await AsyncStorage.setItem(
|
||||
@@ -300,6 +343,44 @@ export default function AuthScreen() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleSaveEdit = async () => {
|
||||
if (!currentUser || !db) return;
|
||||
await db.runAsync(
|
||||
`UPDATE users SET firstName=?, lastName=?, residence=?, residenceStreet=?, residenceNumber=?, workplace=?, workplaceStreet=?, workplaceNumber=?, transportMode=?, latitude=?, longitude=? WHERE id=?`,
|
||||
[
|
||||
firstName,
|
||||
lastName,
|
||||
residence,
|
||||
residenceStreet,
|
||||
residenceNumber,
|
||||
workplace,
|
||||
workplaceStreet,
|
||||
workplaceNumber,
|
||||
transportMode,
|
||||
latitude ?? "",
|
||||
longitude ?? "",
|
||||
currentUser.id,
|
||||
]
|
||||
);
|
||||
setEditMode(false);
|
||||
setShowOnlyName(true);
|
||||
setCurrentUser({
|
||||
...currentUser,
|
||||
firstName,
|
||||
lastName,
|
||||
residence,
|
||||
residenceStreet,
|
||||
residenceNumber,
|
||||
workplace,
|
||||
workplaceStreet,
|
||||
workplaceNumber,
|
||||
transportMode,
|
||||
latitude: latitude ?? "",
|
||||
longitude: longitude ?? "",
|
||||
});
|
||||
Alert.alert("Erfolg", "Daten gespeichert.");
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
@@ -314,33 +395,141 @@ export default function AuthScreen() {
|
||||
if (isLoggedIn && currentUser) {
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<View style={styles.welcomeContainer}>
|
||||
<Text style={styles.welcomeTitle}>Willkommen zurück!</Text>
|
||||
<Text style={styles.userName}>
|
||||
{currentUser.firstName} {currentUser.lastName}
|
||||
</Text>
|
||||
|
||||
<View style={styles.userInfo}>
|
||||
<Text style={styles.infoLabel}>E-Mail:</Text>
|
||||
<Text style={styles.infoValue}>{currentUser.email}</Text>
|
||||
|
||||
<Text style={styles.infoLabel}>Mitglied seit:</Text>
|
||||
<Text style={styles.infoValue}>
|
||||
{new Date(currentUser.createdAt).toLocaleDateString("de-DE")}
|
||||
<ScrollView
|
||||
contentContainerStyle={styles.scrollContent}
|
||||
keyboardShouldPersistTaps="handled"
|
||||
>
|
||||
<View style={styles.welcomeContainer}>
|
||||
<Text style={styles.welcomeTitle}>Willkommen zurück!</Text>
|
||||
<Text style={styles.userName}>
|
||||
{currentUser.firstName} {currentUser.lastName}
|
||||
</Text>
|
||||
<View style={styles.userInfo}>
|
||||
{showOnlyName ? (
|
||||
<></>
|
||||
) : editMode ? (
|
||||
<>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
value={firstName}
|
||||
onChangeText={setFirstName}
|
||||
placeholder="Vorname"
|
||||
/>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
value={lastName}
|
||||
onChangeText={setLastName}
|
||||
placeholder="Nachname"
|
||||
/>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
value={residenceStreet}
|
||||
onChangeText={setResidenceStreet}
|
||||
placeholder="Straße (Wohnort)"
|
||||
/>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
value={residenceNumber}
|
||||
onChangeText={setResidenceNumber}
|
||||
placeholder="Hausnummer (Wohnort)"
|
||||
/>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
value={residence}
|
||||
onChangeText={setResidence}
|
||||
placeholder="Wohnort"
|
||||
/>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
value={workplaceStreet}
|
||||
onChangeText={setWorkplaceStreet}
|
||||
placeholder="Straße (Arbeit/Schule/Uni)"
|
||||
/>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
value={workplaceNumber}
|
||||
onChangeText={setWorkplaceNumber}
|
||||
placeholder="Hausnummer (Arbeit/Schule/Uni)"
|
||||
/>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
value={workplace}
|
||||
onChangeText={setWorkplace}
|
||||
placeholder="Arbeitsplatz / Uni / Schule"
|
||||
/>
|
||||
<View style={{ marginBottom: 15 }}>
|
||||
<Text style={{ marginBottom: 5, fontWeight: "600" }}>
|
||||
Verkehrsmittel
|
||||
</Text>
|
||||
<Picker
|
||||
selectedValue={transportMode}
|
||||
onValueChange={setTransportMode}
|
||||
style={{ backgroundColor: "#fff" }}
|
||||
>
|
||||
<Picker.Item label="Auto" value="auto" />
|
||||
<Picker.Item label="Zug" value="zug" />
|
||||
<Picker.Item label="Bus" value="bus" />
|
||||
<Picker.Item label="Fahrrad" value="fahrrad" />
|
||||
<Picker.Item label="Zu Fuß" value="zufuss" />
|
||||
</Picker>
|
||||
</View>
|
||||
<TouchableOpacity
|
||||
style={[styles.submitButton, { marginBottom: 10 }]}
|
||||
onPress={handleSaveEdit}
|
||||
>
|
||||
<Text style={styles.submitButtonText}>Speichern</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={styles.logoutButton}
|
||||
onPress={() => setEditMode(false)}
|
||||
>
|
||||
<Text style={styles.logoutButtonText}>Abbrechen</Text>
|
||||
</TouchableOpacity>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Text style={styles.infoLabel}>E-Mail:</Text>
|
||||
<Text style={styles.infoValue}>{currentUser.email}</Text>
|
||||
<Text style={styles.infoLabel}>Wohnort:</Text>
|
||||
<Text style={styles.infoValue}>
|
||||
{currentUser.residenceStreet} {currentUser.residenceNumber},{" "}
|
||||
{currentUser.residence}
|
||||
</Text>
|
||||
<Text style={styles.infoLabel}>Arbeit/Schule/Uni:</Text>
|
||||
<Text style={styles.infoValue}>
|
||||
{currentUser.workplaceStreet} {currentUser.workplaceNumber},{" "}
|
||||
{currentUser.workplace}
|
||||
</Text>
|
||||
<Text style={styles.infoLabel}>Verkehrsmittel:</Text>
|
||||
<Text style={styles.infoValue}>
|
||||
{currentUser.transportMode}
|
||||
</Text>
|
||||
<TouchableOpacity
|
||||
style={[
|
||||
styles.submitButton,
|
||||
{ marginTop: 10, marginBottom: 10 },
|
||||
]}
|
||||
onPress={() => setEditMode(true)}
|
||||
>
|
||||
<Text style={styles.submitButtonText}>Bearbeiten</Text>
|
||||
</TouchableOpacity>
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
<TouchableOpacity
|
||||
style={styles.logoutButton}
|
||||
onPress={handleLogout}
|
||||
>
|
||||
<Text style={styles.logoutButtonText}>Abmelden</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={[styles.submitButton, { marginTop: 20 }]}
|
||||
onPress={() => router.push("/calendar")}
|
||||
>
|
||||
<Text style={styles.submitButtonText}>Zum Kalender</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<TouchableOpacity style={styles.logoutButton} onPress={handleLogout}>
|
||||
<Text style={styles.logoutButtonText}>Abmelden</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity
|
||||
style={[styles.submitButton, { marginTop: 20 }]}
|
||||
onPress={() => router.push("/calendar")}
|
||||
>
|
||||
<Text style={styles.submitButtonText}>Zum Kalender</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
@@ -351,111 +540,156 @@ export default function AuthScreen() {
|
||||
style={styles.keyboardView}
|
||||
behavior={Platform.OS === "ios" ? "padding" : "height"}
|
||||
>
|
||||
<View style={styles.authContainer}>
|
||||
<Text style={styles.title}>
|
||||
{authMode === "login" ? "Anmelden" : "Registrieren"}
|
||||
</Text>
|
||||
<ScrollView
|
||||
contentContainerStyle={styles.scrollContent}
|
||||
keyboardShouldPersistTaps="handled"
|
||||
>
|
||||
<View style={styles.authContainer}>
|
||||
<Text style={styles.title}>
|
||||
{authMode === "login" ? "Anmelden" : "Registrieren"}
|
||||
</Text>
|
||||
|
||||
{authMode === "register" && (
|
||||
<>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="Vorname"
|
||||
value={firstName}
|
||||
onChangeText={setFirstName}
|
||||
autoCapitalize="words"
|
||||
/>
|
||||
{authMode === "register" && (
|
||||
<>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="Vorname"
|
||||
value={firstName}
|
||||
onChangeText={setFirstName}
|
||||
autoCapitalize="words"
|
||||
/>
|
||||
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="Nachname"
|
||||
value={lastName}
|
||||
onChangeText={setLastName}
|
||||
autoCapitalize="words"
|
||||
/>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="Nachname"
|
||||
value={lastName}
|
||||
onChangeText={setLastName}
|
||||
autoCapitalize="words"
|
||||
/>
|
||||
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="Wohnort"
|
||||
value={residence}
|
||||
onChangeText={setResidence}
|
||||
/>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="Arbeitsplatz / Uni / Schule"
|
||||
value={workplace}
|
||||
onChangeText={setWorkplace}
|
||||
/>
|
||||
<TouchableOpacity
|
||||
style={[
|
||||
styles.submitButton,
|
||||
{ backgroundColor: "#34C759", marginBottom: 10 },
|
||||
]}
|
||||
onPress={handleUseLocation}
|
||||
>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="Straße (Wohnort)"
|
||||
value={residenceStreet}
|
||||
onChangeText={setResidenceStreet}
|
||||
/>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="Hausnummer (Wohnort)"
|
||||
value={residenceNumber}
|
||||
onChangeText={setResidenceNumber}
|
||||
/>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="Wohnort"
|
||||
value={residence}
|
||||
onChangeText={setResidence}
|
||||
/>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="Straße (Arbeit/Schule/Uni)"
|
||||
value={workplaceStreet}
|
||||
onChangeText={setWorkplaceStreet}
|
||||
/>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="Hausnummer (Arbeit/Schule/Uni)"
|
||||
value={workplaceNumber}
|
||||
onChangeText={setWorkplaceNumber}
|
||||
/>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="Arbeitsplatz / Uni / Schule"
|
||||
value={workplace}
|
||||
onChangeText={setWorkplace}
|
||||
/>
|
||||
<View style={{ marginBottom: 15 }}>
|
||||
<Text style={{ marginBottom: 5, fontWeight: "600" }}>
|
||||
Verkehrsmittel
|
||||
</Text>
|
||||
<Picker
|
||||
selectedValue={transportMode}
|
||||
onValueChange={setTransportMode}
|
||||
style={{ backgroundColor: "#fff" }}
|
||||
>
|
||||
<Picker.Item label="Auto" value="auto" />
|
||||
<Picker.Item label="Zug" value="zug" />
|
||||
<Picker.Item label="Bus" value="bus" />
|
||||
<Picker.Item label="Fahrrad" value="fahrrad" />
|
||||
<Picker.Item label="Zu Fuß" value="zufuss" />
|
||||
</Picker>
|
||||
</View>
|
||||
<TouchableOpacity
|
||||
style={[
|
||||
styles.submitButton,
|
||||
{ backgroundColor: "#34C759", marginBottom: 10 },
|
||||
]}
|
||||
onPress={handleUseLocation}
|
||||
>
|
||||
<Text style={styles.submitButtonText}>
|
||||
Aktuellen Standort verwenden
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</>
|
||||
)}
|
||||
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="E-Mail"
|
||||
value={email}
|
||||
onChangeText={setEmail}
|
||||
keyboardType="email-address"
|
||||
autoCapitalize="none"
|
||||
/>
|
||||
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="Passwort"
|
||||
value={password}
|
||||
onChangeText={setPassword}
|
||||
secureTextEntry
|
||||
autoCapitalize="none"
|
||||
/>
|
||||
|
||||
<TouchableOpacity
|
||||
style={styles.submitButton}
|
||||
onPress={authMode === "login" ? handleLogin : handleRegister}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? (
|
||||
<ActivityIndicator color="white" />
|
||||
) : (
|
||||
<Text style={styles.submitButtonText}>
|
||||
Aktuellen Standort verwenden
|
||||
{authMode === "login" ? "Anmelden" : "Registrieren"}
|
||||
</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
|
||||
{biometricSupported && authMode === "login" && (
|
||||
<TouchableOpacity
|
||||
style={styles.biometricButton}
|
||||
onPress={handleBiometricAuth}
|
||||
>
|
||||
<Text style={styles.biometricButtonText}>
|
||||
Mit Face ID / Touch ID anmelden
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</>
|
||||
)}
|
||||
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="E-Mail"
|
||||
value={email}
|
||||
onChangeText={setEmail}
|
||||
keyboardType="email-address"
|
||||
autoCapitalize="none"
|
||||
/>
|
||||
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="Passwort"
|
||||
value={password}
|
||||
onChangeText={setPassword}
|
||||
secureTextEntry
|
||||
autoCapitalize="none"
|
||||
/>
|
||||
|
||||
<TouchableOpacity
|
||||
style={styles.submitButton}
|
||||
onPress={authMode === "login" ? handleLogin : handleRegister}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? (
|
||||
<ActivityIndicator color="white" />
|
||||
) : (
|
||||
<Text style={styles.submitButtonText}>
|
||||
{authMode === "login" ? "Anmelden" : "Registrieren"}
|
||||
</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
|
||||
{biometricSupported && authMode === "login" && (
|
||||
<TouchableOpacity
|
||||
style={styles.biometricButton}
|
||||
onPress={handleBiometricAuth}
|
||||
style={styles.switchButton}
|
||||
onPress={() =>
|
||||
setAuthMode(authMode === "login" ? "register" : "login")
|
||||
}
|
||||
>
|
||||
<Text style={styles.biometricButtonText}>
|
||||
Mit Face ID / Touch ID anmelden
|
||||
<Text style={styles.switchButtonText}>
|
||||
{authMode === "login"
|
||||
? "Noch kein Konto? Registrieren"
|
||||
: "Bereits ein Konto? Anmelden"}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
|
||||
<TouchableOpacity
|
||||
style={styles.switchButton}
|
||||
onPress={() =>
|
||||
setAuthMode(authMode === "login" ? "register" : "login")
|
||||
}
|
||||
>
|
||||
<Text style={styles.switchButtonText}>
|
||||
{authMode === "login"
|
||||
? "Noch kein Konto? Registrieren"
|
||||
: "Bereits ein Konto? Anmelden"}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</KeyboardAvoidingView>
|
||||
</SafeAreaView>
|
||||
);
|
||||
@@ -469,10 +703,16 @@ const styles = StyleSheet.create({
|
||||
keyboardView: {
|
||||
flex: 1,
|
||||
},
|
||||
scrollContent: {
|
||||
flexGrow: 1,
|
||||
justifyContent: "center",
|
||||
paddingVertical: 30,
|
||||
},
|
||||
authContainer: {
|
||||
flex: 1,
|
||||
justifyContent: "center",
|
||||
paddingHorizontal: 30,
|
||||
paddingBottom: 30,
|
||||
},
|
||||
loadingContainer: {
|
||||
flex: 1,
|
||||
|
||||
Reference in New Issue
Block a user