From b02f655d4d6e809a4693767682f373d76d8694d3 Mon Sep 17 00:00:00 2001 From: Sajad Mirjalili Date: Wed, 20 Aug 2025 20:55:24 +0330 Subject: [PATCH 1/2] fix: completion page apis, validation, email states --- public/locales/en/common.json | 252 +-------- public/locales/en/completionForm.json | 19 +- public/locales/en/country.json | 492 +++++++++--------- .../locales/en/{sideMap.json => sideNav.json} | 4 +- public/locales/fa/common.json | 197 +------ public/locales/fa/completionForm.json | 21 +- public/locales/fa/country.json | 362 ++++++------- public/locales/fa/sideMap.json | 14 - public/locales/fa/sideNav.json | 13 + src/components/CardContainer.tsx | 2 +- src/components/Layout/Header.tsx | 4 +- src/components/Layout/Toolbar.tsx | 11 +- src/components/Layout/buildNavItems.tsx | 3 +- src/components/Loading.tsx | 3 +- .../authorization/api/userCompletion.ts | 1 + .../AccountCreated/AccountCreated.tsx | 4 +- .../AccountCreatedClubBanner.tsx | 5 +- .../AccountCreatedRedirectButton.tsx | 2 +- .../components/AuthenticationCard.tsx | 8 +- .../AuthenticationSteps.tsx | 2 +- .../components/CountryCodeSelector.tsx | 6 +- .../UserCompletionForm/DateOfBirth.tsx | 7 +- .../UserCompletionForm/EmailSection.tsx | 103 ++-- .../UserCompletionForm/PasswordSection.tsx | 21 +- .../UserCompletionForm/PersonalInfoFields.tsx | 28 +- .../UserCompletionForm/SubmitSection.tsx | 3 +- .../routes/UserCompletionPage.tsx | 473 ++++++++++------- .../types/completionFormApiTypes.ts | 1 + .../authorization/types/settingForm.ts | 23 +- .../userInformation/PersonalInformation.tsx | 2 +- .../userInformation/SocialMedia.tsx | 2 +- src/hooks/useApi.ts | 24 +- src/providers/CustomThemeProvider.tsx | 3 + src/routes/config.tsx | 12 +- src/theme/color.type.ts | 2 +- src/theme/colors.ts | 2 + src/theme/palette.ts | 6 + src/utils/regexes/nationalId.ts | 1 + 38 files changed, 935 insertions(+), 1203 deletions(-) rename public/locales/en/{sideMap.json => sideNav.json} (76%) delete mode 100644 public/locales/fa/sideMap.json create mode 100644 public/locales/fa/sideNav.json create mode 100644 src/utils/regexes/nationalId.ts diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 5196be8..bb3eeaf 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -1,254 +1,10 @@ { - "helloWorld": "hello world", - "country": { - "afghanistan": "Afghanistan", - "aland_islands": "Aland islands", - "albania": "Albania", - "algeria": "Algeria", - "american_samoa": "American samoa", - "andorra": "Andorra", - "angola": "Angola", - "anguilla": "Anguilla", - "antarctica": "Antarctica", - "antigua_and_barbuda": "Antigua and barbuda", - "argentina": "Argentina", - "armenia": "Armenia", - "aruba": "Aruba", - "australia": "Australia", - "austria": "Austria", - "azerbaijan": "Azerbaijan", - "bahamas": "Bahamas", - "bahrain": "Bahrain", - "bangladesh": "Bangladesh", - "barbados": "Barbados", - "belarus": "Belarus", - "belgium": "Belgium", - "belize": "Belize", - "benin": "Benin", - "bermuda": "Bermuda", - "bhutan": "Bhutan", - "bolivia": "Bolivia", - "bosnia_and_herzegovina": "Bosnia and herzegovina", - "botswana": "Botswana", - "brazil": "Brazil", - "british_indian_ocean_territory": "British indian ocean territory", - "british_virgin_islands": "British virgin islands", - "brunei": "Brunei", - "bulgaria": "Bulgaria", - "burkina_faso": "Burkina faso", - "burundi": "Burundi", - "cambodia": "Cambodia", - "cameroon": "Cameroon", - "canada": "Canada", - "cape_verde": "Cape verde", - "cayman_islands": "Cayman islands", - "central_african_republic": "Central african republic", - "chad": "Chad", - "chile": "Chile", - "china": "China", - "christmas_island": "Christmas island", - "cocos_keeling_islands": "Cocos keeling islands", - "colombia": "Colombia", - "comoros": "Comoros", - "congo_brazzaville": "Congo brazzaville", - "congo_kinshasa": "Congo kinshasa", - "cook_islands": "Cook islands", - "costa_rica": "Costa rica", - "cote_divoire": "Cote divoire", - "croatia": "Croatia", - "cuba": "Cuba", - "curacao": "Curacao", - "cyprus": "Cyprus", - "czech_republic": "Czech republic", - "denmark": "Denmark", - "djibouti": "Djibouti", - "dominica": "Dominica", - "dominican_republic": "Dominican republic", - "ecuador": "Ecuador", - "egypt": "Egypt", - "el_salvador": "El salvador", - "equatorial_guinea": "Equatorial guinea", - "eritrea": "Eritrea", - "estonia": "Estonia", - "eswatini": "Eswatini", - "ethiopia": "Ethiopia", - "falkland_islands": "Falkland islands", - "faroe_islands": "Faroe islands", - "fiji": "Fiji", - "finland": "Finland", - "france": "France", - "french_guiana": "French guiana", - "french_polynesia": "French polynesia", - "gabon": "Gabon", - "gambia": "Gambia", - "georgia": "Georgia", - "germany": "Germany", - "ghana": "Ghana", - "gibraltar": "Gibraltar", - "greece": "Greece", - "greenland": "Greenland", - "grenada": "Grenada", - "guadeloupe": "Guadeloupe", - "guam": "Guam", - "guatemala": "Guatemala", - "guernsey": "Guernsey", - "guinea": "Guinea", - "guinea_bissau": "Guinea bissau", - "guyana": "Guyana", - "haiti": "Haiti", - "honduras": "Honduras", - "hong_kong": "Hong kong", - "hungary": "Hungary", - "iceland": "Iceland", - "india": "India", - "indonesia": "Indonesia", - "iran": "Iran", - "iraq": "Iraq", - "ireland": "Ireland", - "isle_of_man": "Isle of man", - "israel": "Israel", - "italy": "Italy", - "jamaica": "Jamaica", - "japan": "Japan", - "jersey": "Jersey", - "jordan": "Jordan", - "kazakhstan": "Kazakhstan", - "kenya": "Kenya", - "kiribati": "Kiribati", - "kosovo": "Kosovo", - "kuwait": "Kuwait", - "kyrgyzstan": "Kyrgyzstan", - "laos": "Laos", - "latvia": "Latvia", - "lebanon": "Lebanon", - "lesotho": "Lesotho", - "liberia": "Liberia", - "libya": "Libya", - "liechtenstein": "Liechtenstein", - "lithuania": "Lithuania", - "luxembourg": "Luxembourg", - "macau": "Macau", - "madagascar": "Madagascar", - "malawi": "Malawi", - "malaysia": "Malaysia", - "maldives": "Maldives", - "mali": "Mali", - "malta": "Malta", - "marshall_islands": "Marshall islands", - "martinique": "Martinique", - "mauritania": "Mauritania", - "mauritius": "Mauritius", - "mayotte": "Mayotte", - "mexico": "Mexico", - "micronesia": "Micronesia", - "moldova": "Moldova", - "monaco": "Monaco", - "mongolia": "Mongolia", - "montenegro": "Montenegro", - "montserrat": "Montserrat", - "morocco": "Morocco", - "mozambique": "Mozambique", - "myanmar": "Myanmar", - "namibia": "Namibia", - "nauru": "Nauru", - "nepal": "Nepal", - "netherlands": "Netherlands", - "new_caledonia": "New caledonia", - "new_zealand": "New zealand", - "nicaragua": "Nicaragua", - "niger": "Niger", - "nigeria": "Nigeria", - "niue": "Niue", - "norfolk_island": "Norfolk island", - "north_korea": "North korea", - "north_macedonia": "North macedonia", - "northern_mariana_islands": "Northern mariana islands", - "norway": "Norway", - "oman": "Oman", - "pakistan": "Pakistan", - "palau": "Palau", - "palestine": "Palestine", - "panama": "Panama", - "papua_new_guinea": "Papua new guinea", - "paraguay": "Paraguay", - "peru": "Peru", - "philippines": "Philippines", - "pitcairn_islands": "Pitcairn islands", - "poland": "Poland", - "portugal": "Portugal", - "puerto_rico": "Puerto rico", - "qatar": "Qatar", - "reunion": "Reunion", - "romania": "Romania", - "russia": "Russia", - "rwanda": "Rwanda", - "saint_barthelemy": "Saint barthelemy", - "saint_helena": "Saint helena", - "saint_kitts_and_nevis": "Saint kitts and nevis", - "saint_lucia": "Saint lucia", - "saint_martin": "Saint martin", - "saint_pierre_and_miquelon": "Saint pierre and miquelon", - "saint_vincent_and_the_grenadines": "Saint vincent and the grenadines", - "samoa": "Samoa", - "san_marino": "San marino", - "sao_tome_and_principe": "Sao tome and principe", - "saudi_arabia": "Saudi arabia", - "senegal": "Senegal", - "serbia": "Serbia", - "seychelles": "Seychelles", - "sierra_leone": "Sierra leone", - "singapore": "Singapore", - "sint_maarten": "Sint maarten", - "slovakia": "Slovakia", - "slovenia": "Slovenia", - "solomon_islands": "Solomon islands", - "somalia": "Somalia", - "south_africa": "South africa", - "south_georgia_and_south_sandwich_islands": "South georgia and south sandwich islands", - "south_korea": "South korea", - "south_sudan": "South sudan", - "spain": "Spain", - "sri_lanka": "Sri lanka", - "sudan": "Sudan", - "suriname": "Suriname", - "svalbard_and_jan_mayen": "Svalbard and jan mayen", - "sweden": "Sweden", - "switzerland": "Switzerland", - "syria": "Syria", - "taiwan": "Taiwan", - "tajikistan": "Tajikistan", - "tanzania": "Tanzania", - "thailand": "Thailand", - "timor_leste": "Timor leste", - "togo": "Togo", - "tokelau": "Tokelau", - "tonga": "Tonga", - "trinidad_and_tobago": "Trinidad and tobago", - "tunisia": "Tunisia", - "turkey": "Turkey", - "turkmenistan": "Turkmenistan", - "turks_and_caicos_islands": "Turks and caicos islands", - "tuvalu": "Tuvalu", - "us_virgin_islands": "Us virgin islands", - "uganda": "Uganda", - "ukraine": "Ukraine", - "united_arab_emirates": "United arab emirates", - "united_kingdom": "United kingdom", - "united_states": "United states", - "uruguay": "Uruguay", - "uzbekistan": "Uzbekistan", - "vanuatu": "Vanuatu", - "vatican_city": "Vatican city", - "venezuela": "Venezuela", - "vietnam": "Vietnam", - "wallis_and_futuna": "Wallis and futuna", - "western_sahara": "Western sahara", - "yemen": "Yemen", - "zambia": "Zambia", - "zimbabwe": "Zimbabwe" + "labels": { + "search": "search" }, "messages": { "noResualtFound": "No result found.", - "serverError": "Internal server error" + "serverError": "Internal server error", + "networkError": "Network error. Please check your internet connection and try again." } } diff --git a/public/locales/en/completionForm.json b/public/locales/en/completionForm.json index 34572a5..77b3ae3 100644 --- a/public/locales/en/completionForm.json +++ b/public/locales/en/completionForm.json @@ -4,7 +4,7 @@ "description": "Enter your business information", "name": "Name", "familyName": "Family Name", - "gender": "Gender", + "gender": "Gender(Optional)", "optionalNationalCode": "National Code(Optional)", "determinePassword": "Determine Password", "password": "Password", @@ -23,8 +23,8 @@ "hasSpecialChar": "includes sign (!@#$%^&*)", "notCompatibility": "does not match", "emailCorrectForm": "Enter the correct email form.", - "agreementPart1": "By continuing the registration process, you agree to the", - "agreementLinkText": " Harmony Terms and Conditions", + "agreementPart1": "By continuing the registration process, you agree to the ", + "agreementLinkText": "Harmony Terms and Conditions", "agreementPart2": ".", "sent": "sent", "country": "country", @@ -34,5 +34,18 @@ "submitting": "Submitting...", "success": "Success", "agreement": "1. Confidentiality of Information: Harmony commits under no circumstances to disclose users’ identity information, such as phone numbers, email addresses, passwords, user IDs, or any related data, to third parties.\n\n2. User information is used solely for providing authentication services and remains confidential even after account deactivation or termination.\n\n3. Harmony is obliged to implement necessary security measures to prevent unauthorized access.\n\n4. Responsibility for Account Security: Users must protect their accounts and choose strong, non-guessable passwords. Periodic password changes and immediate action in case of suspected unauthorized access are required. Any misuse of the account due to user negligence is the responsibility of the user.\n\n5. Security Breaches and Cyber Attacks: Harmony is not responsible for security breaches caused by cyber attacks beyond the system's control. However, Harmony employs up-to-date security standards and encryption to prevent such incidents.\n\n6. User Negligence in Protecting Information: If account information is disclosed due to user negligence or error, Harmony bears no responsibility. Determining such cases, based on system security logs, is the responsibility of Harmony's technical manager.\n\n7. Accurate Logging of Activities: All events related to registering, editing, and deleting information in the system are accurately and immutably logged. Claims regarding deletion or modification of data without logs are invalid unless supported by documentation provided by the user.\n\n8. Service Updates: Harmony services may be updated or changed over time. Continued use of the system after changes implies acceptance of the new terms. If users disagree, they may request account deletion.\n\n9. User Support: Support is provided only via email and phone, free of charge. Harmony is not obligated to provide in-person support or training beyond basic services.\n\n10. Official Communication Channels: Harmony communicates with users only via the phone number and email registered in the user account. Official announcements are sent through these channels.\n\n11. Official Domains for Communication: All emails from Harmony are sent exclusively from the domain harmony.id. Users must verify this to prevent phishing or similar attacks.\n\n12. Compliance with Iranian Laws: Users must comply with all applicable laws of the Islamic Republic of Iran, including the “Electronic Commerce Law,” “Computer Crimes Law,” and related legislation. Responsibility for violations rests with the user.\n\n13. Temporary Data Retention After Account Termination: Upon account termination or deletion, user information is stored securely for 30 days and permanently deleted thereafter.\n\n14. Ownership of User Data: All data submitted by users belongs to them. Harmony has no ownership over this information. Users are responsible for the accuracy, quality, and legality of their data.\n\n15. Purposeful Use of Identity Information: Collected identity information during registration is used only for authentication and basic services. It will not be shared with any third party without explicit user consent, except under a court order or legal authority.\n\n16. Permanent Data Confidentiality: Harmony commits to maintaining confidentiality of collected information even after the end of the user relationship or account closure.\n\n17. Limitation of Liability: Harmony is not liable for direct or indirect damages resulting from use or inability to use the authentication services.\n\n18. Disruptions in Communication Infrastructure: Harmony is not responsible for disruptions caused by the internet, infrastructure services, or other issues beyond its control.\n\n19. Force Majeure and Unforeseen Events: Harmony bears no responsibility for natural disasters, strikes, power outages, cyber attacks, or other events beyond its control that prevent service delivery.\n\n20. Services Dependent on Third Parties: If parts of the authentication services are provided by third parties, the usage terms of those services are the responsibility of those companies, and Harmony bears no liability.\n\n21. Guarantee of Data Access in Case of Service Termination: If Harmony ceases operations permanently, it commits to keeping servers active for two years and allowing users access to their data.\n\n22. Notification of Service Interruptions: If service interruption is necessary, Harmony must notify users at least 12 hours in advance via email or SMS." + }, + "validation": { + "firstNameRequired": "First name is required.", + "lastNameRequired": "Last name is required.", + "countryRequired": "Country is required.", + "emailInvalid": "A valid email is required.", + "nationalIdInvalid": "National ID must be 10 digits.", + "passwordRequired": "Password is required.", + "passwordInvalid": "Password does not meet all the requirements.", + "confirmPasswordRequired": "Please confirm your password.", + "passwordsDoNotMatch": "Passwords do not match.", + "verificationCodeRequired": "Verification code is required.", + "mustVerifyCode": "Please click the verify button to confirm the code." } } diff --git a/public/locales/en/country.json b/public/locales/en/country.json index b874af3..0eed9d0 100644 --- a/public/locales/en/country.json +++ b/public/locales/en/country.json @@ -1,247 +1,249 @@ { - "country.afghanistan": "Afghanistan", - "country.aland_islands": "Aland islands", - "country.albania": "Albania", - "country.algeria": "Algeria", - "country.american_samoa": "American samoa", - "country.andorra": "Andorra", - "country.angola": "Angola", - "country.anguilla": "Anguilla", - "country.antarctica": "Antarctica", - "country.antigua_and_barbuda": "Antigua and barbuda", - "country.argentina": "Argentina", - "country.armenia": "Armenia", - "country.aruba": "Aruba", - "country.australia": "Australia", - "country.austria": "Austria", - "country.azerbaijan": "Azerbaijan", - "country.bahamas": "Bahamas", - "country.bahrain": "Bahrain", - "country.bangladesh": "Bangladesh", - "country.barbados": "Barbados", - "country.belarus": "Belarus", - "country.belgium": "Belgium", - "country.belize": "Belize", - "country.benin": "Benin", - "country.bermuda": "Bermuda", - "country.bhutan": "Bhutan", - "country.bolivia": "Bolivia", - "country.bosnia_and_herzegovina": "Bosnia and herzegovina", - "country.botswana": "Botswana", - "country.brazil": "Brazil", - "country.british_indian_ocean_territory": "British indian ocean territory", - "country.british_virgin_islands": "British virgin islands", - "country.brunei": "Brunei", - "country.bulgaria": "Bulgaria", - "country.burkina_faso": "Burkina faso", - "country.burundi": "Burundi", - "country.cambodia": "Cambodia", - "country.cameroon": "Cameroon", - "country.canada": "Canada", - "country.cape_verde": "Cape verde", - "country.cayman_islands": "Cayman islands", - "country.central_african_republic": "Central african republic", - "country.chad": "Chad", - "country.chile": "Chile", - "country.china": "China", - "country.christmas_island": "Christmas island", - "country.cocos_keeling_islands": "Cocos keeling islands", - "country.colombia": "Colombia", - "country.comoros": "Comoros", - "country.congo_brazzaville": "Congo brazzaville", - "country.congo_kinshasa": "Congo kinshasa", - "country.cook_islands": "Cook islands", - "country.costa_rica": "Costa rica", - "country.cote_divoire": "Cote divoire", - "country.croatia": "Croatia", - "country.cuba": "Cuba", - "country.curacao": "Curacao", - "country.cyprus": "Cyprus", - "country.czech_republic": "Czech republic", - "country.denmark": "Denmark", - "country.djibouti": "Djibouti", - "country.dominica": "Dominica", - "country.dominican_republic": "Dominican republic", - "country.ecuador": "Ecuador", - "country.egypt": "Egypt", - "country.el_salvador": "El salvador", - "country.equatorial_guinea": "Equatorial guinea", - "country.eritrea": "Eritrea", - "country.estonia": "Estonia", - "country.eswatini": "Eswatini", - "country.ethiopia": "Ethiopia", - "country.falkland_islands": "Falkland islands", - "country.faroe_islands": "Faroe islands", - "country.fiji": "Fiji", - "country.finland": "Finland", - "country.france": "France", - "country.french_guiana": "French guiana", - "country.french_polynesia": "French polynesia", - "country.gabon": "Gabon", - "country.gambia": "Gambia", - "country.georgia": "Georgia", - "country.germany": "Germany", - "country.ghana": "Ghana", - "country.gibraltar": "Gibraltar", - "country.greece": "Greece", - "country.greenland": "Greenland", - "country.grenada": "Grenada", - "country.guadeloupe": "Guadeloupe", - "country.guam": "Guam", - "country.guatemala": "Guatemala", - "country.guernsey": "Guernsey", - "country.guinea": "Guinea", - "country.guinea_bissau": "Guinea bissau", - "country.guyana": "Guyana", - "country.haiti": "Haiti", - "country.honduras": "Honduras", - "country.hong_kong": "Hong kong", - "country.hungary": "Hungary", - "country.iceland": "Iceland", - "country.india": "India", - "country.indonesia": "Indonesia", - "country.iran": "Iran", - "country.iraq": "Iraq", - "country.ireland": "Ireland", - "country.isle_of_man": "Isle of man", - "country.israel": "Israel", - "country.italy": "Italy", - "country.jamaica": "Jamaica", - "country.japan": "Japan", - "country.jersey": "Jersey", - "country.jordan": "Jordan", - "country.kazakhstan": "Kazakhstan", - "country.kenya": "Kenya", - "country.kiribati": "Kiribati", - "country.kosovo": "Kosovo", - "country.kuwait": "Kuwait", - "country.kyrgyzstan": "Kyrgyzstan", - "country.laos": "Laos", - "country.latvia": "Latvia", - "country.lebanon": "Lebanon", - "country.lesotho": "Lesotho", - "country.liberia": "Liberia", - "country.libya": "Libya", - "country.liechtenstein": "Liechtenstein", - "country.lithuania": "Lithuania", - "country.luxembourg": "Luxembourg", - "country.macau": "Macau", - "country.madagascar": "Madagascar", - "country.malawi": "Malawi", - "country.malaysia": "Malaysia", - "country.maldives": "Maldives", - "country.mali": "Mali", - "country.malta": "Malta", - "country.marshall_islands": "Marshall islands", - "country.martinique": "Martinique", - "country.mauritania": "Mauritania", - "country.mauritius": "Mauritius", - "country.mayotte": "Mayotte", - "country.mexico": "Mexico", - "country.micronesia": "Micronesia", - "country.moldova": "Moldova", - "country.monaco": "Monaco", - "country.mongolia": "Mongolia", - "country.montenegro": "Montenegro", - "country.montserrat": "Montserrat", - "country.morocco": "Morocco", - "country.mozambique": "Mozambique", - "country.myanmar": "Myanmar", - "country.namibia": "Namibia", - "country.nauru": "Nauru", - "country.nepal": "Nepal", - "country.netherlands": "Netherlands", - "country.new_caledonia": "New caledonia", - "country.new_zealand": "New zealand", - "country.nicaragua": "Nicaragua", - "country.niger": "Niger", - "country.nigeria": "Nigeria", - "country.niue": "Niue", - "country.norfolk_island": "Norfolk island", - "country.north_korea": "North korea", - "country.north_macedonia": "North macedonia", - "country.northern_mariana_islands": "Northern mariana islands", - "country.norway": "Norway", - "country.oman": "Oman", - "country.pakistan": "Pakistan", - "country.palau": "Palau", - "country.palestine": "Palestine", - "country.panama": "Panama", - "country.papua_new_guinea": "Papua new guinea", - "country.paraguay": "Paraguay", - "country.peru": "Peru", - "country.philippines": "Philippines", - "country.pitcairn_islands": "Pitcairn islands", - "country.poland": "Poland", - "country.portugal": "Portugal", - "country.puerto_rico": "Puerto rico", - "country.qatar": "Qatar", - "country.reunion": "Reunion", - "country.romania": "Romania", - "country.russia": "Russia", - "country.rwanda": "Rwanda", - "country.saint_barthelemy": "Saint barthelemy", - "country.saint_helena": "Saint helena", - "country.saint_kitts_and_nevis": "Saint kitts and nevis", - "country.saint_lucia": "Saint lucia", - "country.saint_martin": "Saint martin", - "country.saint_pierre_and_miquelon": "Saint pierre and miquelon", - "country.saint_vincent_and_the_grenadines": "Saint vincent and the grenadines", - "country.samoa": "Samoa", - "country.san_marino": "San marino", - "country.sao_tome_and_principe": "Sao tome and principe", - "country.saudi_arabia": "Saudi arabia", - "country.senegal": "Senegal", - "country.serbia": "Serbia", - "country.seychelles": "Seychelles", - "country.sierra_leone": "Sierra leone", - "country.singapore": "Singapore", - "country.sint_maarten": "Sint maarten", - "country.slovakia": "Slovakia", - "country.slovenia": "Slovenia", - "country.solomon_islands": "Solomon islands", - "country.somalia": "Somalia", - "country.south_africa": "South africa", - "country.south_georgia_and_south_sandwich_islands": "South georgia and south sandwich islands", - "country.south_korea": "South korea", - "country.south_sudan": "South sudan", - "country.spain": "Spain", - "country.sri_lanka": "Sri lanka", - "country.sudan": "Sudan", - "country.suriname": "Suriname", - "country.svalbard_and_jan_mayen": "Svalbard and jan mayen", - "country.sweden": "Sweden", - "country.switzerland": "Switzerland", - "country.syria": "Syria", - "country.taiwan": "Taiwan", - "country.tajikistan": "Tajikistan", - "country.tanzania": "Tanzania", - "country.thailand": "Thailand", - "country.timor_leste": "Timor leste", - "country.togo": "Togo", - "country.tokelau": "Tokelau", - "country.tonga": "Tonga", - "country.trinidad_and_tobago": "Trinidad and tobago", - "country.tunisia": "Tunisia", - "country.turkey": "Turkey", - "country.turkmenistan": "Turkmenistan", - "country.turks_and_caicos_islands": "Turks and caicos islands", - "country.tuvalu": "Tuvalu", - "country.us_virgin_islands": "Us virgin islands", - "country.uganda": "Uganda", - "country.ukraine": "Ukraine", - "country.united_arab_emirates": "United arab emirates", - "country.united_kingdom": "United kingdom", - "country.united_states": "United states", - "country.uruguay": "Uruguay", - "country.uzbekistan": "Uzbekistan", - "country.vanuatu": "Vanuatu", - "country.vatican_city": "Vatican city", - "country.venezuela": "Venezuela", - "country.vietnam": "Vietnam", - "country.wallis_and_futuna": "Wallis and futuna", - "country.western_sahara": "Western sahara", - "country.yemen": "Yemen", - "country.zambia": "Zambia", - "country.zimbabwe": "Zimbabwe" + "country": { + "afghanistan": "Afghanistan", + "aland_islands": "Aland islands", + "albania": "Albania", + "algeria": "Algeria", + "american_samoa": "American samoa", + "andorra": "Andorra", + "angola": "Angola", + "anguilla": "Anguilla", + "antarctica": "Antarctica", + "antigua_and_barbuda": "Antigua and barbuda", + "argentina": "Argentina", + "armenia": "Armenia", + "aruba": "Aruba", + "australia": "Australia", + "austria": "Austria", + "azerbaijan": "Azerbaijan", + "bahamas": "Bahamas", + "bahrain": "Bahrain", + "bangladesh": "Bangladesh", + "barbados": "Barbados", + "belarus": "Belarus", + "belgium": "Belgium", + "belize": "Belize", + "benin": "Benin", + "bermuda": "Bermuda", + "bhutan": "Bhutan", + "bolivia": "Bolivia", + "bosnia_and_herzegovina": "Bosnia and herzegovina", + "botswana": "Botswana", + "brazil": "Brazil", + "british_indian_ocean_territory": "British indian ocean territory", + "british_virgin_islands": "British virgin islands", + "brunei": "Brunei", + "bulgaria": "Bulgaria", + "burkina_faso": "Burkina faso", + "burundi": "Burundi", + "cambodia": "Cambodia", + "cameroon": "Cameroon", + "canada": "Canada", + "cape_verde": "Cape verde", + "cayman_islands": "Cayman islands", + "central_african_republic": "Central african republic", + "chad": "Chad", + "chile": "Chile", + "china": "China", + "christmas_island": "Christmas island", + "cocos_keeling_islands": "Cocos keeling islands", + "colombia": "Colombia", + "comoros": "Comoros", + "congo_brazzaville": "Congo brazzaville", + "congo_kinshasa": "Congo kinshasa", + "cook_islands": "Cook islands", + "costa_rica": "Costa rica", + "cote_divoire": "Cote divoire", + "croatia": "Croatia", + "cuba": "Cuba", + "curacao": "Curacao", + "cyprus": "Cyprus", + "czech_republic": "Czech republic", + "denmark": "Denmark", + "djibouti": "Djibouti", + "dominica": "Dominica", + "dominican_republic": "Dominican republic", + "ecuador": "Ecuador", + "egypt": "Egypt", + "el_salvador": "El salvador", + "equatorial_guinea": "Equatorial guinea", + "eritrea": "Eritrea", + "estonia": "Estonia", + "eswatini": "Eswatini", + "ethiopia": "Ethiopia", + "falkland_islands": "Falkland islands", + "faroe_islands": "Faroe islands", + "fiji": "Fiji", + "finland": "Finland", + "france": "France", + "french_guiana": "French guiana", + "french_polynesia": "French polynesia", + "gabon": "Gabon", + "gambia": "Gambia", + "georgia": "Georgia", + "germany": "Germany", + "ghana": "Ghana", + "gibraltar": "Gibraltar", + "greece": "Greece", + "greenland": "Greenland", + "grenada": "Grenada", + "guadeloupe": "Guadeloupe", + "guam": "Guam", + "guatemala": "Guatemala", + "guernsey": "Guernsey", + "guinea": "Guinea", + "guinea_bissau": "Guinea bissau", + "guyana": "Guyana", + "haiti": "Haiti", + "honduras": "Honduras", + "hong_kong": "Hong kong", + "hungary": "Hungary", + "iceland": "Iceland", + "india": "India", + "indonesia": "Indonesia", + "iran": "Iran", + "iraq": "Iraq", + "ireland": "Ireland", + "isle_of_man": "Isle of man", + "israel": "Israel", + "italy": "Italy", + "jamaica": "Jamaica", + "japan": "Japan", + "jersey": "Jersey", + "jordan": "Jordan", + "kazakhstan": "Kazakhstan", + "kenya": "Kenya", + "kiribati": "Kiribati", + "kosovo": "Kosovo", + "kuwait": "Kuwait", + "kyrgyzstan": "Kyrgyzstan", + "laos": "Laos", + "latvia": "Latvia", + "lebanon": "Lebanon", + "lesotho": "Lesotho", + "liberia": "Liberia", + "libya": "Libya", + "liechtenstein": "Liechtenstein", + "lithuania": "Lithuania", + "luxembourg": "Luxembourg", + "macau": "Macau", + "madagascar": "Madagascar", + "malawi": "Malawi", + "malaysia": "Malaysia", + "maldives": "Maldives", + "mali": "Mali", + "malta": "Malta", + "marshall_islands": "Marshall islands", + "martinique": "Martinique", + "mauritania": "Mauritania", + "mauritius": "Mauritius", + "mayotte": "Mayotte", + "mexico": "Mexico", + "micronesia": "Micronesia", + "moldova": "Moldova", + "monaco": "Monaco", + "mongolia": "Mongolia", + "montenegro": "Montenegro", + "montserrat": "Montserrat", + "morocco": "Morocco", + "mozambique": "Mozambique", + "myanmar": "Myanmar", + "namibia": "Namibia", + "nauru": "Nauru", + "nepal": "Nepal", + "netherlands": "Netherlands", + "new_caledonia": "New caledonia", + "new_zealand": "New zealand", + "nicaragua": "Nicaragua", + "niger": "Niger", + "nigeria": "Nigeria", + "niue": "Niue", + "norfolk_island": "Norfolk island", + "north_korea": "North korea", + "north_macedonia": "North macedonia", + "northern_mariana_islands": "Northern mariana islands", + "norway": "Norway", + "oman": "Oman", + "pakistan": "Pakistan", + "palau": "Palau", + "palestine": "Palestine", + "panama": "Panama", + "papua_new_guinea": "Papua new guinea", + "paraguay": "Paraguay", + "peru": "Peru", + "philippines": "Philippines", + "pitcairn_islands": "Pitcairn islands", + "poland": "Poland", + "portugal": "Portugal", + "puerto_rico": "Puerto rico", + "qatar": "Qatar", + "reunion": "Reunion", + "romania": "Romania", + "russia": "Russia", + "rwanda": "Rwanda", + "saint_barthelemy": "Saint barthelemy", + "saint_helena": "Saint helena", + "saint_kitts_and_nevis": "Saint kitts and nevis", + "saint_lucia": "Saint lucia", + "saint_martin": "Saint martin", + "saint_pierre_and_miquelon": "Saint pierre and miquelon", + "saint_vincent_and_the_grenadines": "Saint vincent and the grenadines", + "samoa": "Samoa", + "san_marino": "San marino", + "sao_tome_and_principe": "Sao tome and principe", + "saudi_arabia": "Saudi arabia", + "senegal": "Senegal", + "serbia": "Serbia", + "seychelles": "Seychelles", + "sierra_leone": "Sierra leone", + "singapore": "Singapore", + "sint_maarten": "Sint maarten", + "slovakia": "Slovakia", + "slovenia": "Slovenia", + "solomon_islands": "Solomon islands", + "somalia": "Somalia", + "south_africa": "South africa", + "south_georgia_and_south_sandwich_islands": "South georgia and south sandwich islands", + "south_korea": "South korea", + "south_sudan": "South sudan", + "spain": "Spain", + "sri_lanka": "Sri lanka", + "sudan": "Sudan", + "suriname": "Suriname", + "svalbard_and_jan_mayen": "Svalbard and jan mayen", + "sweden": "Sweden", + "switzerland": "Switzerland", + "syria": "Syria", + "taiwan": "Taiwan", + "tajikistan": "Tajikistan", + "tanzania": "Tanzania", + "thailand": "Thailand", + "timor_leste": "Timor leste", + "togo": "Togo", + "tokelau": "Tokelau", + "tonga": "Tonga", + "trinidad_and_tobago": "Trinidad and tobago", + "tunisia": "Tunisia", + "turkey": "Turkey", + "turkmenistan": "Turkmenistan", + "turks_and_caicos_islands": "Turks and caicos islands", + "tuvalu": "Tuvalu", + "us_virgin_islands": "Us virgin islands", + "uganda": "Uganda", + "ukraine": "Ukraine", + "united_arab_emirates": "United arab emirates", + "united_kingdom": "United kingdom", + "united_states": "United states", + "uruguay": "Uruguay", + "uzbekistan": "Uzbekistan", + "vanuatu": "Vanuatu", + "vatican_city": "Vatican city", + "venezuela": "Venezuela", + "vietnam": "Vietnam", + "wallis_and_futuna": "Wallis and futuna", + "western_sahara": "Western sahara", + "yemen": "Yemen", + "zambia": "Zambia", + "zimbabwe": "Zimbabwe" + } } diff --git a/public/locales/en/sideMap.json b/public/locales/en/sideNav.json similarity index 76% rename from public/locales/en/sideMap.json rename to public/locales/en/sideNav.json index 04428f3..bdb6e8a 100644 --- a/public/locales/en/sideMap.json +++ b/public/locales/en/sideNav.json @@ -3,11 +3,11 @@ "account": "Account", "personalInfo": "Personal information", "phoneNumber": "Phone number", + "contactInfo": "Contact info", "email": "Email", "security": "Security", "password": "Password", - "verifiedAddress": "Verified addresses", - "recentLogins": "Recent logins", + "recentSessions": "Recent Sessions", "activeDevices": "Active devices", "settings": "Settings" } diff --git a/public/locales/fa/common.json b/public/locales/fa/common.json index 878b22d..a19bc43 100644 --- a/public/locales/fa/common.json +++ b/public/locales/fa/common.json @@ -2,202 +2,9 @@ "labels": { "search": "جست و جو" }, - "country": { - "afghanistan": "افغانستان", - "aland_islands": "جزایر آلند", - "albania": "آلبانی", - "algeria": "الجزایر", - "american_samoa": "ساموای آمریکایی", - "andorra": "آندورا", - "angola": "آنگولا", - "anguilla": "آنگویلا", - "antarctica": "جنوبگان", - "antigua_and_barbuda": "آنتیگوا و باربودا", - "argentina": "آرژانتین", - "armenia": "ارمنستان", - "aruba": "آروبا", - "australia": "استرالیا", - "austria": "اتریش", - "azerbaijan": "آذربایجان", - "bahamas": "باهاما", - "bahrain": "بحرین", - "bangladesh": "بنگلادش", - "barbados": "باربادوس", - "belarus": "بلاروس", - "belgium": "بلژیک", - "belize": "بلیز", - "benin": "بنین", - "bermuda": "برمودا", - "bhutan": "بوتان", - "bolivia": "بولیوی", - "bosnia_and_herzegovina": "بوسنی و هرزگوین", - "botswana": "بوتسوانا", - "brazil": "برزیل", - "british_virgin_islands": "جزایر ویرجین بریتانیا", - "brunei": "برونئی", - "bulgaria": "بلغارستان", - "burkina_faso": "بورکینافاسو", - "burundi": "بوروندی", - "cambodia": "کامبوج", - "cameroon": "کامرون", - "canada": "کانادا", - "cape_verde": "کیپ ورد", - "cayman_islands": "جزایر کیمن", - "central_african_republic": "جمهوری آفریقای مرکزی", - "chad": "چاد", - "chile": "شیلی", - "china": "چین", - "colombia": "کلمبیا", - "comoros": "کومور", - "costa_rica": "کاستاریکا", - "cote_divoire": "ساحل عاج", - "croatia": "کرواسی", - "cuba": "کوبا", - "cyprus": "قبرس", - "czech_republic": "جمهوری چک", - "denmark": "دانمارک", - "djibouti": "جیبوتی", - "dominica": "دومینیکا", - "dominican_republic": "جمهوری دومینیکن", - "ecuador": "اکوادور", - "egypt": "مصر", - "el_salvador": "السالوادور", - "equatorial_guinea": "گینه استوایی", - "eritrea": "اریتره", - "estonia": "استونی", - "eswatini": "سوازیلند", - "ethiopia": "اتیوپی", - "fiji": "فیجی", - "finland": "فنلاند", - "france": "فرانسه", - "gabon": "گابن", - "gambia": "گامبیا", - "georgia": "گرجستان", - "germany": "آلمان", - "ghana": "غنا", - "greece": "یونان", - "guatemala": "گواتمالا", - "guinea": "گینه", - "guinea_bissau": "گینه بیسائو", - "guyana": "گویان", - "haiti": "هائیتی", - "honduras": "هندوراس", - "hungary": "مجارستان", - "iceland": "ایسلند", - "india": "هندوستان", - "indonesia": "اندونزی", - "iran": "ایران", - "iraq": "عراق", - "ireland": "ایرلند", - "israel": "اسرائیل", - "italy": "ایتالیا", - "jamaica": "جامائیکا", - "japan": "ژاپن", - "jordan": "اردن", - "kazakhstan": "قزاقستان", - "kenya": "کنیا", - "kuwait": "کویت", - "kyrgyzstan": "قرقیزستان", - "laos": "لائوس", - "latvia": "لتونی", - "lebanon": "لبنان", - "lesotho": "لسوتو", - "liberia": "لیبریا", - "libya": "لیبی", - "luxembourg": "لوکزامبورگ", - "malaysia": "مالزی", - "maldives": "مالدیو", - "mali": "مالی", - "malta": "مالت", - "mauritania": "موریتانی", - "mauritius": "موریس", - "mexico": "مکزیک", - "moldova": "مولداوی", - "monaco": "موناکو", - "mongolia": "مغولستان", - "morocco": "مراکش", - "mozambique": "موزامبیک", - "myanmar": "میانمار", - "namibia": "نامیبیا", - "nepal": "نپال", - "netherlands": "هلند", - "new_zealand": "نیوزیلند", - "nicaragua": "نیکاراگوئه", - "niger": "نیجر", - "nigeria": "نیجریه", - "north_korea": "کره شمالی", - "north_macedonia": "مقدونیه", - "norway": "نروژ", - "oman": "عمان", - "pakistan": "پاکستان", - "palau": "پالائو", - "panama": "پاناما", - "papua_new_guinea": "پاپوآ گینه نو", - "paraguay": "پاراگوئه", - "peru": "پرو", - "philippines": "فیلیپین", - "poland": "لهستان", - "portugal": "پرتغال", - "qatar": "قطر", - "romania": "رومانی", - "russia": "روسیه", - "rwanda": "رواندا", - "saudi_arabia": "عربستان سعودی", - "senegal": "سنگال", - "serbia": "صربستان", - "seychelles": "سیشل", - "sierra_leone": "سیرالئون", - "singapore": "سنگاپور", - "south_africa": "آفریقای جنوبی", - "south_korea": "کره جنوبی", - "south_sudan": "سودان جنوبی", - "spain": "اسپانیا", - "sri_lanka": "سری‌لانکا", - "sudan": "سودان", - "suriname": "سورینام", - "sweden": "سوئد", - "switzerland": "سوئیس", - "syria": "سوریه", - "taiwan": "تایوان", - "tajikistan": "تاجیکستان", - "tanzania": "تانزانیا", - "thailand": "تایلند", - "timor_leste": "تیمور شرقی", - "togo": "توگو", - "tonga": "تونگا", - "trinidad_and_tobago": "ترینیداد و توباگو", - "tunisia": "تونس", - "turkey": "ترکیه", - "turkmenistan": "ترکمنستان", - "tuvalu": "تووالو", - "uganda": "اوگاندا", - "ukraine": "اوکراین", - "united_arab_emirates": "امارات متحده عربی", - "united_kingdom": "انگلستان", - "united_states": "ایالات متحده آمریکا", - "uruguay": "اروگوئه", - "uzbekistan": "ازبکستان", - "vanuatu": "وانواتو", - "venezuela": "ونزوئلا", - "vietnam": "ویتنام", - "yemen": "یمن", - "zambia": "زامبیا", - "zimbabwe": "زیمبابوه" - }, "messages": { "noResualtFound": "نتیجه ای یافت نشد.", - "serverError": "خطای سمت سرور" - }, - "side": { - "account": "حساب کاربری", - "personalInfo": "اطلاعات شخصی", - "contactInfo": "شماره تماس", - "email": "ایمیل", - "security": "امنیت", - "password": "رمز عبور", - "confirmedIps": "آدرس های تایید شده", - "recentSessions": "ورود های اخیر", - "activeSessions": "نشست های فعال", - "setting": "تنظیمات" + "serverError": "خطای سمت سرور", + "networkError": "خطای شبکه. لطفاً اتصال اینترنت خود را بررسی کرده و دوباره تلاش کنید." } } diff --git a/public/locales/fa/completionForm.json b/public/locales/fa/completionForm.json index 273ea69..c8f12c9 100644 --- a/public/locales/fa/completionForm.json +++ b/public/locales/fa/completionForm.json @@ -4,7 +4,7 @@ "description": "اطلاعات کسب و کار خود را وارد کنید", "name": "نام", "familyName": "نام خانوادگی", - "gender": "جنسیت", + "gender": "جنسیت(اختیاری)", "optionalNationalCode": "کدملی(اختیاری)", "determinePassword": "تعیین رمز عبور", "password": "رمز عبور", @@ -23,9 +23,9 @@ "hasSpecialChar": "شامل علامت (!@#$%^&*)", "notCompatibility": "تکرار رمز عبور با رمز عبور یکسان نمی باشد", "emailCorrectForm": "ساختار ایمیل صحیح نیست", - "agreementPart1": " ادامه فرایند ثبت نام به منزله تایید و قبول", - "agreementLinkText": " قوانین و مقررات هارمونی", - "agreementPart2": "می باشد.", + "agreementPart1": "ادامه فرایند ثبت نام به منزله تایید و قبول ", + "agreementLinkText": "قوانین و مقررات هارمونی", + "agreementPart2": " می باشد.", "sent": "ارسال شد!", "country": "کشور", "dateOfBirth": "تاریخ تولد(اختیاری)", @@ -42,5 +42,18 @@ "codeVerified": "کد با موفقیت تایید شد", "invalidCode": "کد نامعتبر است", "agreement": "۱. محرمانگی اطلاعات هارمونی متعهد می‌شود تحت هیچ شرایطی اطلاعات هویتی کاربران نظیر شماره تلفن، ایمیل، رمز عبور، شناسه کاربری و هرگونه داده مرتبط را در اختیار اشخاص ثالث قرار ندهد. اطلاعات کاربران صرفاً در چارچوب ارائه خدمات احراز هویت مورد استفاده قرار گرفته و حتی پس از غیرفعال‌سازی حساب یا قطع همکاری، این اطلاعات محرمانه باقی خواهد ماند. هارمونی موظف به پیاده‌سازی تدابیر امنیتی لازم برای جلوگیری از هرگونه دسترسی غیرمجاز می‌باشد.\n\n۲. مسئولیت حفظ اطلاعات ورود: کاربر موظف است از حساب کاربری خود محافظت کند و رمز عبوری ایمن و غیرقابل حدس انتخاب نماید. تغییر دوره‌ای رمز عبور و اقدام فوری در صورت احساس خطر دسترسی غیرمجاز الزامی است. مسئولیت هرگونه سوءاستفاده از حساب کاربری به دلیل بی‌احتیاطی کاربر، بر عهده خود وی خواهد بود.\n\n۳. رخنه‌های امنیتی و حملات سایبری: هارمونی در برابر رخنه‌های امنیتی ناشی از حملات سایبری که خارج از کنترل سیستم است، مسئولیتی ندارد. با این حال، هارمونی از به‌روزترین استانداردهای امنیتی و رمزنگاری برای جلوگیری از چنین حوادثی بهره می‌برد.\n\n۴. قصور کاربر در حفاظت از اطلاعات: چنانچه اطلاعات حساب کاربری به دلیل سهل‌انگاری یا اشتباه کاربر افشا شود، هارمونی مسئولیتی در این خصوص ندارد. تشخیص چنین مواردی بر اساس لاگ‌های امنیتی سیستم، بر عهده مدیر فنی هارمونی خواهد بود.\n\n۵. ثبت دقیق فعالیت‌ها در لاگ‌ها: تمامی رویدادهای مرتبط با ثبت، ویرایش و حذف اطلاعات در سیستم، به‌صورت دقیق و غیرقابل‌تغییر در لاگ کاربران ثبت می‌گردد. هرگونه ادعا مبنی بر حذف یا تغییر داده‌ها بدون ردپای لاگ قابل پذیرش نیست مگر با ارائه مستندات از سوی کاربر.\n\n۶. به‌روزرسانی خدمات: خدمات هارمونی ممکن است به مرور زمان به‌روزرسانی یا تغییر پیدا کند. ادامه استفاده از سیستم پس از اعمال تغییرات به معنای پذیرش مقررات جدید است. در صورت عدم موافقت، کاربر می‌تواند درخواست حذف حساب خود را ارائه دهد.\n\n۷. پشتیبانی کاربران: پشتیبانی خدمات صرفاً از طریق ایمیل و تماس تلفنی صورت می‌گیرد و رایگان است. هارمونی تعهدی به ارائه پشتیبانی حضوری یا آموزش‌های فراتر از خدمات پایه ندارد.\n\n۸. راه‌های ارتباط رسمی: هارمونی تنها از طریق شماره تلفن و ایمیل ثبت‌شده در حساب کاربر با وی در ارتباط خواهد بود. اطلاعیه‌ها و اعلانات رسمی از این مسیرها انجام می‌گیرد.\n\n۹. دامنه‌های رسمی ارتباط: تمام ایمیل‌های ارسالی از سوی هارمونی صرفاً با دامنه‌ی harmony.id ارسال می‌شود. کاربران موظف به بررسی این نشانی برای جلوگیری از فیشینگ و حملات مشابه هستند.\n\n۱۰. رعایت قوانین جمهوری اسلامی ایران: کاربر موظف است در استفاده از سیستم، کلیه قوانین جاری کشور، از جمله «قانون تجارت الکترونیکی»، «قانون جرائم رایانه‌ای» و سایر قوانین مرتبط را رعایت نماید. مسئولیت هرگونه تخلف بر عهده کاربر خواهد بود.\n\n۱۱. نگهداری موقت اطلاعات پس از فسخ حساب: در صورت فسخ یا حذف حساب، اطلاعات کاربر به مدت ۳۰ روز در فضای امن نگهداری می‌شود و پس از آن، به‌طور غیرقابل‌بازگشت حذف خواهد شد.\n\n۱۲. مالکیت اطلاعات کاربر: تمام اطلاعات ثبت‌شده توسط کاربر متعلق به خود اوست و هارمونی هیچ‌گونه مالکیتی بر این اطلاعات ندارد. کاربر مسئول صحت، کیفیت و قانونی بودن داده‌های خود می‌باشد.\n\n۱۳. استفاده هدفمند از اطلاعات شناسایی: اطلاعات هویتی جمع‌آوری‌شده هنگام ثبت‌نام تنها برای احراز هویت و ارائه خدمات پایه مورد استفاده قرار می‌گیرد. این اطلاعات بدون رضایت صریح کاربر، به هیچ نهاد یا شخص ثالثی منتقل نخواهد شد. تبصره: اطلاعات هویتی کاربران صرفاً در صورت حکم مقام قضایی یا مراجع ذی‌صلاح و در چارچوب قوانین، قابل ارائه خواهد بود.\n\n۱۴. محرمانگی دائمی داده‌ها: هارمونی متعهد است حتی پس از اتمام رابطه کاربری یا انحلال حساب، اطلاعات جمع‌آوری‌شده را به عنوان محرمانه حفظ نماید.\n\n۱۵. محدودیت مسئولیت: هارمونی مسئولیتی در قبال خسارات مستقیم یا غیرمستقیمی که به دلیل استفاده یا عدم استفاده از خدمات احراز هویت ایجاد شود، نخواهد داشت.\n\n۱۶. اختلال در بسترهای ارتباطی: هارمونی در برابر اختلال‌های ناشی از شبکه اینترنت، خدمات زیرساختی یا هرگونه مشکل خارج از کنترل خود، مسئولیتی ندارد.\n\n۱۷. حوادث قهری و غیرمترقبه: در صورت وقوع بلایای طبیعی، اعتصاب، قطعی برق، حملات سایبری یا هرگونه رخداد خارج از کنترل هارمونی که مانع ارائه خدمات شود، مسئولیتی متوجه هارمونی نخواهد بود.\n\n۱۸. خدمات وابسته به سایر سرویس‌ها: چنانچه بخشی از خدمات احراز هویت توسط شرکت‌های ثالث ارائه شود، قوانین استفاده از این سرویس‌ها بر عهده همان شرکت‌هاست و هارمونی نسبت به آن‌ها مسئولیتی ندارد.\n\n۱۹. تضمین دسترسی به اطلاعات در صورت توقف فعالیت: در صورت توقف دائمی فعالیت هارمونی، این شرکت متعهد است به مدت دو سال، سرورها را فعال نگه دارد و امکان دسترسی کاربران به اطلاعات خود را فراهم سازد.\n\n۲۰. اطلاع‌رسانی در مورد قطع سرویس‌ها: در صورت نیاز به توقف خدمات، هارمونی موظف است حداقل ۱۲ ساعت قبل، این موضوع را از طریق ایمیل یا پیامک به اطلاع کاربران برساند." + }, + "validation": { + "firstNameRequired": "وارد کردن نام الزامی است.", + "lastNameRequired": "وارد کردن نام خانوادگی الزامی است.", + "countryRequired": "انتخاب کشور الزامی است.", + "emailInvalid": "ایمیل معتبر وارد کنید.", + "nationalIdInvalid": "کد ملی باید ۱۰ رقم باشد.", + "passwordRequired": "وارد کردن رمز عبور الزامی است.", + "passwordInvalid": "رمز عبور تمام شرایط را ندارد.", + "confirmPasswordRequired": "لطفاً رمز عبور خود را تکرار کنید.", + "passwordsDoNotMatch": "رمزهای عبور با یکدیگر مطابقت ندارند.", + "verificationCodeRequired": "وارد کردن کد تایید الزامی است.", + "mustVerifyCode": "لطفاً برای تایید کد، روی دکمه بررسی کلیک کنید." } } diff --git a/public/locales/fa/country.json b/public/locales/fa/country.json index 0da70cf..40e2441 100644 --- a/public/locales/fa/country.json +++ b/public/locales/fa/country.json @@ -1,182 +1,184 @@ { - "country.afghanistan": "افغانستان", - "country.aland_islands": "جزایر آلند", - "country.albania": "آلبانی", - "country.algeria": "الجزایر", - "country.american_samoa": "ساموای آمریکایی", - "country.andorra": "آندورا", - "country.angola": "آنگولا", - "country.anguilla": "آنگویلا", - "country.antarctica": "جنوبگان", - "country.antigua_and_barbuda": "آنتیگوا و باربودا", - "country.argentina": "آرژانتین", - "country.armenia": "ارمنستان", - "country.aruba": "آروبا", - "country.australia": "استرالیا", - "country.austria": "اتریش", - "country.azerbaijan": "آذربایجان", - "country.bahamas": "باهاما", - "country.bahrain": "بحرین", - "country.bangladesh": "بنگلادش", - "country.barbados": "باربادوس", - "country.belarus": "بلاروس", - "country.belgium": "بلژیک", - "country.belize": "بلیز", - "country.benin": "بنین", - "country.bermuda": "برمودا", - "country.bhutan": "بوتان", - "country.bolivia": "بولیوی", - "country.bosnia_and_herzegovina": "بوسنی و هرزگوین", - "country.botswana": "بوتسوانا", - "country.brazil": "برزیل", - "country.british_virgin_islands": "جزایر ویرجین بریتانیا", - "country.brunei": "برونئی", - "country.bulgaria": "بلغارستان", - "country.burkina_faso": "بورکینافاسو", - "country.burundi": "بوروندی", - "country.cambodia": "کامبوج", - "country.cameroon": "کامرون", - "country.canada": "کانادا", - "country.cape_verde": "کیپ ورد", - "country.cayman_islands": "جزایر کیمن", - "country.central_african_republic": "جمهوری آفریقای مرکزی", - "country.chad": "چاد", - "country.chile": "شیلی", - "country.china": "چین", - "country.colombia": "کلمبیا", - "country.comoros": "کومور", - "country.costa_rica": "کاستاریکا", - "country.cote_divoire": "ساحل عاج", - "country.croatia": "کرواسی", - "country.cuba": "کوبا", - "country.cyprus": "قبرس", - "country.czech_republic": "جمهوری چک", - "country.denmark": "دانمارک", - "country.djibouti": "جیبوتی", - "country.dominica": "دومینیکا", - "country.dominican_republic": "جمهوری دومینیکن", - "country.ecuador": "اکوادور", - "country.egypt": "مصر", - "country.el_salvador": "السالوادور", - "country.equatorial_guinea": "گینه استوایی", - "country.eritrea": "اریتره", - "country.estonia": "استونی", - "country.eswatini": "سوازیلند", - "country.ethiopia": "اتیوپی", - "country.fiji": "فیجی", - "country.finland": "فنلاند", - "country.france": "فرانسه", - "country.gabon": "گابن", - "country.gambia": "گامبیا", - "country.georgia": "گرجستان", - "country.germany": "آلمان", - "country.ghana": "غنا", - "country.greece": "یونان", - "country.guatemala": "گواتمالا", - "country.guinea": "گینه", - "country.guinea_bissau": "گینه بیسائو", - "country.guyana": "گویان", - "country.haiti": "هائیتی", - "country.honduras": "هندوراس", - "country.hungary": "مجارستان", - "country.iceland": "ایسلند", - "country.india": "هندوستان", - "country.indonesia": "اندونزی", - "country.iran": "ایران", - "country.iraq": "عراق", - "country.ireland": "ایرلند", - "country.israel": "اسرائیل", - "country.italy": "ایتالیا", - "country.jamaica": "جامائیکا", - "country.japan": "ژاپن", - "country.jordan": "اردن", - "country.kazakhstan": "قزاقستان", - "country.kenya": "کنیا", - "country.kuwait": "کویت", - "country.kyrgyzstan": "قرقیزستان", - "country.laos": "لائوس", - "country.latvia": "لتونی", - "country.lebanon": "لبنان", - "country.lesotho": "لسوتو", - "country.liberia": "لیبریا", - "country.libya": "لیبی", - "country.luxembourg": "لوکزامبورگ", - "country.malaysia": "مالزی", - "country.maldives": "مالدیو", - "country.mali": "مالی", - "country.malta": "مالت", - "country.mauritania": "موریتانی", - "country.mauritius": "موریس", - "country.mexico": "مکزیک", - "country.moldova": "مولداوی", - "country.monaco": "موناکو", - "country.mongolia": "مغولستان", - "country.morocco": "مراکش", - "country.mozambique": "موزامبیک", - "country.myanmar": "میانمار", - "country.namibia": "نامیبیا", - "country.nepal": "نپال", - "country.netherlands": "هلند", - "country.new_zealand": "نیوزیلند", - "country.nicaragua": "نیکاراگوئه", - "country.niger": "نیجر", - "country.nigeria": "نیجریه", - "country.north_korea": "کره شمالی", - "country.north_macedonia": "مقدونیه", - "country.norway": "نروژ", - "country.oman": "عمان", - "country.pakistan": "پاکستان", - "country.palau": "پالائو", - "country.panama": "پاناما", - "country.papua_new_guinea": "پاپوآ گینه نو", - "country.paraguay": "پاراگوئه", - "country.peru": "پرو", - "country.philippines": "فیلیپین", - "country.poland": "لهستان", - "country.portugal": "پرتغال", - "country.qatar": "قطر", - "country.romania": "رومانی", - "country.russia": "روسیه", - "country.rwanda": "رواندا", - "country.saudi_arabia": "عربستان سعودی", - "country.senegal": "سنگال", - "country.serbia": "صربستان", - "country.seychelles": "سیشل", - "country.sierra_leone": "سیرالئون", - "country.singapore": "سنگاپور", - "country.south_africa": "آفریقای جنوبی", - "country.south_korea": "کره جنوبی", - "country.south_sudan": "سودان جنوبی", - "country.spain": "اسپانیا", - "country.sri_lanka": "سری‌لانکا", - "country.sudan": "سودان", - "country.suriname": "سورینام", - "country.sweden": "سوئد", - "country.switzerland": "سوئیس", - "country.syria": "سوریه", - "country.taiwan": "تایوان", - "country.tajikistan": "تاجیکستان", - "country.tanzania": "تانزانیا", - "country.thailand": "تایلند", - "country.timor_leste": "تیمور شرقی", - "country.togo": "توگو", - "country.tonga": "تونگا", - "country.trinidad_and_tobago": "ترینیداد و توباگو", - "country.tunisia": "تونس", - "country.turkey": "ترکیه", - "country.turkmenistan": "ترکمنستان", - "country.tuvalu": "تووالو", - "country.uganda": "اوگاندا", - "country.ukraine": "اوکراین", - "country.united_arab_emirates": "امارات متحده عربی", - "country.united_kingdom": "انگلستان", - "country.united_states": "ایالات متحده آمریکا", - "country.uruguay": "اروگوئه", - "country.uzbekistan": "ازبکستان", - "country.vanuatu": "وانواتو", - "country.venezuela": "ونزوئلا", - "country.vietnam": "ویتنام", - "country.yemen": "یمن", - "country.zambia": "زامبیا", - "country.zimbabwe": "زیمبابوه" + "country": { + "afghanistan": "افغانستان", + "aland_islands": "جزایر آلند", + "albania": "آلبانی", + "algeria": "الجزایر", + "american_samoa": "ساموای آمریکایی", + "andorra": "آندورا", + "angola": "آنگولا", + "anguilla": "آنگویلا", + "antarctica": "جنوبگان", + "antigua_and_barbuda": "آنتیگوا و باربودا", + "argentina": "آرژانتین", + "armenia": "ارمنستان", + "aruba": "آروبا", + "australia": "استرالیا", + "austria": "اتریش", + "azerbaijan": "آذربایجان", + "bahamas": "باهاما", + "bahrain": "بحرین", + "bangladesh": "بنگلادش", + "barbados": "باربادوس", + "belarus": "بلاروس", + "belgium": "بلژیک", + "belize": "بلیز", + "benin": "بنین", + "bermuda": "برمودا", + "bhutan": "بوتان", + "bolivia": "بولیوی", + "bosnia_and_herzegovina": "بوسنی و هرزگوین", + "botswana": "بوتسوانا", + "brazil": "برزیل", + "british_virgin_islands": "جزایر ویرجین بریتانیا", + "brunei": "برونئی", + "bulgaria": "بلغارستان", + "burkina_faso": "بورکینافاسو", + "burundi": "بوروندی", + "cambodia": "کامبوج", + "cameroon": "کامرون", + "canada": "کانادا", + "cape_verde": "کیپ ورد", + "cayman_islands": "جزایر کیمن", + "central_african_republic": "جمهوری آفریقای مرکزی", + "chad": "چاد", + "chile": "شیلی", + "china": "چین", + "colombia": "کلمبیا", + "comoros": "کومور", + "costa_rica": "کاستاریکا", + "cote_divoire": "ساحل عاج", + "croatia": "کرواسی", + "cuba": "کوبا", + "cyprus": "قبرس", + "czech_republic": "جمهوری چک", + "denmark": "دانمارک", + "djibouti": "جیبوتی", + "dominica": "دومینیکا", + "dominican_republic": "جمهوری دومینیکن", + "ecuador": "اکوادور", + "egypt": "مصر", + "el_salvador": "السالوادور", + "equatorial_guinea": "گینه استوایی", + "eritrea": "اریتره", + "estonia": "استونی", + "eswatini": "سوازیلند", + "ethiopia": "اتیوپی", + "fiji": "فیجی", + "finland": "فنلاند", + "france": "فرانسه", + "gabon": "گابن", + "gambia": "گامبیا", + "georgia": "گرجستان", + "germany": "آلمان", + "ghana": "غنا", + "greece": "یونان", + "guatemala": "گواتمالا", + "guinea": "گینه", + "guinea_bissau": "گینه بیسائو", + "guyana": "گویان", + "haiti": "هائیتی", + "honduras": "هندوراس", + "hungary": "مجارستان", + "iceland": "ایسلند", + "india": "هندوستان", + "indonesia": "اندونزی", + "iran": "ایران", + "iraq": "عراق", + "ireland": "ایرلند", + "israel": "اسرائیل", + "italy": "ایتالیا", + "jamaica": "جامائیکا", + "japan": "ژاپن", + "jordan": "اردن", + "kazakhstan": "قزاقستان", + "kenya": "کنیا", + "kuwait": "کویت", + "kyrgyzstan": "قرقیزستان", + "laos": "لائوس", + "latvia": "لتونی", + "lebanon": "لبنان", + "lesotho": "لسوتو", + "liberia": "لیبریا", + "libya": "لیبی", + "luxembourg": "لوکزامبورگ", + "malaysia": "مالزی", + "maldives": "مالدیو", + "mali": "مالی", + "malta": "مالت", + "mauritania": "موریتانی", + "mauritius": "موریس", + "mexico": "مکزیک", + "moldova": "مولداوی", + "monaco": "موناکو", + "mongolia": "مغولستان", + "morocco": "مراکش", + "mozambique": "موزامبیک", + "myanmar": "میانمار", + "namibia": "نامیبیا", + "nepal": "نپال", + "netherlands": "هلند", + "new_zealand": "نیوزیلند", + "nicaragua": "نیکاراگوئه", + "niger": "نیجر", + "nigeria": "نیجریه", + "north_korea": "کره شمالی", + "north_macedonia": "مقدونیه", + "norway": "نروژ", + "oman": "عمان", + "pakistan": "پاکستان", + "palau": "پالائو", + "panama": "پاناما", + "papua_new_guinea": "پاپوآ گینه نو", + "paraguay": "پاراگوئه", + "peru": "پرو", + "philippines": "فیلیپین", + "poland": "لهستان", + "portugal": "پرتغال", + "qatar": "قطر", + "romania": "رومانی", + "russia": "روسیه", + "rwanda": "رواندا", + "saudi_arabia": "عربستان سعودی", + "senegal": "سنگال", + "serbia": "صربستان", + "seychelles": "سیشل", + "sierra_leone": "سیرالئون", + "singapore": "سنگاپور", + "south_africa": "آفریقای جنوبی", + "south_korea": "کره جنوبی", + "south_sudan": "سودان جنوبی", + "spain": "اسپانیا", + "sri_lanka": "سری‌لانکا", + "sudan": "سودان", + "suriname": "سورینام", + "sweden": "سوئد", + "switzerland": "سوئیس", + "syria": "سوریه", + "taiwan": "تایوان", + "tajikistan": "تاجیکستان", + "tanzania": "تانزانیا", + "thailand": "تایلند", + "timor_leste": "تیمور شرقی", + "togo": "توگو", + "tonga": "تونگا", + "trinidad_and_tobago": "ترینیداد و توباگو", + "tunisia": "تونس", + "turkey": "ترکیه", + "turkmenistan": "ترکمنستان", + "tuvalu": "تووالو", + "uganda": "اوگاندا", + "ukraine": "اوکراین", + "united_arab_emirates": "امارات متحده عربی", + "united_kingdom": "انگلستان", + "united_states": "ایالات متحده آمریکا", + "uruguay": "اروگوئه", + "uzbekistan": "ازبکستان", + "vanuatu": "وانواتو", + "venezuela": "ونزوئلا", + "vietnam": "ویتنام", + "yemen": "یمن", + "zambia": "زامبیا", + "zimbabwe": "زیمبابوه" + } } diff --git a/public/locales/fa/sideMap.json b/public/locales/fa/sideMap.json deleted file mode 100644 index fd2238a..0000000 --- a/public/locales/fa/sideMap.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "side": { - "account": "حساب کاربری", - "personalInfo": "اطلاعات شخصی", - "phoneNumber": "شماره تماس", - "email": "ایمیل", - "security": "امنیت", - "password": "رمز عبور", - "verifiedAddress": "آدرس های تایید شده", - "recentLogins": "ورود های اخیر", - "activeDevices": "دستگاه های فعال", - "settings": "تنظیمات" - } -} diff --git a/public/locales/fa/sideNav.json b/public/locales/fa/sideNav.json new file mode 100644 index 0000000..166eda6 --- /dev/null +++ b/public/locales/fa/sideNav.json @@ -0,0 +1,13 @@ +{ + "side": { + "account": "حساب کاربری", + "personalInfo": "اطلاعات شخصی", + "contactInfo": "شماره تماس", + "email": "ایمیل", + "security": "امنیت", + "password": "رمز عبور", + "recentSessions": "ورود های اخیر", + "activeSessions": "نشست های فعال", + "setting": "تنظیمات" + } +} diff --git a/src/components/CardContainer.tsx b/src/components/CardContainer.tsx index 2159df7..aa35019 100644 --- a/src/components/CardContainer.tsx +++ b/src/components/CardContainer.tsx @@ -33,7 +33,7 @@ export function CardContainer({ justifyContent: 'space-between', alignItems: { xs: 'flex-start', sm: 'center' }, flexDirection: { xs: 'column', sm: 'row' }, - bgcolor: highlighted ? 'primary.light' : 'background.default', + bgcolor: highlighted ? 'background.primary' : 'background.default', p: 2, borderRadius: 1, gap: { xs: 1, sm: 0 }, diff --git a/src/components/Layout/Header.tsx b/src/components/Layout/Header.tsx index 729c651..9121b43 100644 --- a/src/components/Layout/Header.tsx +++ b/src/components/Layout/Header.tsx @@ -1,4 +1,4 @@ -import { Box, IconButton, Skeleton, Typography } from '@mui/material'; +import { Box, IconButton, Typography } from '@mui/material'; import { Icon } from '@rkheftan/harmony-ui'; import { More } from 'iconsax-react'; import type { UserInfo } from '@/contexts/AuthContext'; @@ -7,7 +7,7 @@ interface HeaderProps { user: UserInfo; } -export const Header: React.FC = ({ user, loading }) => { +export const Header: React.FC = ({ user }) => { return ( = ({ setSideNavOpen, isMobile, user, - loading, }) => { return ( t.spacing(isMobile ? 8 : 10.5), + bgcolor: 'background.paper', px: isMobile ? 3 : 2, borderBottom: (t) => `1px solid ${t.palette.divider}`, boxSizing: 'content-box', diff --git a/src/components/Layout/buildNavItems.tsx b/src/components/Layout/buildNavItems.tsx index 4cfaba0..d54aa7d 100644 --- a/src/components/Layout/buildNavItems.tsx +++ b/src/components/Layout/buildNavItems.tsx @@ -10,8 +10,9 @@ const getIcon = (icon?: Iconsax) => (isSelected: boolean) => ) : undefined; +// TODO: make this a hook export function buildNavItems(routes: RouteConfig[]): NavItemConfig[] { - const { t } = useTranslation(); + const { t } = useTranslation('sideNav'); return routes.flatMap((route) => { // Check if route itself does not have a navItem but its child has diff --git a/src/components/Loading.tsx b/src/components/Loading.tsx index 1572b6a..6790bd5 100644 --- a/src/components/Loading.tsx +++ b/src/components/Loading.tsx @@ -1,5 +1,4 @@ import { CircularProgress, Stack } from '@mui/material'; -import React from 'react'; export const Loading = () => { return ( @@ -7,7 +6,7 @@ export const Loading = () => { sx={{ alignItems: 'center', justifyContent: 'center', - backgroundColor: (t) => t.palette.background.default, + backgroundColor: 'background.default', position: 'fixed', inset: '0', zIndex: (t) => t.zIndex.tooltip + 1, diff --git a/src/features/authorization/api/userCompletion.ts b/src/features/authorization/api/userCompletion.ts index efb03fc..0f133a6 100644 --- a/src/features/authorization/api/userCompletion.ts +++ b/src/features/authorization/api/userCompletion.ts @@ -5,6 +5,7 @@ import { } from '../types/completionFormApiTypes'; import apiClient from '@/lib/apiClient'; +// TODO: define generic type export const sendEmailOtpApi = async (payload: SendEmailOtpPayload) => { return apiClient.post('/User/SendEmailOtp', payload); }; diff --git a/src/features/authorization/components/AccountCreated/AccountCreated.tsx b/src/features/authorization/components/AccountCreated/AccountCreated.tsx index ba49095..bee3d4d 100644 --- a/src/features/authorization/components/AccountCreated/AccountCreated.tsx +++ b/src/features/authorization/components/AccountCreated/AccountCreated.tsx @@ -1,6 +1,6 @@ -import React, { useMemo, useState } from 'react'; +import { useMemo } from 'react'; import { AuthenticationCard } from '../AuthenticationCard'; -import { Box, CardHeader, Divider, Stack, Typography } from '@mui/material'; +import { Box, Divider, Stack, Typography } from '@mui/material'; import AccountCreatedIcon from '@/assets/account-created.svg'; import { useTranslation } from 'react-i18next'; import { Link as RouterLink, useSearchParams } from 'react-router-dom'; diff --git a/src/features/authorization/components/AccountCreated/AccountCreatedClubBanner.tsx b/src/features/authorization/components/AccountCreated/AccountCreatedClubBanner.tsx index 213e17c..ca8b7a3 100644 --- a/src/features/authorization/components/AccountCreated/AccountCreatedClubBanner.tsx +++ b/src/features/authorization/components/AccountCreated/AccountCreatedClubBanner.tsx @@ -1,7 +1,5 @@ import { Stack, Typography, useTheme } from '@mui/material'; -import { Icon } from '@rkheftan/harmony-ui'; -import { Box, Profile2User } from 'iconsax-react'; -import React from 'react'; +import { Profile2User } from 'iconsax-react'; import { useTranslation } from 'react-i18next'; export const AccountCreatedClubBanner = () => { @@ -10,6 +8,7 @@ export const AccountCreatedClubBanner = () => { return ( + {/* FIXME: Replace with Club Logo (this icon is placeholder) */} diff --git a/src/features/authorization/components/AccountCreated/AccountCreatedRedirectButton.tsx b/src/features/authorization/components/AccountCreated/AccountCreatedRedirectButton.tsx index 1cd78cb..199652c 100644 --- a/src/features/authorization/components/AccountCreated/AccountCreatedRedirectButton.tsx +++ b/src/features/authorization/components/AccountCreated/AccountCreatedRedirectButton.tsx @@ -1,6 +1,6 @@ import { useMemo } from 'react'; import type { RequestedApplication } from './AccountCreated'; -import { Box, Button, useTheme } from '@mui/material'; +import { Box, Button } from '@mui/material'; import { useTranslation } from 'react-i18next'; import { CountDownTimer } from '@/components/CountDownTimer'; import type { PalleteColor } from '@/theme/palette'; diff --git a/src/features/authorization/components/AuthenticationCard.tsx b/src/features/authorization/components/AuthenticationCard.tsx index 6a9b136..444b83e 100644 --- a/src/features/authorization/components/AuthenticationCard.tsx +++ b/src/features/authorization/components/AuthenticationCard.tsx @@ -1,20 +1,22 @@ -import { Paper } from '@mui/material'; +import { Paper, type SxProps, type Theme } from '@mui/material'; import { type PropsWithChildren } from 'react'; export interface AuthenticationCardProps extends PropsWithChildren { maxWidth?: string; + sx?: SxProps; } // Beacuse in the otp verify there is a element outside of the authentication card export const AuthenticationCard = ({ children, maxWidth, + sx, }: AuthenticationCardProps) => { return ( `calc(100% - ${t.spacing(2)})`, maxWidth: maxWidth ?? '552px', + + ...sx, }} > {children} diff --git a/src/features/authorization/components/AuthenticationSteps/AuthenticationSteps.tsx b/src/features/authorization/components/AuthenticationSteps/AuthenticationSteps.tsx index 344427b..bd5ca98 100644 --- a/src/features/authorization/components/AuthenticationSteps/AuthenticationSteps.tsx +++ b/src/features/authorization/components/AuthenticationSteps/AuthenticationSteps.tsx @@ -6,7 +6,7 @@ import { isNumeric } from '@/utils/regexes/isNumeric'; import { CompleteSignUp } from './CompleteSignUp'; import { EnterPasswordForm } from './EnterPasswordForm'; import { UserStatus } from '../../types/userTypes'; -import type { CountryCode, GUID } from '@/types/commonTypes'; +import type { CountryCode } from '@/types/commonTypes'; import { VerifyPhoneNumber } from './VerifyPhoneNumber'; import { useNavigate, useSearchParams } from 'react-router-dom'; diff --git a/src/features/authorization/components/CountryCodeSelector.tsx b/src/features/authorization/components/CountryCodeSelector.tsx index 575c839..2aa9709 100644 --- a/src/features/authorization/components/CountryCodeSelector.tsx +++ b/src/features/authorization/components/CountryCodeSelector.tsx @@ -40,7 +40,7 @@ export function CountryCodeSelector({ const open = Boolean(anchorEl); const searchInputRef = useRef(null); const menuWidth = menuAnchor ? menuAnchor.clientWidth : 'auto'; - const { t, i18n } = useTranslation(); + const { t, i18n } = useTranslation(['country', 'common']); const selectedCountry = countries.find((c) => c.phone === value) || countries[0]; @@ -176,7 +176,7 @@ export function CountryCodeSelector({ inputRef={searchInputRef} size="small" fullWidth - label={t('labels.search')} + label={t('labels.search', { ns: 'common' })} value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)} /> @@ -207,7 +207,7 @@ export function CountryCodeSelector({ }} /> - + {country.phone} diff --git a/src/features/authorization/components/UserCompletionForm/DateOfBirth.tsx b/src/features/authorization/components/UserCompletionForm/DateOfBirth.tsx index 10a2c29..ecf6d99 100644 --- a/src/features/authorization/components/UserCompletionForm/DateOfBirth.tsx +++ b/src/features/authorization/components/UserCompletionForm/DateOfBirth.tsx @@ -61,8 +61,13 @@ export default function DateOfBirth({ value, onChange }: DateOfBirthProps) { slotProps={{ textField: { fullWidth: true, + }, + popper: { sx: { - flex: '1 1 260px', + '& .MuiDateCalendar-root': { + // TODO: fix this to use textfield width instead of defining hardcode + width: '309px', + }, }, }, }} diff --git a/src/features/authorization/components/UserCompletionForm/EmailSection.tsx b/src/features/authorization/components/UserCompletionForm/EmailSection.tsx index 341faa0..c57dd18 100644 --- a/src/features/authorization/components/UserCompletionForm/EmailSection.tsx +++ b/src/features/authorization/components/UserCompletionForm/EmailSection.tsx @@ -8,41 +8,45 @@ import { Typography, InputAdornment, IconButton, - CircularProgress, } from '@mui/material'; import { useTranslation } from 'react-i18next'; import { TickCircle, Edit } from 'iconsax-react'; import { Icon } from '@rkheftan/harmony-ui'; import { type EmailSectionProps } from '../../types/settingForm'; +import { toLocaleDigits } from '@/utils/persianDigit'; export function EmailSection({ showEmail, setShowEmail, email, setEmail, - correctEmail, codeSent, verificationCode, setVerificationCode, buttonState, - getButtonLabel, handleSendCode, handleVerifyCode, emailVerified, - loading, + isVerifyingCode, + isSendingCode, handleEditEmail, + errors, + touched, + handleBlur, + countdown, }: EmailSectionProps) { - const { t } = useTranslation('completionForm'); - - const onSendCodeClick = () => { - if (!correctEmail) return; - handleSendCode(); - }; + const { t, i18n } = useTranslation('completionForm'); const handleToggleEmail = (e: React.ChangeEvent) => { setShowEmail(e.target.checked); }; + const formatTimerValue = () => { + const m = String(Math.floor(countdown / 60)).padStart(2, '0'); + const s = String(countdown % 60).padStart(2, '0'); + return toLocaleDigits(`${m}:${s}`, i18n.language); + }; + return ( <> @@ -51,7 +55,6 @@ export function EmailSection({ display: 'flex', alignItems: 'center', gap: 1, - px: { xs: 2, sm: 0 }, }} > @@ -84,13 +87,16 @@ export function EmailSection({ variant="outlined" fullWidth value={email} + autoFocus onChange={(e) => setEmail(e.target.value)} - error={email.length > 0 && !correctEmail} + onBlur={() => handleBlur('email')} + error={touched.email && !!errors.email} + helperText={touched.email && errors.email} sx={{ flex: '1 1 260px' }} slotProps={{ input: { startAdornment: - !loading && emailVerified ? ( + !isVerifyingCode && emailVerified ? ( - {!loading && !emailVerified && ( - - )} + {!isVerifyingCode && + !emailVerified && + (buttonState === 'counting' ? ( + + {formatTimerValue()} + + ) : ( + + ))} - {email && ( - - {correctEmail ? '' : t('completion.emailCorrectForm')} - - )} - {!emailVerified && codeSent && correctEmail && ( + {!emailVerified && codeSent && ( setVerificationCode(e.target.value)} sx={{ flex: '1 1 260px' }} - disabled={loading} + disabled={isVerifyingCode} + onBlur={() => handleBlur('verificationCode')} + error={touched.verificationCode && !!errors.verificationCode} + helperText={touched.verificationCode && errors.verificationCode} /> )} diff --git a/src/features/authorization/components/UserCompletionForm/PasswordSection.tsx b/src/features/authorization/components/UserCompletionForm/PasswordSection.tsx index 7ef1d26..9254980 100644 --- a/src/features/authorization/components/UserCompletionForm/PasswordSection.tsx +++ b/src/features/authorization/components/UserCompletionForm/PasswordSection.tsx @@ -28,6 +28,9 @@ export function PasswordSection({ hasSpecialChar, validPassword, showValidations, + errors, + touched, + handleBlur, }: PasswordSectionProps) { const { t } = useTranslation('completionForm'); const [showPasswordText, setShowPasswordText] = useState(false); @@ -51,7 +54,6 @@ export function PasswordSection({ sx={{ display: 'flex', gap: 0.5, - px: { xs: 2, sm: -4 }, alignItems: 'center', }} > @@ -75,7 +77,6 @@ export function PasswordSection({ display: 'flex', flexDirection: 'column', gap: 2, - px: { xs: 2, sm: 0 }, }} > setPassword(e.target.value)} variant="outlined" type={showPasswordText ? 'text' : 'password'} + autoFocus + onBlur={() => handleBlur('password')} + error={touched.password && !!errors.password} + helperText={touched.password && errors.password} sx={{ flex: '1 1 260px', '& .MuiInputBase-input': { pr: 8, // Increased padding to accommodate both icons }, }} + // FIXME: deprecated InputProps={{ endAdornment: ( @@ -146,12 +152,9 @@ export function PasswordSection({ variant="outlined" value={confirmPassword} onChange={(e) => setConfirmPassword(e.target.value)} - error={confirmPassword.length > 0 && !matchPassword} - helperText={ - confirmPassword.length > 0 && !matchPassword - ? t('completion.notCompatibility') - : ' ' - } + onBlur={() => handleBlur('confirmPassword')} + error={touched.confirmPassword && !!errors.confirmPassword} + helperText={touched.confirmPassword && errors.confirmPassword} type={showPasswordRepetitionText ? 'text' : 'password'} sx={{ flex: '1 1 260px', @@ -205,7 +208,7 @@ export function PasswordSection({ sx={{ display: 'flex', flexWrap: 'wrap', - gap: 2, + gap: { xs: 0, sm: 2 }, justifyContent: { xs: 'center', sm: 'flex-start' }, }} > diff --git a/src/features/authorization/components/UserCompletionForm/PersonalInfoFields.tsx b/src/features/authorization/components/UserCompletionForm/PersonalInfoFields.tsx index b33ad35..0fc74b1 100644 --- a/src/features/authorization/components/UserCompletionForm/PersonalInfoFields.tsx +++ b/src/features/authorization/components/UserCompletionForm/PersonalInfoFields.tsx @@ -30,12 +30,15 @@ export function PersonalInfoFields({ setSex, country, setCountry, + errors, + touched, + handleBlur, }: PersonalInfoFieldsProps) { - const { t } = useTranslation('completionForm'); + const { t } = useTranslation(['completionForm', 'country']); const countryOptions = countries.map((c) => ({ code: c.code, - label: t(c.label, { ns: 'countries' }), + label: t(c.label, { ns: 'country' }), })); const currentCountry = countryOptions.find((c) => c.code === country) || null; @@ -67,7 +70,6 @@ export function PersonalInfoFields({ flexDirection: 'column', gap: 2, width: '100%', - px: { xs: 2, sm: 4, md: 1 }, }} > setFirstName(e.target.value)} sx={{ flex: '1 1 260px' }} + onBlur={() => handleBlur('firstName')} + error={touched.firstName && !!errors.firstName} + helperText={touched.firstName && errors.firstName} /> setLastName(e.target.value)} sx={{ flex: '1 1 260px' }} + onBlur={() => handleBlur('lastName')} + error={touched.lastName && !!errors.lastName} + helperText={touched.lastName && errors.lastName} /> @@ -107,7 +115,7 @@ export function PersonalInfoFields({ {t('completion.gender')} - {genderOptions.map((g) => ( - - - - {g.label} - - - ))} - - + + setLastName(e.target.value)} + onBlur={() => handleBlur('lastName')} + error={touched.lastName && !!errors.lastName} + helperText={touched.lastName && errors.lastName} + /> + - setNationalId(e.target.value)} - variant="outlined" - sx={{ flex: '1 1 260px' }} - onBlur={() => handleBlur('nationalId')} - error={touched.nationalId && !!errors.nationalId} - helperText={touched.nationalId && errors.nationalId} - /> - + + + {t('completion.gender')} + - - option.label} - value={currentCountry} - onChange={(_, newValue) => setCountry(newValue?.code || '')} - onBlur={() => handleBlur('country')} - renderOption={(props, option) => ( - - - {option.label} - - )} - renderInput={(params) => ( - {errors.sex} + )} + + + + + option.label} + noOptionsText={t('completion.noOption')} + value={currentCountry} + onChange={(_, newValue) => setCountry(newValue?.code || '')} + onBlur={() => handleBlur('country')} + renderOption={(props, option) => ( + + - )} - clearOnEscape - /> + {option.label} + + )} + renderInput={(params) => ( + + )} + clearOnEscape + /> + - - - - - - + + setNationalId(e.target.value)} + variant="outlined" + onBlur={() => handleBlur('nationalId')} + error={touched.nationalId && !!errors.nationalId} + helperText={touched.nationalId && errors.nationalId} + /> + + + + + + ); } diff --git a/src/features/authorization/components/UserCompletionForm/SubmitSection.tsx b/src/features/authorization/components/UserCompletionForm/SubmitSection.tsx index 982a40a..0e97f19 100644 --- a/src/features/authorization/components/UserCompletionForm/SubmitSection.tsx +++ b/src/features/authorization/components/UserCompletionForm/SubmitSection.tsx @@ -28,9 +28,8 @@ export function SubmitSection({ onSubmit, loading }: SubmitProps) { display: 'flex', flexWrap: 'wrap', gap: 2, - px: { xs: 2, sm: 0 }, mb: 2, - justifyContent: { xs: 'center', sm: 'flex-start' }, + justifyContent: 'flex-start', }} > ({}); const [touched, setTouched] = useState<{ [key: string]: boolean }>({}); @@ -73,10 +72,6 @@ export function UserCompletionPage() { completeUserInformationApi, ); - useEffect(() => { - setShowPasswordValidations(password ? !validPassword : false); - }, [password, validPassword]); - useEffect(() => { let timer: NodeJS.Timeout; if (buttonState === 'counting' && countdown > 0) { @@ -101,6 +96,17 @@ export function UserCompletionPage() { return; } + setTouched((prev) => { + const newTouched = { ...prev }; + delete newTouched.verificationCode; + return newTouched; + }); + setErrors((prev) => { + const newErrors = { ...prev }; + delete newErrors.verificationCode; + return newErrors; + }); + const res = await sendCode({ email }); if (res) { @@ -122,14 +128,23 @@ export function UserCompletionPage() { }; const handleVerifyCode = async () => { - if (!verificationCode.trim()) { - // Manually trigger the validation error and stop + const trimmedCode = verificationCode.trim(); + + // Manually trigger the validation error and stop + if (!trimmedCode) { setTouched((prev) => ({ ...prev, verificationCode: true })); setErrors((prev) => ({ ...prev, verificationCode: t('validation.verificationCodeRequired'), })); return; + } else if (trimmedCode.length < 4) { + setTouched((prev) => ({ ...prev, verificationCode: true })); + setErrors((prev) => ({ + ...prev, + verificationCode: t('validation.verificationCodeInvalid'), + })); + return; } const res = await verifyCode({ email, otpCode: verificationCode }); @@ -161,6 +176,7 @@ export function UserCompletionPage() { verificationCode: showEmail, password: showPasswordSection, confirmPassword: showPasswordSection, + sex: true, }); const isValid = validateForm(); @@ -207,10 +223,22 @@ export function UserCompletionPage() { setCodeSent(false); setEmailVerified(false); setVerificationCode(''); + // We clear both touched and errors + setTouched((prev) => { + const newTouched = { ...prev }; + delete newTouched.email; + delete newTouched.verificationCode; + return newTouched; + }); + setErrors((prev) => { + const newErrors = { ...prev }; + delete newErrors.email; + delete newErrors.verificationCode; + return newErrors; + }); }; const validateForm = () => { - // TODO: check if need separate validation or same common validation const newErrors: { [key: string]: string } = {}; // Rule 1: First Name is required @@ -235,11 +263,16 @@ export function UserCompletionPage() { // Rule 6: If verification code sent and email section is active if (showEmail && codeSent && !emailVerified) { - if (!verificationCode.trim()) { + const trimmedCode = verificationCode.trim(); + + if (!trimmedCode) { // Case 1: The code is required but the field is empty. newErrors.verificationCode = t('validation.verificationCodeRequired'); + } else if (trimmedCode.length < 4) { + // Case 2 : The code is entered but is less than 4 digits. + newErrors.verificationCode = t('validation.verificationCodeInvalid'); } else { - // Case 2: The user has typed a code but hasn't clicked "Verify" yet. + // Case 3: The user has typed a code but hasn't clicked "Verify" yet. newErrors.verificationCode = t('validation.mustVerifyCode'); } } @@ -263,6 +296,10 @@ export function UserCompletionPage() { } } + if (sex === null) { + newErrors.sex = t('validation.genderRequired'); + } + setErrors(newErrors); return Object.keys(newErrors).length === 0; // Returns true if form is valid }; @@ -271,6 +308,43 @@ export function UserCompletionPage() { setTouched((prev) => ({ ...prev, [field]: true })); }; + useEffect(() => { + if (!showPasswordSection) { + // We clear both touched and errors to prevent lingering validation messages + setTouched((prev) => { + const newTouched = { ...prev }; + delete newTouched.password; + delete newTouched.confirmPassword; + return newTouched; + }); + setErrors((prev) => { + const newErrors = { ...prev }; + delete newErrors.password; + delete newErrors.confirmPassword; + return newErrors; + }); + } + }, [showPasswordSection]); + + // This effect resets email fields when the section is hidden + useEffect(() => { + if (!showEmail) { + // We clear both touched and errors + setTouched((prev) => { + const newTouched = { ...prev }; + delete newTouched.email; + delete newTouched.verificationCode; + return newTouched; + }); + setErrors((prev) => { + const newErrors = { ...prev }; + delete newErrors.email; + delete newErrors.verificationCode; + return newErrors; + }); + } + }, [showEmail]); + // re-validate whenever a field the user has touched changes value useEffect(() => { // Only run validation if at least one field has been touched @@ -289,6 +363,7 @@ export function UserCompletionPage() { password, confirmPassword, showPasswordSection, + sex, touched, ]); @@ -300,17 +375,16 @@ export function UserCompletionPage() { sx={{ minHeight: '100vh', gap: 3, - // TODO: check if this padding needed for mobile view - py: { sm: 0, xs: 2 }, + py: { md: 0, xs: 4 }, }} > @@ -361,7 +435,6 @@ export function UserCompletionPage() { hasUpperAndLower={hasUpperAndLower} hasSpecialChar={hasSpecialChar} validPassword={validPassword} - showValidations={showPasswordValidations} errors={errors} touched={touched} handleBlur={handleBlur} diff --git a/src/features/authorization/types/settingForm.ts b/src/features/authorization/types/settingForm.ts index 5fa7bc8..68d7030 100644 --- a/src/features/authorization/types/settingForm.ts +++ b/src/features/authorization/types/settingForm.ts @@ -49,7 +49,6 @@ export interface PasswordSectionProps extends ValidationProps { hasUpperAndLower: boolean; hasSpecialChar: boolean; validPassword: boolean; - showValidations: boolean; } export interface ValidationItemProps {