Skip to content

Commit 34c7bdc

Browse files
authored
Merge pull request #35 from fraidakis/fraidakis
feat(i18n): add missing translations and improve form validation UX
2 parents 35aa987 + 2320983 commit 34c7bdc

15 files changed

Lines changed: 89 additions & 37 deletions

src/components/home/FeaturesSection.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const FeaturesSection = ({ t }) => {
1616
<div className="container">
1717
<div className="features-header">
1818
<h2 className="section-title">{t('whatWeOffer')}</h2>
19-
<p className="section-subtitle">Everything you need for your perfect travel experience</p>
19+
<p className="section-subtitle">{t('whatWeOfferSubtitle')}</p>
2020
</div>
2121

2222
<div className="features-grid">

src/components/preferences/PreferenceForm.jsx

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const CATEGORY_ICONS = {
1919
/**
2020
* Preference form for creating/editing preference profiles
2121
*/
22-
const PreferenceForm = ({ t, formData, setFormData, editingProfile, onSubmit, onClose }) => {
22+
const PreferenceForm = ({ t, formData, setFormData, editingProfile, onSubmit, onClose, showError }) => {
2323
const toggleCategory = (category) => {
2424
setFormData(prev => {
2525
const categories = prev.categories || [];
@@ -32,6 +32,24 @@ const PreferenceForm = ({ t, formData, setFormData, editingProfile, onSubmit, on
3232
});
3333
};
3434

35+
const handleSubmit = (e) => {
36+
e.preventDefault();
37+
38+
// Validate name
39+
if (!formData.name || !formData.name.trim()) {
40+
showError(t('profileNameRequired'));
41+
return;
42+
}
43+
44+
// Validate categories
45+
if (!formData.categories || formData.categories.length === 0) {
46+
showError(t('categoryMinOne'));
47+
return;
48+
}
49+
50+
onSubmit(e);
51+
};
52+
3553
return (
3654
<div className="preference-form animate-fadeInUp">
3755
<div className="form-header">
@@ -41,18 +59,16 @@ const PreferenceForm = ({ t, formData, setFormData, editingProfile, onSubmit, on
4159
</button>
4260
</div>
4361

44-
<form onSubmit={onSubmit}>
62+
<form onSubmit={handleSubmit}>
4563
<div className="form-group">
4664
<label className="form-label">{t('profileName')}</label>
4765
<input
4866
type="text"
4967
value={formData.name}
5068
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
5169
className="form-input"
52-
placeholder="e.g., Weekend Getaway"
70+
placeholder={t('profileNamePlaceholder')}
5371
required
54-
pattern=".*\S+.*"
55-
title="Profile name cannot be empty or contain only whitespace"
5672
/>
5773
</div>
5874

@@ -67,7 +83,7 @@ const PreferenceForm = ({ t, formData, setFormData, editingProfile, onSubmit, on
6783
onClick={() => toggleCategory(cat)}
6884
>
6985
<span className="category-icon">{CATEGORY_ICONS[cat]}</span>
70-
<span className="category-name">{cat}</span>
86+
<span className="category-name">{t(cat)}</span>
7187
</button>
7288
))}
7389
</div>
@@ -88,3 +104,4 @@ const PreferenceForm = ({ t, formData, setFormData, editingProfile, onSubmit, on
88104

89105
export { PreferenceForm, CATEGORY_ICONS };
90106
export default PreferenceForm;
107+

src/components/preferences/ProfileCard.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ const ProfileCard = ({ t, profile, isActive, index, onActivate, onEdit, onDelete
3535
<div className="profile-tags">
3636
{(profile.categories || []).map(cat => (
3737
<span key={cat} className="profile-tag">
38-
{CATEGORY_ICONS[cat]} {cat}
38+
{CATEGORY_ICONS[cat]} {t(cat)}
3939
</span>
4040
))}
4141
{(!profile.categories || profile.categories.length === 0) && (
42-
<span className="no-data">No categories selected</span>
42+
<span className="no-data">{t('noCategoriesSelected')}</span>
4343
)}
4444
</div>
4545
</div>

src/components/recommendations/RecommendationFilters.jsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,10 @@ const RecommendationFilters = ({
5858
/>
5959
</div>
6060
<div className="filter-group filter-group--sort">
61-
<label className="filter-label">{t('sortBy') || 'Sort By'}</label>
61+
<label className="filter-label">{t('sortBy')}</label>
6262
<select value={sortBy} onChange={onSortChange} className="filter-select">
63-
<option value="distance">{t('sortByDistance') || 'Distance'}</option>
64-
<option value="rating">{t('sortByRating') || 'Rating'}</option>
63+
<option value="distance">{t('sortByDistance')}</option>
64+
<option value="rating">{t('sortByRating')}</option>
6565
</select>
6666
</div>
6767
<div className="filter-group filter-group--action">

src/i18n/locales/el/common.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"ctaDescription": "Γίνετε μέλος χιλιάδων ταξιδιωτών που ανακαλύπτουν εκπληκτικούς προορισμούς κάθε μέρα.",
4242
"exploreDestinations": "Εξερευνήστε Προορισμούς",
4343
"whatWeOffer": "Τι προσφέρουμε",
44+
"whatWeOfferSubtitle": "Ό,τι χρειάζεστε για μια τέλεια ταξιδιωτική εμπειρία",
4445
"personalizedRecommendations": "Εξατομικευμένες Προτάσεις",
4546
"personalizedRecommendationsDesc": "Λάβετε προτάσεις βασισμένες στις προτιμήσεις σας",
4647
"reviews": "Αξιολογήσεις",
@@ -68,7 +69,8 @@
6869
"haveAccount": "Έχετε ήδη λογαριασμό;",
6970
"loginLink": "Συνδεθείτε εδώ",
7071
"signupError": "Σφάλμα εγγραφής. Το email μπορεί να χρησιμοποιείται ήδη",
71-
"passwordRequirement": "Τουλάχιστον 6 χαρακτήρες (κεφαλαίο, πεζό, αριθμό)"
72+
"passwordRequirement": "Τουλάχιστον 6 χαρακτήρες (κεφαλαίο, πεζό, αριθμό)",
73+
"namePlaceholder": "Γιάννης Παπαδόπουλος"
7274
},
7375
"validation": {
7476
"invalidEmail": "Μη έγκυρη διεύθυνση email",

src/i18n/locales/el/features.json

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"from": "Από",
44
"to": "Προς",
55
"getRoute": "Εύρεση Διαδρομής",
6+
"navigationTitle": "Πλοήγηση Διαδρομής",
67
"navigationSubtitle": "Βρείτε τη διαδρομή προς τον προορισμό σας",
78
"calculateRoute": "Υπολογισμός Διαδρομής",
89
"startPoint": "Σημείο Εκκίνησης",
@@ -22,6 +23,9 @@
2223
"minutes": "λεπτά",
2324
"mapView": "Προβολή χάρτη (θα ενσωματωθεί σε μελλοντική έκδοση)",
2425
"quickRoutes": "Γρήγορες Διαδρομές",
26+
"routeAthensToThessaloniki": "Αθήνα → Θεσσαλονίκη",
27+
"routeThessalonikiToAthens": "Θεσσαλονίκη → Αθήνα",
28+
"routeHeraklionToAthens": "Ηράκλειο → Αθήνα",
2529
"resolvingLocation": "Εύρεση τοποθεσίας...",
2630
"enterLocation": "Τοποθεσία",
2731
"searchLocationPlaceholder": "π.χ., Αθήνα, Ελλάδα",
@@ -31,7 +35,7 @@
3135
"enterLocationsToStart": "Εισάγετε τοποθεσίες ή επιλέξτε μια γρήγορη διαδρομή"
3236
},
3337
"recommendationsPage": {
34-
"recommendationsTitle": "Προτάσεις για Εσάς",
38+
"recommendationsTitle": "Προτάσεις για Εσάς",
3539
"recommendationsSubtitle": "Εξατομικευμένες προτάσεις βασισμένες στις προτιμήσεις σας",
3640
"filtersTitle": "Φίλτρα Αναζήτησης",
3741
"latitude": "Γεωγραφικό Πλάτος",
@@ -42,8 +46,14 @@
4246
"errorLoadingRecommendations": "Σφάλμα κατά τη φόρτωση των προτάσεων",
4347
"noRecommendationsFound": "Δεν βρέθηκαν προτάσεις",
4448
"tryAgain": "Προσπάθεια Ξανά",
49+
"createProfileForRecommendations": "Δημιουργήστε ένα προφίλ προτιμήσεων για να δείτε προτάσεις",
4550
"goToPreferences": "Πηγαίνετε στο \"⚙️ Προφίλ Προτιμήσεων\" για να δημιουργήσετε ένα προφίλ",
46-
"tryDifferentFilters": "Δοκιμάστε να αλλάξετε τα φίλτρα αναζήτησης ή τις κατηγορίες στο προφίλ σας"
51+
"tryDifferentFilters": "Δοκιμάστε να αλλάξετε τα φίλτρα αναζήτησης ή τις κατηγορίες στο προφίλ σας",
52+
"sortBy": "Ταξινόμηση",
53+
"sortByDistance": "Απόσταση",
54+
"sortByRating": "Αξιολόγηση",
55+
"recommendationSingular": "Πρόταση",
56+
"recommendationPlural": "Προτάσεις"
4757
},
4858
"placeDetails": {
4959
"location": "Τοποθεσία",
@@ -105,6 +115,8 @@
105115
"HOTEL": "Ξενοδοχείο",
106116
"CAFE": "Καφετέρια",
107117
"BAR": "Μπαρ",
118+
"NIGHTLIFE": "Νυχτερινή Ζωή",
119+
"SPORTS": "Αθλητισμός",
108120
"cheap": "Οικονομικό",
109121
"moderate": "Μέτριο",
110122
"expensive": "Ακριβό"

src/i18n/locales/el/pages.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,10 @@
5151
"errorUpdatingProfile": "Σφάλμα κατά την ενημέρωση του προφίλ",
5252
"confirmDeleteProfile": "Είστε σίγουροι ότι θέλετε να διαγράψετε αυτό το προφίλ;",
5353
"errorDeletingProfile": "Σφάλμα κατά τη διαγραφή του προφίλ",
54-
"errorActivatingProfile": "Σφάλμα κατά την ενεργοποίηση του προφίλ"
54+
"errorActivatingProfile": "Σφάλμα κατά την ενεργοποίηση του προφίλ",
55+
"noCategoriesSelected": "Δεν έχουν επιλεγεί κατηγορίες",
56+
"profileNamePlaceholder": "π.χ., Σαββατοκύριακο",
57+
"profileNameRequired": "Το όνομα προφίλ δεν μπορεί να είναι κενό ή να περιέχει μόνο κενά"
5558
},
5659
"favouritesPage": {
5760
"favouritesTitle": "Τα Αγαπημένα σας Μέρη",

src/i18n/locales/en/common.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"ctaDescription": "Join thousands of travelers discovering amazing destinations every day.",
4242
"exploreDestinations": "Explore Destinations",
4343
"whatWeOffer": "What We Offer",
44+
"whatWeOfferSubtitle": "Everything you need for your perfect travel experience",
4445
"personalizedRecommendations": "Personalized Recommendations",
4546
"personalizedRecommendationsDesc": "Get recommendations based on your preferences",
4647
"reviews": "Reviews",
@@ -68,7 +69,8 @@
6869
"haveAccount": "Already have an account?",
6970
"loginLink": "Login here",
7071
"signupError": "Signup error. Email may already be in use",
71-
"passwordRequirement": "At least 6 characters (uppercase, lowercase, number)"
72+
"passwordRequirement": "At least 6 characters (uppercase, lowercase, number)",
73+
"namePlaceholder": "John Doe"
7274
},
7375
"validation": {
7476
"invalidEmail": "Invalid email address",

src/i18n/locales/en/features.json

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"from": "From",
44
"to": "To",
55
"getRoute": "Get Route",
6+
"navigationTitle": "Route Navigation",
67
"navigationSubtitle": "Find the route to your destination",
78
"calculateRoute": "Calculate Route",
89
"startPoint": "Starting Point",
@@ -22,6 +23,9 @@
2223
"minutes": "minutes",
2324
"mapView": "Map view (will be integrated in future version)",
2425
"quickRoutes": "Quick Routes",
26+
"routeAthensToThessaloniki": "Athens → Thessaloniki",
27+
"routeThessalonikiToAthens": "Thessaloniki → Athens",
28+
"routeHeraklionToAthens": "Heraklion → Athens",
2529
"resolvingLocation": "Resolving location...",
2630
"enterLocation": "Location",
2731
"searchLocationPlaceholder": "e.g., Athens, Greece",
@@ -31,7 +35,7 @@
3135
"enterLocationsToStart": "Enter locations or select a quick route to get started"
3236
},
3337
"recommendationsPage": {
34-
"recommendationsTitle": "Recommendations for You",
38+
"recommendationsTitle": "Recommendations for You",
3539
"recommendationsSubtitle": "Personalized recommendations based on your preferences",
3640
"filtersTitle": "Search Filters",
3741
"latitude": "Latitude",
@@ -42,8 +46,14 @@
4246
"errorLoadingRecommendations": "Error loading recommendations",
4347
"noRecommendationsFound": "No recommendations found",
4448
"tryAgain": "Try Again",
49+
"createProfileForRecommendations": "Create a preference profile to see recommendations",
4550
"goToPreferences": "Go to \"⚙️ Preference Profile\" to create a profile",
46-
"tryDifferentFilters": "Try changing the search filters or categories in your profile"
51+
"tryDifferentFilters": "Try changing the search filters or categories in your profile",
52+
"sortBy": "Sort By",
53+
"sortByDistance": "Distance",
54+
"sortByRating": "Rating",
55+
"recommendationSingular": "Recommendation",
56+
"recommendationPlural": "Recommendations"
4757
},
4858
"placeDetails": {
4959
"location": "Location",
@@ -105,6 +115,8 @@
105115
"HOTEL": "Hotel",
106116
"CAFE": "Cafe",
107117
"BAR": "Bar",
118+
"NIGHTLIFE": "Nightlife",
119+
"SPORTS": "Sports",
108120
"cheap": "Cheap",
109121
"moderate": "Moderate",
110122
"expensive": "Expensive"

src/i18n/locales/en/pages.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,10 @@
5151
"errorUpdatingProfile": "Error updating profile",
5252
"confirmDeleteProfile": "Are you sure you want to delete this profile?",
5353
"errorDeletingProfile": "Error deleting profile",
54-
"errorActivatingProfile": "Error activating profile"
54+
"errorActivatingProfile": "Error activating profile",
55+
"noCategoriesSelected": "No categories selected",
56+
"profileNamePlaceholder": "e.g., Weekend Getaway",
57+
"profileNameRequired": "Profile name cannot be empty or contain only whitespace"
5558
},
5659
"favouritesPage": {
5760
"favouritesTitle": "Your Favourite Places",

0 commit comments

Comments
 (0)