Skip to content

Commit bc04c29

Browse files
committed
feat: set limits on input fields
1 parent 57104ee commit bc04c29

3 files changed

Lines changed: 40 additions & 31 deletions

File tree

src/mocks/handlers/editProfileHandlers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const mockUsername = 'johndoe';
1212
export const editProfileHandlers = [
1313
// Update profile info
1414
http.patch(`${baseURL}/me`, async ({ request }) => {
15-
const body = (await request.json()) as UpdateProfileRequest;
15+
const body = (await request.json()) as Partial<UpdateProfileRequest>;
1616
const mockResponse = { ...mockUsers[mockUsername], ...body };
1717

1818
if (!mockResponse) {

src/screens/profile/EditProfileScreen.tsx

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable react-native/no-raw-text */
12
import { useCallback, useEffect, useState } from 'react';
23

34
import {
@@ -21,6 +22,7 @@ import { ScrollView } from 'react-native-gesture-handler';
2122
import Avatar from '@/components/profile/Avatar';
2223
import ProfileBanner from '@/components/profile/Banner';
2324
import { TextInput } from '@/components/ui';
25+
import AppText from '@/components/ui/AppText';
2426
import Button from '@/components/ui/Button';
2527
import Spinner from '@/components/ui/Spinner';
2628
import { formatBirthDate } from '@/components/utils/profile';
@@ -49,14 +51,14 @@ const EditProfileScreen = () => {
4951
const [websiteError, setWebsiteError] = useState<string | null>(null);
5052
const [birthDateError, setBirthDateError] = useState<string | null>(null);
5153

52-
const [birthDate, setBirthDate] = useState<string | null>(user?.birthDate || null);
54+
const [birthDate, setBirthDate] = useState<string | null>(user.birthDate || null);
5355
const [birthDateInput, setBirthDateInput] = useState<string>(
54-
formatBirthDate(user?.birthDate ?? null) || ''
56+
formatBirthDate(user.birthDate ?? null) || ''
5557
);
5658
const [showDatePicker, setShowDatePicker] = useState<boolean>(false);
5759

58-
const [avatarUrl, setAvatarUrl] = useState<string | null>(user?.avatarUrl || null);
59-
const [bannerUrl, setBannerUrl] = useState<string | null>(user?.bannerUrl || null);
60+
const [avatarUrl, setAvatarUrl] = useState<string | null>(user.avatarUrl || null);
61+
const [bannerUrl, setBannerUrl] = useState<string | null>(user.bannerUrl || null);
6062
const [isEditingBanner, setIsEditingBanner] = useState<boolean>(false);
6163
const [menuVisible, setMenuVisible] = useState<boolean>(false);
6264
const [warningMenuVisible, setWarningMenuVisible] = useState<boolean>(false);
@@ -65,10 +67,10 @@ const EditProfileScreen = () => {
6567
const [canNavigateAway, setCanNavigateAway] = useState<boolean>(false);
6668

6769
const [formData, setFormData] = useState({
68-
displayName: user?.displayName || '',
69-
bio: user?.bio || '',
70-
location: user?.location || '',
71-
websiteUrl: user?.websiteUrl || '',
70+
displayName: user.displayName || '',
71+
bio: user.bio || '',
72+
location: user.location || '',
73+
websiteUrl: user.websiteUrl || '',
7274
});
7375

7476
const openDatePicker = () => {
@@ -96,10 +98,10 @@ const EditProfileScreen = () => {
9698
// format as YYYY-MM-DD
9799
const newBirthDate = selectedDate.toISOString().split('T')[0].trim();
98100
setBirthDateInput(newBirthDateInput);
101+
99102
// update in date picker
100103
setBirthDate(newBirthDate);
101104
// update form data
102-
// console.log('selected date:', newBirthDate);
103105
setFormData((prev) => ({ ...prev, birthDate: newBirthDate || '' }));
104106
setFormDataChanged(true);
105107
setBirthDateError(null);
@@ -201,31 +203,33 @@ const EditProfileScreen = () => {
201203
if (formDataChanged) {
202204
// to be implemented with mock later: updates to profile media
203205

204-
const request: UpdateProfileRequest = {
205-
displayName: formData.displayName.trim() || '', //fallback
206-
bio: formData.bio.trim() === '' ? null : formData.bio,
207-
location: formData.location.trim() === '' ? null : formData.location,
208-
websiteUrl: formData.websiteUrl.trim() === '' ? null : formData.websiteUrl,
209-
birthDate: birthDate === '' ? null : birthDate,
210-
};
206+
const request: Partial<UpdateProfileRequest> = {};
207+
208+
for (const [key, value] of Object.entries(formData)) {
209+
const changedInput = value.trim() === '' ? null : value;
210+
211+
if (changedInput) {
212+
request[key as keyof UpdateProfileRequest] = changedInput;
213+
}
214+
}
215+
216+
if (birthDate !== user.birthDate) {
217+
request.birthDate = birthDate;
218+
}
211219

212-
// console.log(request);
213-
// console.log(user);
214220
// call update profile
215221
await updateUserProfile(request);
216222

217223
// update user store
218224
updateUser({ ...request, avatarUrl, bannerUrl });
219225

220226
// update react query cache for profile screen
221-
queryClient.setQueryData(['profile', user?.username], (user: UserProfile) => ({
227+
queryClient.setQueryData(['profile', user.username], (user: UserProfile) => ({
222228
...user,
223229
...request,
224-
birthDate: birthDate,
225230
avatarUrl: avatarUrl,
226231
bannerUrl: bannerUrl,
227232
}));
228-
// console.log('inside update', user);
229233
}
230234

231235
// navigate back to profile screen
@@ -256,11 +260,7 @@ const EditProfileScreen = () => {
256260
]);
257261

258262
const isSaveDisabled =
259-
isLoading ||
260-
formData.displayName.trim().length === 0 ||
261-
!!websiteError ||
262-
!!birthDateError ||
263-
!formDataChanged;
263+
isLoading || formData.displayName.trim().length === 0 || !!websiteError || !!birthDateError;
264264

265265
useEffect(() => {
266266
navigation.setOptions({
@@ -292,6 +292,12 @@ const EditProfileScreen = () => {
292292
return unsubscribe;
293293
}, [navigation, formDataChanged, canNavigateAway]);
294294

295+
if (!user) {
296+
return (
297+
<AppText variant="heading1">This account does not exist. Try refreshing the page</AppText>
298+
);
299+
}
300+
295301
if (isLoading) {
296302
return (
297303
<View style={styles.centerContainer} testID="profile-loading-spinner">
@@ -318,8 +324,8 @@ const EditProfileScreen = () => {
318324
>
319325
<ProfileBanner
320326
uri={bannerUrl}
321-
username={user?.username}
322-
displayName={user?.displayName}
327+
username={user.username}
328+
displayName={user.displayName}
323329
isEdit={true}
324330
testID="banner-image"
325331
/>
@@ -352,6 +358,7 @@ const EditProfileScreen = () => {
352358
}}
353359
autoCapitalize="none"
354360
testID="edit-display-name-input"
361+
maxLength={50}
355362
/>
356363
<TextInput
357364
value={formData.bio}
@@ -362,8 +369,8 @@ const EditProfileScreen = () => {
362369
}}
363370
autoCapitalize="none"
364371
multiline={true}
365-
numberOfLines={5}
366372
maxLength={160}
373+
numberOfLines={4}
367374
testID="edit-bio-input"
368375
/>
369376
<TextInput
@@ -374,6 +381,7 @@ const EditProfileScreen = () => {
374381
setFormDataChanged(true);
375382
}}
376383
testID="edit-location-input"
384+
maxLength={30}
377385
/>
378386
<TextInput
379387
value={formData.websiteUrl}
@@ -382,6 +390,7 @@ const EditProfileScreen = () => {
382390
autoCapitalize="none"
383391
error={websiteError || undefined}
384392
testID="edit-website-input"
393+
maxLength={100}
385394
/>
386395
<Pressable onPress={openDatePicker} testID="edit-birthdate-button">
387396
<TextInput

src/services/user.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export async function getUserProfile(username: string) {
99
return response;
1010
}
1111

12-
export async function updateUserProfile(updatedProfile: UpdateProfileRequest) {
12+
export async function updateUserProfile(updatedProfile: Partial<UpdateProfileRequest>) {
1313
try {
1414
const response = await api.patch<ApiSuccessResponse<UpdateProfileRequest>>(
1515
'/me',

0 commit comments

Comments
 (0)