This commit is contained in:
jjbrunton committed 2025-12-30 11:09:03 +00:00
1 parent b10eae1bf3
commit a15089f607
20 files changed
+3566 -3654

No files matched your search

+1 -1
View File
@@ -2,7 +2,7 @@ EXPO_PUBLIC_SUPABASE_URL=your_supabase_url
EXPO_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
# Sentry error tracking (get DSN from https://sentry.io)
EXPO_PUBLIC_SENTRY_DSN=https://03a91f8a1b1ecdce2d5f38a4c23ca9d5@o4510613894070272.ingest.de.sentry.io/4510613896560720
EXPO_PUBLIC_SENTRY_DSN=https://your-public-key@your-org.ingest.sentry.io/your-project-id
# RevenueCat (for Apple subscriptions)
# Get your API key from https://app.revenuecat.com
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
+3 -1
View File
@@ -63,7 +63,9 @@
"organization": "molten-prints",
"project": "sauci"
}
]
],
"@sentry/react-native",
"expo-font"
],
"experiments": {
"typedRoutes": true
+5 -3
View File
@@ -85,8 +85,10 @@ export default function PairingScreen() {
};
const handleJoinCouple = async () => {
if (inviteCode.length < 8) {
Alert.alert("Error", "Please enter a valid invite code");
// Validate invite code format (8 alphanumeric characters)
const sanitizedCode = inviteCode.trim().toUpperCase();
if (!/^[A-Z0-9]{8}$/.test(sanitizedCode)) {
Alert.alert("Error", "Please enter a valid 8-character invite code");
return;
}
@@ -100,7 +102,7 @@ export default function PairingScreen() {
const { data, error } = await supabase.functions.invoke("manage-couple", {
method: "POST",
body: { invite_code: inviteCode },
body: { invite_code: sanitizedCode },
});
if (error) throw error;
+2 -2
View File
@@ -190,8 +190,8 @@ export default function LoginScreen() {
showError("Please enter your password");
return;
}
if (isSignUp && password.length < 6) {
showError("Password must be at least 6 characters");
if (isSignUp && password.length < 8) {
showError("Password must be at least 8 characters");
return;
}
+67 -10
View File
@@ -45,16 +45,52 @@ export default function PackDetailsScreen() {
{item.partner_text && (
<Text style={styles.partnerText}>Partner role: {item.partner_text}</Text>
)}
<View style={styles.intensityContainer}>
{[...Array(5)].map((_, index) => (
<Ionicons
key={index}
name="flame"
size={12}
color={index < item.intensity ? "#e94560" : "#333"}
style={{ marginRight: 2 }}
/>
))}
<View style={styles.footerContainer}>
<View style={styles.intensityContainer}>
{[...Array(5)].map((_, index) => (
<Ionicons
key={index}
name="flame"
size={12}
color={index < item.intensity ? "#e94560" : "#333"}
style={{ marginRight: 2 }}
/>
))}
</View>
{item.allowed_couple_genders && item.allowed_couple_genders.length > 0 ? (
<View style={styles.targetsContainer}>
{item.allowed_couple_genders.map((g) => {
const icons = [];
if (g === 'male+male') {
icons.push('male', 'male');
} else if (g === 'female+female') {
icons.push('female', 'female');
} else {
icons.push('male', 'female');
}
return (
<View key={g} style={styles.targetBadge}>
{icons.map((icon, i) => (
<Ionicons
key={i}
name={icon as any}
size={10}
color="#ccc"
style={i > 0 ? { marginLeft: 2 } : {}}
/>
))}
</View>
);
})}
</View>
) : (
<View style={styles.targetsContainer}>
<View style={styles.targetBadge}>
<Ionicons name="people" size={10} color="#ccc" />
</View>
</View>
)}
</View>
</View>
);
@@ -188,4 +224,25 @@ const styles = StyleSheet.create({
fontStyle: "italic",
marginBottom: 8,
},
footerContainer: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginTop: 8,
},
targetsContainer: {
flexDirection: 'row',
flexWrap: 'wrap',
gap: 4,
},
targetBadge: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: 'rgba(255, 255, 255, 0.1)',
paddingHorizontal: 6,
paddingVertical: 2,
borderRadius: 4,
borderWidth: 1,
borderColor: 'rgba(255, 255, 255, 0.2)',
},
});
+206 -446
View File
File diff suppressed because it is too large. Load diff
+8 -7
View File
@@ -13,12 +13,12 @@
},
"dependencies": {
"@expo/ngrok": "^4.1.0",
"@expo/vector-icons": "^14.0.0",
"@react-native-async-storage/async-storage": "^2.2.0",
"@expo/vector-icons": "~14.0.4",
"@react-native-async-storage/async-storage": "1.23.1",
"@react-navigation/bottom-tabs": "^7.0.0",
"@react-navigation/native": "^7.0.0",
"@react-navigation/native-stack": "^7.0.0",
"@sentry/react-native": "^7.8.0",
"@sentry/react-native": "~6.10.0",
"@supabase/supabase-js": "^2.39.0",
"@tanstack/react-query": "^5.17.0",
"base64-arraybuffer": "^1.0.2",
@@ -29,25 +29,26 @@
"expo-constants": "~17.0.0",
"expo-dev-client": "~5.0.20",
"expo-file-system": "~18.0.12",
"expo-font": "~13.0.4",
"expo-haptics": "~14.0.1",
"expo-image-picker": "~16.0.6",
"expo-linear-gradient": "~14.0.2",
"expo-linking": "~7.0.0",
"expo-local-authentication": "^17.0.8",
"expo-local-authentication": "~15.0.2",
"expo-notifications": "~0.29.0",
"expo-router": "~4.0.0",
"expo-secure-store": "~14.0.0",
"expo-status-bar": "~2.0.0",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-native": "0.76.5",
"react-native": "0.76.9",
"react-native-gesture-handler": "~2.20.0",
"react-native-purchases": "^9.6.12",
"react-native-reanimated": "~3.16.0",
"react-native-safe-area-context": "4.12.0",
"react-native-screens": "~4.1.0",
"react-native-screens": "~4.4.0",
"react-native-url-polyfill": "^2.0.0",
"react-native-web": "^0.21.2",
"react-native-web": "~0.19.13",
"zustand": "^4.4.7"
},
"devDependencies": {
-3
View File
@@ -50,9 +50,6 @@ const ExpoStorageAdapter = {
const supabaseUrl = process.env.EXPO_PUBLIC_SUPABASE_URL!;
const supabaseAnonKey = process.env.EXPO_PUBLIC_SUPABASE_ANON_KEY!;
// DEBUG: Log which key is being used
console.log("DEBUG - Anon key preview:", supabaseAnonKey?.substring(0, 30) + "...");
export const supabase = createClient(supabaseUrl, supabaseAnonKey, {
auth: {
storage: ExpoStorageAdapter,
+1
View File
@@ -56,6 +56,7 @@ export interface Question {
text: string;
partner_text?: string | null;
intensity: 1 | 2 | 3 | 4 | 5;
allowed_couple_genders?: string[] | null;
created_at: string;
}