modules/frontend/Write-Frontend-RN-Auth.ps1

param(
    [string]$ProjectName,
    [string]$OutputPath,
    [string]$Platform,
    [string]$Language = "tr"
)

. (Join-Path (Split-Path $MyInvocation.MyCommand.Path) "..\core\Utils.ps1")
. (Join-Path (Split-Path $MyInvocation.MyCommand.Path) "..\core\Get-Locale.ps1")
$L = Get-Locale -Language $Language

$MobilePath = Join-Path $OutputPath "$ProjectName-mobile"
$AppPath = Join-Path $MobilePath "app"
$ContextPath = Join-Path $MobilePath "context"

if (-not $Global:DryRun) {
    New-Item -ItemType Directory -Path $ContextPath -Force | Out-Null
}

# 1. Write context/AuthContext.tsx
$authContext = @'
import React, { createContext, useState, useContext, useEffect } from 'react';
import * as SecureStore from 'expo-secure-store';
import { api } from '../services/api';
import { useRouter } from 'expo-router';
 
interface AuthContextType {
  token: string | null;
  username: string | null;
  loading: boolean;
  login: (u: string, p: string) => Promise<void>;
  logout: () => Promise<void>;
}
 
const AuthContext = createContext<AuthContextType | null>(null);
 
export function AuthProvider({ children }: { children: React.ReactNode }) {
  const [token, setToken] = useState<string | null>(null);
  const [username, setUsername] = useState<string | null>(null);
  const [loading, setLoading] = useState(true);
  const router = useRouter();
 
  useEffect(() => {
    async function loadStorage() {
      try {
        const savedToken = await SecureStore.getItemAsync('token');
        const savedUser = await SecureStore.getItemAsync('username');
        if (savedToken && savedUser) {
          setToken(savedToken);
          setUsername(savedUser);
          api.setToken(savedToken);
        }
      } catch (e) {
        console.log(e);
      } finally {
        setLoading(false);
      }
    }
    loadStorage();
  }, []);
 
  const login = async (u: string, p: string) => {
    const res = await api.request('/auth/login', {
      method: 'POST',
      body: JSON.stringify({ username: u, password: p }),
    });
    const { token: jwtToken, username: user } = res;
    await SecureStore.setItemAsync('token', jwtToken);
    await SecureStore.setItemAsync('username', user);
    setToken(jwtToken);
    setUsername(user);
    api.setToken(jwtToken);
    router.replace('/(tabs)');
  };
 
  const logout = async () => {
    await SecureStore.deleteItemAsync('token');
    await SecureStore.deleteItemAsync('username');
    setToken(null);
    setUsername(null);
    api.setToken(null);
    router.replace('/(auth)/login');
  };
 
  return (
    <AuthContext.Provider value={{ token, username, loading, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
}
 
export function useAuth() {
  const context = useContext(AuthContext);
  if (!context) throw new Error('useAuth must be used inside AuthProvider');
  return context;
}
'@

Write-CoreFile (Join-Path $ContextPath "AuthContext.tsx") $authContext

# 2. Write app/(auth)/login.tsx (UI)
$loginScreen = @"
import { View, Text, TextInput, StyleSheet, TouchableOpacity, ActivityIndicator } from 'react-native';
import { useState } from 'react';
import { useAuth } from '../../context/AuthContext';
 
export default function LoginScreen() {
  const { login } = useAuth();
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [error, setError] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);
 
  const handleLogin = async () => {
    if (!username.trim() || !password.trim()) {
      setError('Please fill all fields');
      return;
    }
    setError(null);
    setLoading(true);
    try {
      await login(username, password);
    } catch (err: any) {
      setError(err.message || '$($L.uiLoginFailed)');
    } finally {
      setLoading(false);
    }
  };
 
  return (
    <View style={styles.container}>
      <View style={styles.card}>
        <Text style={styles.title}>$ProjectName</Text>
        <Text style={styles.subtitle}>$($L.uiLoginSubtitle)</Text>
 
        {error && <Text style={styles.error}>{error}</Text>}
 
        <Text style={styles.label}>$($L.uiUsername)</Text>
        <TextInput
          style={styles.input}
          value={username}
          onChangeText={setUsername}
          autoCapitalize="none"
          placeholder="admin"
          placeholderTextColor="#666666"
        />
 
        <Text style={styles.label}>$($L.uiPassword)</Text>
        <TextInput
          style={styles.input}
          value={password}
          onChangeText={setPassword}
          secureTextEntry
          autoCapitalize="none"
          placeholder="********"
          placeholderTextColor="#666666"
        />
 
        <TouchableOpacity
          style={[styles.button, loading && styles.disabled]}
          onPress={handleLogin}
          disabled={loading}
        >
          {loading ? (
            <ActivityIndicator color="#ffffff" />
          ) : (
            <Text style={styles.buttonText}>$($L.uiLogin)</Text>
          )}
        </TouchableOpacity>
      </View>
    </View>
  );
}
 
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#121212',
    justifyContent: 'center',
    padding: 20,
  },
  card: {
    backgroundColor: '#1e1e1e',
    padding: 24,
    borderRadius: 12,
    borderWidth: 1,
    borderColor: '#333333',
  },
  title: {
    fontSize: 28,
    fontWeight: 'bold',
    color: '#ffffff',
    textAlign: 'center',
  },
  subtitle: {
    fontSize: 14,
    color: '#888888',
    textAlign: 'center',
    marginBottom: 24,
    marginTop: 4,
  },
  label: {
    color: '#ffffff',
    fontSize: 14,
    fontWeight: '600',
    marginBottom: 8,
    marginTop: 12,
  },
  input: {
    backgroundColor: '#2a2a2a',
    color: '#ffffff',
    padding: 12,
    borderRadius: 8,
    fontSize: 16,
    borderWidth: 1,
    borderColor: '#444444',
  },
  error: {
    color: '#ef4444',
    textAlign: 'center',
    marginBottom: 16,
    fontWeight: '600',
  },
  button: {
    backgroundColor: '#3b82f6',
    padding: 14,
    borderRadius: 8,
    alignItems: 'center',
    marginTop: 24,
  },
  buttonText: {
    color: '#ffffff',
    fontWeight: 'bold',
    fontSize: 16,
  },
  disabled: {
    opacity: 0.7,
  },
});
"@

Write-CoreFile (Join-Path $AppPath "(auth)\login.tsx") $loginScreen