From 65b31fa96a63c200096a1620127f35ae36a02a2c Mon Sep 17 00:00:00 2001 From: zealves99 Date: Fri, 30 May 2025 00:16:02 +0100 Subject: [PATCH] feat: dialogs translations Added the translations to the dialogs and toasts --- .../app/components/forms/location-form.tsx | 37 ++- .../vizzy/app/profile/[username]/page.tsx | 10 +- frontend/vizzy/app/refresh/page.tsx | 6 +- frontend/vizzy/app/settings/account/page.tsx | 50 ++-- .../app/settings/components/contact-form.tsx | 20 +- .../app/settings/components/contacts-list.tsx | 8 +- .../settings/components/contacts-section.tsx | 9 +- .../settings/components/location-settings.tsx | 12 +- .../components/personal-information.tsx | 42 ++-- .../settings/components/profile-picture.tsx | 27 +-- .../vizzy/app/settings/hooks/useContacts.ts | 12 +- frontend/vizzy/app/settings/page.tsx | 7 +- .../app/settings/settings-navigation.tsx | 7 +- .../marketplace/filters-section.tsx | 20 +- .../components/proposals/buy-now-dialog.tsx | 30 +-- .../proposals/cancel-proposal-dialog.tsx | 25 +- .../proposals/giveaway-proposal-dialog.tsx | 30 +-- .../components/proposals/proposal-card.tsx | 2 +- .../proposals/purchase-proposal-dialog.tsx | 33 +-- .../components/proposals/rent-now-dialog.tsx | 36 +-- .../proposals/rental-proposal-dialog.tsx | 40 +-- .../proposals/swap-proposal-dialog.tsx | 67 ++--- frontend/vizzy/messages/en.json | 229 ++++++++++++++++-- frontend/vizzy/messages/pt.json | 228 +++++++++++++++-- 24 files changed, 681 insertions(+), 306 deletions(-) diff --git a/frontend/vizzy/app/components/forms/location-form.tsx b/frontend/vizzy/app/components/forms/location-form.tsx index db33cd18..dded2693 100644 --- a/frontend/vizzy/app/components/forms/location-form.tsx +++ b/frontend/vizzy/app/components/forms/location-form.tsx @@ -18,6 +18,7 @@ import { import { Loader2 } from 'lucide-react'; import { fetchLocationDetails } from '@/lib/api/location/geocoding'; import { toast } from 'sonner'; +import { useTranslations } from 'next-intl'; interface LocationFormProps { defaultValues?: Partial; @@ -50,7 +51,7 @@ export function LocationForm({ }) | null >(null); - + const t = useTranslations('accountSettings.profileTab.location'); const form = useForm({ resolver: zodResolver(locationSchema), defaultValues: { @@ -66,9 +67,7 @@ export function LocationForm({ const result = await fetchLocationDetails(data.country, data.village); if (!result.data?.valid) { - toast.warning( - "We couldn't find this location. Please check your input and try again.", - ); + toast.warning(t('locationError')); form.setError('country', { type: 'manual', message: 'Please check your input', @@ -81,12 +80,10 @@ export function LocationForm({ !result.data.latitude || !result.data.longitude ) { - toast.warning( - "We found the location but couldn't get all the details. Please try entering a more specific location.", - ); + toast.warning(t('locationFoundButIncomplete')); form.setError('country', { type: 'manual', - message: 'Please try a more specific location', + message: t('locationFoundButIncompleteMessage'), }); return; } @@ -101,12 +98,10 @@ export function LocationForm({ setShowConfirmation(true); } catch (error) { console.error('Error validating location:', error); - toast.error( - 'There was an error validating your location. Please try again.', - ); + toast.error(t('validationError')); form.setError('country', { type: 'manual', - message: 'Please check your input', + message: t('validationErrorMessage'), }); } finally { setIsLoading(false); @@ -127,10 +122,10 @@ export function LocationForm({ return (
-

Confirm Your Location

+

{t('confirmLocation')}

- Full Address:{' '} + {t('fullAddress')}:{' '} {locationData.fullAddress}
@@ -147,10 +142,10 @@ export function LocationForm({ className="flex-1" onClick={handleEdit} > - Edit + {t('edit')}
@@ -175,9 +170,9 @@ export function LocationForm({ name="country" render={({ field }) => ( - Country + {t('country')} - + @@ -189,9 +184,9 @@ export function LocationForm({ name="village" render={({ field }) => ( - Village + {t('village')} - + @@ -213,7 +208,7 @@ export function LocationForm({ {isLoading ? ( <> - Validating... + {t('loading')} ) : ( submitButtonText diff --git a/frontend/vizzy/app/profile/[username]/page.tsx b/frontend/vizzy/app/profile/[username]/page.tsx index 13d308b7..c8f6547c 100644 --- a/frontend/vizzy/app/profile/[username]/page.tsx +++ b/frontend/vizzy/app/profile/[username]/page.tsx @@ -6,7 +6,7 @@ import { } from '@/components/ui/data-display/avatar'; import { Badge } from '@/components/ui/common/badge'; import { Card } from '@/components/ui/data-display/card'; -import { ChevronRight, MapPin } from 'lucide-react'; +import { MapPin } from 'lucide-react'; import { Button } from '@/components/ui/common/button'; import UserListings from './components/user-listings'; import Link from 'next/link'; @@ -140,14 +140,6 @@ export default async function ProfilePage(props: ProfilePageProps) {

{t('listingsSection.title')}

- {/* TODO: create the See all page (paginated list of product listings) */} - - {t('listingsSection.seeAll')} - -
{user.activeListings > 0 ? ( diff --git a/frontend/vizzy/app/refresh/page.tsx b/frontend/vizzy/app/refresh/page.tsx index 00ba9c2d..082d22ac 100644 --- a/frontend/vizzy/app/refresh/page.tsx +++ b/frontend/vizzy/app/refresh/page.tsx @@ -7,7 +7,7 @@ import { getAuthTokensAction } from '@/lib/actions/auth/token-action'; import { useTranslations } from 'next-intl'; export default function RefreshPage() { - const t = useTranslations('auth.refresh'); + const t = useTranslations('common.auth.refresh'); const router = useRouter(); const searchParams = useSearchParams(); const [isLoading, setIsLoading] = useState(true); @@ -69,7 +69,9 @@ export default function RefreshPage() { return (
-

{t('errors.prefix')}: {error}

+

+ {t('errors.prefix')}: {error} +

@@ -84,61 +83,52 @@ export default function AccountSettings() {
-

Account

-

- Manage your account settings and preferences. -

+

{t('account')}

+

{t('description')}

{/* TODO: Implement password update */}
- Password - - Change your password here. After saving, you'll be logged - out. - + {t('password')} + {t('passwordDescription')}
- +
- +
- +
- +
- Danger Zone - - Permanently delete your account and all of your content. - + + {t('dangerZone')} + + {t('dangerZoneDescription')} -

- Once you delete your account, there is no going back. This action - cannot be undone. All of your data will be permanently removed - from our servers. -

+

diff --git a/frontend/vizzy/app/settings/components/contact-form.tsx b/frontend/vizzy/app/settings/components/contact-form.tsx index 29b03c6b..527234a8 100644 --- a/frontend/vizzy/app/settings/components/contact-form.tsx +++ b/frontend/vizzy/app/settings/components/contact-form.tsx @@ -2,6 +2,7 @@ import { Button } from '@/components/ui/common/button'; import { Card, CardContent } from '@/components/ui/data-display/card'; import { Input } from '@/components/ui/forms/input'; import { Label } from '@/components/ui/common/label'; +import { useTranslations } from 'next-intl'; interface ContactFormProps { newContact: { @@ -22,33 +23,36 @@ export function ContactForm({ onSave, isAddingContact, }: ContactFormProps) { + const t = useTranslations('accountSettings.profileTab.contacts'); return (
- + onContactChange('name', e.target.value)} />
- + onContactChange('phone_number', e.target.value)} />
- + onContactChange('description', e.target.value)} /> @@ -61,7 +65,7 @@ export function ContactForm({ disabled={isAddingContact} className="cursor-pointer" > - Cancel + {t('cancel')}
diff --git a/frontend/vizzy/app/settings/components/contacts-list.tsx b/frontend/vizzy/app/settings/components/contacts-list.tsx index 9e427bd0..c7f3a30d 100644 --- a/frontend/vizzy/app/settings/components/contacts-list.tsx +++ b/frontend/vizzy/app/settings/components/contacts-list.tsx @@ -1,6 +1,7 @@ import { Button } from '@/components/ui/common/button'; import { User, Trash2 } from 'lucide-react'; import type { Contact } from '@/types/contact'; +import { useTranslations } from 'next-intl'; interface ContactsListProps { contacts: Contact[]; @@ -13,13 +14,14 @@ export function ContactsList({ isDeletingContact, onDelete, }: ContactsListProps) { + const t = useTranslations('accountSettings.profileTab.contacts'); if (contacts.length === 0) { return (
-

No contacts yet

+

{t('noContacts')}

- Add your first contact to get started. + {t('noContactsDescription')}

); @@ -55,7 +57,7 @@ export function ContactsList({ ) : ( )} - Delete contact + {t('deleteContact')}
))} diff --git a/frontend/vizzy/app/settings/components/contacts-section.tsx b/frontend/vizzy/app/settings/components/contacts-section.tsx index 86661168..76ab4416 100644 --- a/frontend/vizzy/app/settings/components/contacts-section.tsx +++ b/frontend/vizzy/app/settings/components/contacts-section.tsx @@ -10,6 +10,7 @@ import { PlusCircle } from 'lucide-react'; import { ContactForm } from './contact-form'; import { ContactsList } from './contacts-list'; import { useContacts } from '../hooks/useContacts'; +import { useTranslations } from 'next-intl'; export function ContactsSection() { const { @@ -29,12 +30,14 @@ export function ContactsSection() { setNewContact((prev) => ({ ...prev, [field]: value })); }; + const t = useTranslations('accountSettings.profileTab.contacts'); + return (
- Contacts - Manage your contacts list. + {t('title')} + {t('description')}
diff --git a/frontend/vizzy/app/settings/components/location-settings.tsx b/frontend/vizzy/app/settings/components/location-settings.tsx index 00e710fc..b7a03cbe 100644 --- a/frontend/vizzy/app/settings/components/location-settings.tsx +++ b/frontend/vizzy/app/settings/components/location-settings.tsx @@ -10,8 +10,10 @@ import { toast } from 'sonner'; import { updateUserLocation } from '@/lib/api/user/location'; import { fetchUserLocation } from '@/lib/api/user/location'; import { LocationValues } from '@/app/auth/signup/schema/multi-step-signup-schema'; +import { useTranslations } from 'next-intl'; export function LocationSettings() { + const t = useTranslations('accountSettings.profileTab'); const [defaultValues, setDefaultValues] = React.useState< Partial >({}); @@ -53,26 +55,26 @@ export function LocationSettings() { }); if (!result.error) { - toast.success('Location updated successfully'); + toast(t('location.updateLocationSuccess')); } else { - toast.error('Failed to update location'); + toast(t('location.updateLocationError')); } } catch (error) { console.error('Error updating location:', error); - toast.error('Failed to update location'); + toast(t('location.updateLocationError')); } }; return ( - Location + {t('location.label')} diff --git a/frontend/vizzy/app/settings/components/personal-information.tsx b/frontend/vizzy/app/settings/components/personal-information.tsx index 5cb3628f..e61876da 100644 --- a/frontend/vizzy/app/settings/components/personal-information.tsx +++ b/frontend/vizzy/app/settings/components/personal-information.tsx @@ -33,6 +33,7 @@ import { useState } from 'react'; import { logoutUserAction } from '@/lib/actions/auth/logout-action'; import { useRouter } from 'next/navigation'; import { ROUTES } from '@/lib/constants/routes/routes'; +import { useTranslations } from 'next-intl'; interface PersonalInformationProps { form: UseFormReturn; @@ -48,7 +49,7 @@ export function PersonalInformation({ const [pendingData, setPendingData] = useState( null, ); - + const t = useTranslations('accountSettings.profileTab'); const handleLogout = async () => { await logoutUserAction(); router.push(ROUTES.LOGIN); @@ -65,12 +66,12 @@ export function PersonalInformation({ const result = await updateProfileInfo(pendingData); if (result.error) { console.error('Failed to update profile:', result.error); - toast('Failed to update profile. Please try again later.'); + toast(t('updateProfileError')); setShowConfirmDialog(false); return; } - toast('Your profile has been updated successfully.'); + toast(t('updateProfileSuccess')); setShowConfirmDialog(false); await handleLogout(); @@ -81,10 +82,9 @@ export function PersonalInformation({ - Confirm Profile Update + {t('confirmProfileUpdate')} - Updating your profile information will require you to log in again - for security purposes. Do you want to continue? + {t('confirmProfileUpdateDescription')} @@ -93,10 +93,10 @@ export function PersonalInformation({ variant="outline" onClick={() => setShowConfirmDialog(false)} > - Cancel + {t('cancel')} @@ -106,9 +106,9 @@ export function PersonalInformation({
- Personal Information + {t('personalInformation')} - Update your personal information here. + {t('personalInformationDescription')} @@ -128,12 +128,15 @@ export function PersonalInformation({ name="username" render={({ field }) => ( - Username + {t('username')} - + - This is your public display name. + {t('usernameDescription')} @@ -144,9 +147,12 @@ export function PersonalInformation({ name="name" render={({ field }) => ( - Name + {t('name')} - + @@ -157,11 +163,11 @@ export function PersonalInformation({ name="email" render={({ field }) => ( - Email + {t('email')} @@ -191,7 +197,7 @@ export function PersonalInformation({ type="submit" disabled={isLoading} > - Save changes + {t('update')} diff --git a/frontend/vizzy/app/settings/components/profile-picture.tsx b/frontend/vizzy/app/settings/components/profile-picture.tsx index cc1b4f43..fb6d2550 100644 --- a/frontend/vizzy/app/settings/components/profile-picture.tsx +++ b/frontend/vizzy/app/settings/components/profile-picture.tsx @@ -16,6 +16,7 @@ import { CardTitle, } from '@/components/ui/data-display/card'; import { updateAvatar } from '@/lib/api/profile/avatar'; +import { useTranslations } from 'next-intl'; interface ProfilePictureProps { avatarUrl: string | null; @@ -32,7 +33,7 @@ export function ProfilePicture({ }: ProfilePictureProps) { const [selectedImage, setSelectedImage] = useState(null); const [isUploadingAvatar, setIsUploadingAvatar] = useState(false); - + const t = useTranslations('accountSettings.profileTab'); const handleImageChange = (e: React.ChangeEvent) => { const files = e.target.files; if (!files || files.length === 0) return; @@ -40,14 +41,12 @@ export function ProfilePicture({ const file = files[0]; if (file.size > 1024 * 1024) { - toast.error('File is too large. Maximum size is 1MB.'); + toast(t('fileTooLarge')); return; } if (!['image/jpeg', 'image/png'].includes(file.type)) { - toast.error( - 'File is not a supported format. Only JPG and PNG are allowed.', - ); + toast(t('fileNotSupported')); return; } @@ -67,16 +66,14 @@ export function ProfilePicture({ const result = await updateAvatar(selectedImage); if (result.error) { console.error('Upload error:', result.error); - toast.error( - 'Failed to update profile picture. Please try again later.', - ); + toast.error(t('updateProfilePicError')); } else if (result.data) { - toast.success('Your profile picture has been updated successfully.'); + toast.success(t('updateProfilePicSuccess')); onAvatarUpdate(result.data); } } catch (error) { console.error('Upload error:', error); - toast.error('Failed to update profile picture. Please try again later.'); + toast.error(t('updateProfilePicError')); } finally { setIsUploadingAvatar(false); setSelectedImage(null); @@ -86,8 +83,8 @@ export function ProfilePicture({ return ( - Profile Picture - Upload a new profile picture. + {t('profilePic')} + {t('profilePicDescription')}
@@ -95,7 +92,7 @@ export function ProfilePicture({ {isLoading ? (
- Loading... + {t('loading')}
) : ( <> @@ -124,14 +121,14 @@ export function ProfilePicture({
- Recommended: Square JPG, PNG, at least 400x400 pixels. + {t('recommended')}
diff --git a/frontend/vizzy/app/settings/hooks/useContacts.ts b/frontend/vizzy/app/settings/hooks/useContacts.ts index 588c60b8..02a60666 100644 --- a/frontend/vizzy/app/settings/hooks/useContacts.ts +++ b/frontend/vizzy/app/settings/hooks/useContacts.ts @@ -7,6 +7,7 @@ import { fetchContacts, } from '@/lib/api/contacts/contacts'; import { getUserMetadataAction } from '@/lib/actions/auth/get-user-metadata-action'; +import { useTranslations } from 'next-intl'; export function useContacts() { const [contacts, setContacts] = useState([]); @@ -21,6 +22,7 @@ export function useContacts() { const [isDeletingContact, setIsDeletingContact] = useState( null, ); + const t = useTranslations('accountSettings.profileTab.contacts'); useEffect(() => { async function loadContacts() { @@ -30,7 +32,7 @@ export function useContacts() { const result = await fetchContacts(userData.id); if (result.error) { console.error('Failed to load contacts:', result.error); - toast('Failed to load contacts. Please try again later.'); + toast(t('loadContactError')); } else { setContacts(result.data ?? []); } @@ -48,12 +50,12 @@ export function useContacts() { const result = await addContact(newContact); if (result.error) { console.error('Failed to add contact:', result.error); - toast('Failed to add contact. Please try again later.'); + toast(t('addContactError')); } else if (result.data) { setContacts([...contacts, result.data]); setNewContact({ name: '', phone_number: '', description: '' }); setShowContactForm(false); - toast('The contact has been added successfully.'); + toast(t('addContactSuccess')); } setIsAddingContact(false); }; @@ -63,10 +65,10 @@ export function useContacts() { const result = await deleteContact(id); if (result.error) { console.error('Failed to delete contact:', result.error); - toast('Failed to delete contact. Please try again later.'); + toast(t('deleteContactError')); } else { setContacts(contacts.filter((contact) => contact.id !== id)); - toast('The contact has been deleted successfully.'); + toast(t('deleteContactSuccess')); } setIsDeletingContact(null); }; diff --git a/frontend/vizzy/app/settings/page.tsx b/frontend/vizzy/app/settings/page.tsx index e48f2f19..c949b18f 100644 --- a/frontend/vizzy/app/settings/page.tsx +++ b/frontend/vizzy/app/settings/page.tsx @@ -6,18 +6,17 @@ import { ProfilePicture } from './components/profile-picture'; import { PersonalInformation } from './components/personal-information'; import { ContactsSection } from './components/contacts-section'; import { LocationSettings } from './components/location-settings'; +import { useTranslations } from 'next-intl'; export default function ProfileSettings() { const form = useProfileForm(); const { isLoading, avatarUrl, setAvatarUrl } = useProfileData(form); - + const t = useTranslations('accountSettings.profileTab'); return (

Profile

-

- This is how others will see you on the site. -

+

{t('description')}

- Profile + {t('profile')} - Account + {t('account')} ); diff --git a/frontend/vizzy/components/marketplace/filters-section.tsx b/frontend/vizzy/components/marketplace/filters-section.tsx index 2a10cdf5..8fec7d5f 100644 --- a/frontend/vizzy/components/marketplace/filters-section.tsx +++ b/frontend/vizzy/components/marketplace/filters-section.tsx @@ -54,7 +54,7 @@ export function FiltersSection({ } + {trigger || } - Purchase Proposal - - Are you sure you want to buy this item? - + {t('sale.title')} + {t('sale.buyNowDescription')}
@@ -114,7 +113,8 @@ export function BuyNowDialog({ product, trigger, receiver_id }: BuyNowProps) {

{product.title}

- {product.price}€ · {product.condition} + {product.price}€ ·{' '} + {t(`common.condition.${product.condition}`)}

@@ -124,11 +124,11 @@ export function BuyNowDialog({ product, trigger, receiver_id }: BuyNowProps) {
- +