Skip to content
Open
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
109 changes: 88 additions & 21 deletions src/components/mobile/MobileProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { LinearGradient } from 'expo-linear-gradient';
import {
BookOpen,
Camera,
ChevronDown,
ChevronUp,
Clock,
Edit3,
Globe,
Expand All @@ -18,12 +20,21 @@ import {
import React, { useState } from 'react';
import {
ActivityIndicator,
Animated,
LayoutAnimation,
Platform,
SafeAreaView,
ScrollView,
StyleSheet,
TouchableOpacity,
UIManager,
View,
} from 'react-native';

// Enable LayoutAnimation on Android
if (Platform.OS === 'android' && UIManager.setLayoutAnimationEnabledExperimental) {
UIManager.setLayoutAnimationEnabledExperimental(true);
}
import { AppText as Text } from '../common/AppText';
import { CachedImage } from '../ui/CachedImage';
import { Skeleton } from '../ui/Skeleton';
Expand Down Expand Up @@ -290,14 +301,16 @@ export const MobileProfile: React.FC<MobileProfileProps> = ({
const [isEditing, setIsEditing] = useState(false);
const [isCameraVisible, setIsCameraVisible] = useState(false);
const [isSaving, setIsSaving] = useState(false);
// Progressive disclosure: advanced profile fields collapsed by default
const [showAdvancedFields, setShowAdvancedFields] = useState(false);

// Edit form state
const [editName, setEditName] = useState('');
const [editBio, setEditBio] = useState('');
const [editEmail, setEditEmail] = useState('');
const [editLocation, setEditLocation] = useState('');
const [editWebsite, setEditWebsite] = useState('');
const [formErrors, setFormErrors] = useState<Record<string, string>>({});
const [formErrors, setFormErrors] = useState<Record<string, string>>();

// Theme tokens
const bg = isDark ? '#0f172a' : '#f8fafc';
Expand All @@ -321,9 +334,15 @@ export const MobileProfile: React.FC<MobileProfileProps> = ({
setEditLocation(profile.location);
setEditWebsite(profile.website);
setFormErrors({});
setShowAdvancedFields(false); // reset disclosure state on each edit session
setIsEditing(true);
};

const handleToggleAdvancedFields = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
setShowAdvancedFields(prev => !prev);
};

const validateForm = (): Record<string, string> => {
const errors: Record<string, string> = {};
if (!editName.trim()) errors.name = 'Name is required';
Expand Down Expand Up @@ -595,13 +614,15 @@ export const MobileProfile: React.FC<MobileProfileProps> = ({
{isEditing ? (
<>
<Text style={[styles.cardTitle, { color: textPrimary }]}>Edit Profile</Text>

{/* ── Basic Fields (always visible) ── */}
<MobileFormInput
label="Full Name"
value={editName}
onChangeText={setEditName}
placeholder="Your full name"
required
error={formErrors.name}
error={formErrors?.name}
isDark={isDark}
leftIcon={<User size={18} color="#94a3b8" />}
/>
Expand All @@ -613,7 +634,7 @@ export const MobileProfile: React.FC<MobileProfileProps> = ({
keyboardType="email-address"
autoCapitalize="none"
required
error={formErrors.email}
error={formErrors?.email}
isDark={isDark}
leftIcon={<Mail size={18} color="#94a3b8" />}
/>
Expand All @@ -625,24 +646,50 @@ export const MobileProfile: React.FC<MobileProfileProps> = ({
multiline
isDark={isDark}
/>
<MobileFormInput
label="Location"
value={editLocation}
onChangeText={setEditLocation}
placeholder="City, Country"
isDark={isDark}
leftIcon={<MapPin size={18} color="#94a3b8" />}
/>
<MobileFormInput
label="Website"
value={editWebsite}
onChangeText={setEditWebsite}
placeholder="yourwebsite.com"
keyboardType="url"
autoCapitalize="none"
isDark={isDark}
leftIcon={<Globe size={18} color="#94a3b8" />}
/>

{/* ── Progressive Disclosure: Advanced Details ── */}
<TouchableOpacity
style={[
styles.disclosureToggle,
{ borderColor: isDark ? '#334155' : '#e2e8f0' },
]}
onPress={handleToggleAdvancedFields}
activeOpacity={0.7}
accessibilityRole="button"
accessibilityLabel={showAdvancedFields ? 'Hide advanced details' : 'Show advanced details'}
accessibilityState={{ expanded: showAdvancedFields }}
>
<Text style={[styles.disclosureToggleText, { color: '#19c3e6' }]}>
{showAdvancedFields ? 'Hide Advanced Details' : 'Advanced Details'}
</Text>
{showAdvancedFields
? <ChevronUp size={16} color="#19c3e6" />
: <ChevronDown size={16} color="#19c3e6" />}
</TouchableOpacity>

{/* ── Advanced Fields (expandable) ── */}
{showAdvancedFields && (
<View style={styles.disclosureContent}>
<MobileFormInput
label="Location"
value={editLocation}
onChangeText={setEditLocation}
placeholder="City, Country"
isDark={isDark}
leftIcon={<MapPin size={18} color="#94a3b8" />}
/>
<MobileFormInput
label="Website"
value={editWebsite}
onChangeText={setEditWebsite}
placeholder="yourwebsite.com"
keyboardType="url"
autoCapitalize="none"
isDark={isDark}
leftIcon={<Globe size={18} color="#94a3b8" />}
/>
</View>
)}
</>
) : (
<>
Expand Down Expand Up @@ -1123,4 +1170,24 @@ const styles = StyleSheet.create({
fontSize: 12,
fontWeight: '700',
},
// Progressive disclosure
disclosureToggle: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingVertical: 12,
paddingHorizontal: 4,
marginTop: 4,
marginBottom: 2,
borderTopWidth: 1,
borderBottomWidth: 1,
},
disclosureToggleText: {
fontSize: 14,
fontWeight: '600',
},
disclosureContent: {
marginTop: 4,
gap: 0,
},
});
Loading