From a2ddd5f166db49bd2839876df8f787a3c283d2a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Galley?= Date: Fri, 25 Oct 2024 11:53:39 -0400 Subject: [PATCH] Add location to basename profile / TextRecords (#1153) --- .../Basenames/UsernameLocationField/index.tsx | 52 ++++++++++++++ .../Basenames/UsernameProfileCard/index.tsx | 70 ++++++++++++------- .../index.tsx | 6 ++ apps/web/src/components/Icon/Icon.tsx | 17 +++++ .../src/hooks/useReadBaseEnsTextRecords.ts | 1 + apps/web/src/utils/usernames.ts | 5 ++ 6 files changed, 124 insertions(+), 27 deletions(-) create mode 100644 apps/web/src/components/Basenames/UsernameLocationField/index.tsx diff --git a/apps/web/src/components/Basenames/UsernameLocationField/index.tsx b/apps/web/src/components/Basenames/UsernameLocationField/index.tsx new file mode 100644 index 0000000..a0c3634 --- /dev/null +++ b/apps/web/src/components/Basenames/UsernameLocationField/index.tsx @@ -0,0 +1,52 @@ +import Fieldset from 'apps/web/src/components/Fieldset'; +import Input from 'apps/web/src/components/Input'; +import Label from 'apps/web/src/components/Label'; +import { + textRecordsKeysPlaceholderForDisplay, + USERNAME_LOCATION_MAX_LENGTH, + UsernameTextRecordKeys, +} from 'apps/web/src/utils/usernames'; +import { ChangeEvent, ReactNode, useCallback, useId } from 'react'; + +export type UsernameLocationFieldProps = { + labelChildren?: ReactNode; + onChange: (key: UsernameTextRecordKeys, value: string) => void; + value: string; + disabled?: boolean; +}; + +export default function UsernameLocationField({ + labelChildren = 'Location', + onChange, + value, + disabled = false, +}: UsernameLocationFieldProps) { + const onChangeLocation = useCallback( + (event: ChangeEvent) => { + const location = event.target.value; + if (location.length > USERNAME_LOCATION_MAX_LENGTH) { + event.preventDefault(); + } else { + if (onChange) onChange(UsernameTextRecordKeys.Location, location); + } + }, + [onChange], + ); + + const usernameLocationFieldId = useId(); + + return ( +
+ {labelChildren && } + +
+ ); +} diff --git a/apps/web/src/components/Basenames/UsernameProfileCard/index.tsx b/apps/web/src/components/Basenames/UsernameProfileCard/index.tsx index 6952861..c6a5cdf 100644 --- a/apps/web/src/components/Basenames/UsernameProfileCard/index.tsx +++ b/apps/web/src/components/Basenames/UsernameProfileCard/index.tsx @@ -20,6 +20,7 @@ export default function UsernameProfileCard() { }); const textRecordDescription = existingTextRecords[UsernameTextRecordKeys.Description]; + const textRecordLocation = existingTextRecords[UsernameTextRecordKeys.Location]; const textRecordsSocial = textRecordsSocialFieldsEnabled.reduce( (previousValue, textRecordKey) => { @@ -29,9 +30,11 @@ export default function UsernameProfileCard() { {} as UsernameTextRecords, ); + const hasTextRecordsSocials = Object.values(textRecordsSocial).filter((v) => !!v).length > 0; + // TODO: Empty state / CTA to edit if owner const hasTextRecordsToDisplay = - !!textRecordDescription || Object.values(textRecordsSocial).filter((v) => !!v).length > 0; + !!textRecordDescription || !!textRecordLocation || hasTextRecordsSocials; if (!hasTextRecordsToDisplay) { return; @@ -47,32 +50,45 @@ export default function UsernameProfileCard() {

{textRecordDescription}

)} - + {!!textRecordLocation && ( +

+ + + + {textRecordLocation} +

+ )} + {hasTextRecordsSocials && ( + + )} ); } diff --git a/apps/web/src/components/Basenames/UsernameProfileSettingsManageProfile/index.tsx b/apps/web/src/components/Basenames/UsernameProfileSettingsManageProfile/index.tsx index b6ee790..9940f8a 100644 --- a/apps/web/src/components/Basenames/UsernameProfileSettingsManageProfile/index.tsx +++ b/apps/web/src/components/Basenames/UsernameProfileSettingsManageProfile/index.tsx @@ -17,6 +17,7 @@ import { UsernameTextRecordKeys, } from 'apps/web/src/utils/usernames'; import UsernameCastsField from 'apps/web/src/components/Basenames/UsernameCastsField'; +import UsernameLocationField from 'apps/web/src/components/Basenames/UsernameLocationField'; const settingTabClass = classNames( 'flex flex-col justify-between gap-8 text-gray/60 md:items-center p-4 md:p-8', @@ -72,6 +73,11 @@ export default function UsernameProfileSettingsManageProfile() { value={updatedTextRecords[UsernameTextRecordKeys.Description]} disabled={writeTextRecordsIsPending} /> +
{textRecordsSocialFieldsEnabled.map((textRecordKey) => ( diff --git a/apps/web/src/components/Icon/Icon.tsx b/apps/web/src/components/Icon/Icon.tsx index 89eb541..f68b34e 100644 --- a/apps/web/src/components/Icon/Icon.tsx +++ b/apps/web/src/components/Icon/Icon.tsx @@ -521,6 +521,23 @@ const ICONS: Record JSX.Element> = { /> ), + + map: ({ color, width, height }: SvgProps) => ( + + + + ), }; export function Icon({ name, color = 'white', width = '24', height = '24' }: IconProps) { diff --git a/apps/web/src/hooks/useReadBaseEnsTextRecords.ts b/apps/web/src/hooks/useReadBaseEnsTextRecords.ts index 42287f7..979737d 100644 --- a/apps/web/src/hooks/useReadBaseEnsTextRecords.ts +++ b/apps/web/src/hooks/useReadBaseEnsTextRecords.ts @@ -38,6 +38,7 @@ export default function useReadBaseEnsTextRecords({ [UsernameTextRecordKeys.Github]: '', [UsernameTextRecordKeys.Email]: '', [UsernameTextRecordKeys.Phone]: '', + [UsernameTextRecordKeys.Location]: '', [UsernameTextRecordKeys.Avatar]: '', [UsernameTextRecordKeys.Frames]: '', [UsernameTextRecordKeys.Casts]: '', diff --git a/apps/web/src/utils/usernames.ts b/apps/web/src/utils/usernames.ts index 8f5a004..8e5c240 100644 --- a/apps/web/src/utils/usernames.ts +++ b/apps/web/src/utils/usernames.ts @@ -63,6 +63,7 @@ export const USERNAME_MIN_CHARACTER_LENGTH = 3; export const USERNAME_MAX_CHARACTER_LENGTH = 20; export const USERNAME_DESCRIPTION_MAX_LENGTH = 200; +export const USERNAME_LOCATION_MAX_LENGTH = 100; // DANGER: Changing this post-mainnet launch means the stored data won't be accessible via the updated key export enum UsernameTextRecordKeys { @@ -75,6 +76,7 @@ export enum UsernameTextRecordKeys { Email = 'email', Phone = 'phone', Avatar = 'avatar', + Location = 'location', // Socials Github = 'com.github', @@ -177,6 +179,7 @@ export const textRecordsKeysEnabled = [ UsernameTextRecordKeys.Github, UsernameTextRecordKeys.Email, UsernameTextRecordKeys.Phone, + UsernameTextRecordKeys.Location, UsernameTextRecordKeys.Twitter, UsernameTextRecordKeys.Farcaster, UsernameTextRecordKeys.Lens, @@ -196,6 +199,7 @@ export const textRecordsKeysForDisplay = { [UsernameTextRecordKeys.Github]: 'Github', [UsernameTextRecordKeys.Email]: 'Email', [UsernameTextRecordKeys.Phone]: 'Phone', + [UsernameTextRecordKeys.Location]: 'Location', [UsernameTextRecordKeys.Twitter]: 'Twitter / X', [UsernameTextRecordKeys.Farcaster]: 'Farcaster', [UsernameTextRecordKeys.Lens]: 'Lens', @@ -215,6 +219,7 @@ export const textRecordsKeysPlaceholderForDisplay = { [UsernameTextRecordKeys.Github]: 'Username', [UsernameTextRecordKeys.Email]: 'Personal email', [UsernameTextRecordKeys.Phone]: '+1 415 ..', + [UsernameTextRecordKeys.Location]: 'New York, NY, USA', [UsernameTextRecordKeys.Twitter]: 'Username', [UsernameTextRecordKeys.Farcaster]: 'Username', [UsernameTextRecordKeys.Lens]: 'name.lens',