Skip to content

Commit a1dfb27

Browse files
Release v0.0.5 (#18)
* feat: init base of feature * chore: remove loading only in fail in signin * feat: add i18n * feat: update roadmap docs * feat: update github templates * feat: add i18n in mobile * refactor: create navbar dashboard component and add languague selector in dashboard * chore: update future roadmap * chore: create issue finalized markdown template * fix: add vercel json to use public in static * fix: get locale in production with fetch * chore: remove vercel file * fix: moving locales to src * chore: move location to src * chore: remove useless locale public files * chore: add env.example in project github * Create CI/CD Pipeline for Build and Testing Before Deployment to Vercel enhancement New feature or request (#12) * feat: create pipeline * fix: pull request template * fix: run pipeline in all branches * chore: fix pipeline using env * chore: fix pipeline using env 2 * chore: update ci pipeline * chore: add all supabase vars * chore: update packages * feat: add Multi-Currency Support in Stripe (#14) * Add Localization and Translations (#16) * chore: add sections translations * feat: add ssr locale function * refactor: language selector component * feat: add all home translation * feat: add i18n in terms and privacy page * chore: translate all auth domain * chore: add i18n in payment area * chore: add dashboard translation * feat: add portugues i18n * chore: add currency in client * chore: refactor constants * Refactor and Tax Adaptation (#17) * chore: add sections translations * feat: add ssr locale function * refactor: language selector component * feat: add all home translation * feat: add i18n in terms and privacy page * chore: translate all auth domain * chore: add i18n in payment area * chore: add dashboard translation * feat: add portugues i18n * chore: add currency in client * chore: refactor constants * refactor: create optional tax adapt currency * chore: solving conflits 2 * chore: add translations again
1 parent 24019a9 commit a1dfb27

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1390
-449
lines changed

docs/feature-roadmap.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
| **Feature** | **Status** |
2020
|----------------------------------------------------|------------|
2121
| Integration with Transactional Emails ||
22+
| Notification Integration ||
2223
| Custom Webhooks for Notifications ||
2324
| Team Features ||
2425

public/locales/en-US.json

Lines changed: 202 additions & 0 deletions
Large diffs are not rendered by default.

public/locales/pt-BR.json

Lines changed: 202 additions & 0 deletions
Large diffs are not rendered by default.

src/app/(domains)/(auth)/confirm-signup/page.tsx

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { useEffect, useReducer } from "react";
44

55
import BackLink from "@/components/BackLink";
66
import Spinner from "@/components/Spinner";
7+
import { useI18n } from '@/hooks/useI18n';
78
import { supabase } from "@/libs/supabase/client";
89
import SupabaseService from "@/services/supabase";
910

@@ -25,7 +26,7 @@ function confirmationReducer(state: State, action: ConfirmSignupAction): State {
2526
case "CONFIRMATION_SUCCESS":
2627
return { ...state, isLoading: false, isConfirmed: true, isConfirmedOAuh: true, error: null };
2728
case "CONFIRMATION_OAUTH":
28-
return { ...state, isLoading: false, isConfirmed: false, isConfirmedOAuh: true, error: null, };
29+
return { ...state, isLoading: false, isConfirmed: false, isConfirmedOAuh: true, error: null };
2930
case "CONFIRMATION_FAILURE":
3031
return { ...state, isLoading: false, isConfirmed: false, isConfirmedOAuh: true, error: action.error };
3132
case "SET_LOADING":
@@ -36,6 +37,7 @@ function confirmationReducer(state: State, action: ConfirmSignupAction): State {
3637
}
3738

3839
export default function ConfirmSignUp() {
40+
const { translate } = useI18n();
3941
const [state, dispatch] = useReducer(confirmationReducer, {
4042
isLoading: true,
4143
error: null,
@@ -53,26 +55,26 @@ export default function ConfirmSignUp() {
5355
} else if (!token && oauth) {
5456
dispatch({ type: "CONFIRMATION_OAUTH" });
5557
} else {
56-
dispatch({ type: "CONFIRMATION_FAILURE", error: "Invalid or missing token." });
58+
dispatch({ type: "CONFIRMATION_FAILURE", error: translate("confirm-signup-error-token-missing") });
5759
}
5860
}, []);
5961

6062
async function handleConfirmSignup(token: string) {
6163
dispatch({ type: "SET_LOADING", isLoading: true });
6264
const SupabaseServiceInstance = new SupabaseService(supabase);
63-
65+
6466
try {
6567
const response = await SupabaseServiceInstance.confirmEmail(token, 'signup');
6668
if (response?.id) {
6769
dispatch({ type: "CONFIRMATION_SUCCESS" });
6870
} else {
69-
throw new Error("Email confirmation failed. Please try again.");
71+
throw new Error(translate("confirm-signup-error-failed"));
7072
}
7173
} catch (error: unknown) {
7274
if (error instanceof Error) {
7375
dispatch({ type: "CONFIRMATION_FAILURE", error: error.message });
7476
} else {
75-
dispatch({ type: "CONFIRMATION_FAILURE", error: "An unexpected error occurred." });
77+
dispatch({ type: "CONFIRMATION_FAILURE", error: translate("confirm-signup-error-unexpected") });
7678
}
7779
}
7880
};
@@ -96,23 +98,28 @@ export default function ConfirmSignUp() {
9698

9799
const ErrorMessage = ({ message }: { message: string }) => (
98100
<div className="text-red-600">
99-
<h2 className="text-2xl font-semibold text-center">Error</h2>
100-
<p className="text-center text-sm">{message}</p>
101+
<h2 className="text-2xl font-semibold text-center">{message}</h2>
101102
</div>
102103
);
103104

104-
const ConfirmationMessage = () => (
105-
<>
106-
<BackLink href='/signin' label='Back To Login' />
107-
<h2 className="text-2xl font-semibold text-center text-gray-900">Email Confirmed</h2>
108-
<p className="text-center text-sm text-gray-600">Your email has been successfully confirmed.</p>
109-
</>
110-
);
105+
const ConfirmationMessage = () => {
106+
const { translate } = useI18n();
107+
return (
108+
<>
109+
<BackLink href='/signin' label={translate("confirm-signup-back-to-login")} />
110+
<h2 className="text-2xl font-semibold text-center text-gray-900">{translate("confirm-signup-email-confirmed")}</h2>
111+
<p className="text-center text-sm text-gray-600">{translate("confirm-signup-success-message")}</p>
112+
</>
113+
);
114+
};
111115

112-
const ConfirmationOAuthMessage = () => (
113-
<>
114-
<BackLink href='/dashboard' label='Go To Dashboard' />
115-
<h2 className="text-2xl font-semibold text-center text-gray-900">OAuth Successfully</h2>
116-
<p className="text-center text-sm text-gray-600">Your provider has been confirmed register.</p>
117-
</>
118-
);
116+
const ConfirmationOAuthMessage = () => {
117+
const { translate } = useI18n();
118+
return (
119+
<>
120+
<BackLink href='/dashboard' label={translate("confirm-signup-go-to-dashboard")} />
121+
<h2 className="text-2xl font-semibold text-center text-gray-900">{translate("confirm-signup-oauth-success")}</h2>
122+
<p className="text-center text-sm text-gray-600">{translate("confirm-signup-oauth-success-message")}</p>
123+
</>
124+
);
125+
};

src/app/(domains)/(auth)/forgot-password/page.tsx

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { useReducer } from "react";
55
import BackLinkComponent from "@/components/BackLink";
66
import ButtonComponent from "@/components/Button";
77
import InputComponent from "@/components/Input";
8+
import { useI18n } from "@/hooks/useI18n";
89
import { supabase } from "@/libs/supabase/client";
910
import SupabaseService from "@/services/supabase";
1011
import { isValidEmail } from "@/utils/isValidEmail";
@@ -45,6 +46,7 @@ function reducer(state: ForgotPasswordStateType, action: ForgotPasswordAction) {
4546
}
4647

4748
export default function ForgotPassword() {
49+
const { translate } = useI18n();
4850
const [state, dispatch] = useReducer(reducer, initialState);
4951

5052
async function handleForgotPassword() {
@@ -58,7 +60,7 @@ export default function ForgotPassword() {
5860
dispatch({
5961
type: "SET_ERRORS",
6062
payload: {
61-
email: "Invalid email format.",
63+
email: translate("forgot-password-invalid-email"),
6264
},
6365
});
6466
throw new Error("Validation Error");
@@ -70,11 +72,11 @@ export default function ForgotPassword() {
7072
if (response) {
7173
dispatch({ type: "SET_SUCCESS", payload: true });
7274
} else {
73-
dispatch({ type: "SET_ERRORS", payload: { general: "Something went wrong. Please try again." } });
75+
dispatch({ type: "SET_ERRORS", payload: { general: translate("forgot-password-general-error") } });
7476
}
7577
} catch (err) {
7678
if (err instanceof Error && err.message !== "Validation Error") {
77-
dispatch({ type: "SET_ERRORS", payload: { general: "Something went wrong. Please try again." } });
79+
dispatch({ type: "SET_ERRORS", payload: { general: translate("forgot-password-general-error") } });
7880
}
7981
} finally {
8082
dispatch({ type: "SET_LOADING", payload: false });
@@ -84,18 +86,18 @@ export default function ForgotPassword() {
8486
if (state.isSuccess) {
8587
return (
8688
<>
87-
<BackLinkComponent href='/signin' label='Back To Login' />
88-
<h2 className="text-2xl font-semibold text-center text-gray-900">Check Your Inbox</h2>
89-
<p className="text-center text-sm text-gray-600">A password reset link has been sent to your email. Please check your inbox.</p>
89+
<BackLinkComponent href='/signin' label={translate("forgot-password-back-to-login")} />
90+
<h2 className="text-2xl font-semibold text-center text-gray-900">{translate("forgot-password-check-inbox-title")}</h2>
91+
<p className="text-center text-sm text-gray-600">{translate("forgot-password-check-inbox-description")}</p>
9092
</>
9193
);
9294
}
9395

9496
return (
9597
<>
96-
<BackLinkComponent href='/signin' label='Back To Login' />
97-
<h2 className="text-2xl font-semibold text-center text-gray-900">Forgot Password</h2>
98-
<p className="text-center text-sm text-gray-600">Enter your email to receive a password reset link.</p>
98+
<BackLinkComponent href='/signin' label={translate("forgot-password-back-to-login")} />
99+
<h2 className="text-2xl font-semibold text-center text-gray-900">{translate("forgot-password-title")}</h2>
100+
<p className="text-center text-sm text-gray-600">{translate("forgot-password-description")}</p>
99101
<form
100102
className="mt-8 space-y-6"
101103
onSubmit={(e) => {
@@ -106,8 +108,8 @@ export default function ForgotPassword() {
106108
<InputComponent
107109
type="email"
108110
name="email"
109-
label="Email"
110-
placeholder="Enter your email"
111+
label={translate("forgot-password-email-label")}
112+
placeholder={translate("forgot-password-email-placeholder")}
111113
value={state.inputValue.email}
112114
onChange={(e) =>
113115
dispatch({ type: "SET_INPUT_VALUE", payload: { email: e.target.value } })
@@ -123,7 +125,7 @@ export default function ForgotPassword() {
123125
)}
124126

125127
<ButtonComponent isLoading={state.isLoading} type="submit" className="w-full">
126-
Send Reset Link
128+
{translate("forgot-password-button-text")}
127129
</ButtonComponent>
128130
</form>
129131
</>

src/app/(domains)/(auth)/new-password/page.tsx

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import BackLinkComponent from "@/components/BackLink";
88
import ButtonComponent from "@/components/Button";
99
import InputComponent from "@/components/Input";
1010
import PasswordStrengthIndicator from "@/components/PasswordStrength";
11+
import { useI18n } from '@/hooks/useI18n';
1112
import { supabase } from "@/libs/supabase/client";
1213
import SupabaseService from "@/services/supabase";
1314

@@ -57,13 +58,14 @@ function reducer(state: NewPasswordStateType, action: NewPasswordAction) {
5758
}
5859

5960
export default function NewPassword() {
61+
const { translate } = useI18n();
6062
const [state, dispatch] = useReducer(reducer, initialState);
6163
const searchParams = useSearchParams();
6264

6365
useEffect(() => {
6466
const token = searchParams?.get("code");
6567
if (!token) {
66-
dispatch({ type: "SET_TOKEN_ERROR", payload: "Invalid or missing token." });
68+
dispatch({ type: "SET_TOKEN_ERROR", payload: translate("new-password-error-token-missing") });
6769
} else {
6870
dispatch({ type: "SET_TOKEN_VALUE", payload: token });
6971
}
@@ -73,40 +75,39 @@ export default function NewPassword() {
7375
try {
7476
dispatch({ type: "SET_LOADING", payload: true });
7577
dispatch({ type: "SET_ERRORS", payload: { password: "", confirmPassword: "", general: "" } });
76-
78+
7779
const isPasswordValid = state.inputValue.password.length >= 6;
7880
const isPasswordsMatch = state.inputValue.password === state.inputValue.confirmPassword;
79-
81+
8082
if (!isPasswordValid || !isPasswordsMatch) {
8183
dispatch({
8284
type: "SET_ERRORS",
8385
payload: {
84-
password: isPasswordValid ? "" : "Password must be at least 6 characters long.",
85-
confirmPassword: isPasswordsMatch ? "" : "Passwords do not match.",
86+
password: isPasswordValid ? "" : translate("new-password-error-password-valid"),
87+
confirmPassword: isPasswordsMatch ? "" : translate("new-password-error-password-match"),
8688
},
8789
});
8890
throw new Error("Validation Error");
8991
}
90-
92+
9193
const SupabaseServiceInstance = new SupabaseService(supabase);
92-
94+
9395
const response = await SupabaseServiceInstance.newPassword(state.inputValue.password);
94-
96+
9597
if (response) {
9698
dispatch({ type: "SET_PASSWORD_CHANGED", payload: true });
9799
} else {
98-
dispatch({ type: "SET_ERRORS", payload: { general: "Failed to change the password. Please try again." } });
100+
dispatch({ type: "SET_ERRORS", payload: { general: translate("new-password-error-general") } });
99101
}
100102
} catch (err) {
101103
console.log("Error", err);
102104
if (err instanceof Error && err.message !== "Validation Error") {
103-
dispatch({ type: "SET_ERRORS", payload: { general: "Something went wrong. Please try again." } });
105+
dispatch({ type: "SET_ERRORS", payload: { general: translate("new-password-error-unexpected") } });
104106
}
105107
} finally {
106108
dispatch({ type: "SET_LOADING", payload: false });
107109
}
108110
}
109-
110111

111112
return (
112113
<>
@@ -116,15 +117,15 @@ export default function NewPassword() {
116117
</div>
117118
) : state.isSuccess ? (
118119
<>
119-
<BackLinkComponent href='/signin' label='Back To Login' />
120+
<BackLinkComponent href='/signin' label={translate("new-password-back-to-login")} />
120121
<div className="text-center">
121-
<p className="text-lg text-gray-700">Your password has been changed successfully!</p>
122+
<p className="text-lg text-gray-700">{translate("new-password-success-message")}</p>
122123
</div>
123124
</>
124125
) : (
125126
<>
126-
<h2 className="text-2xl font-semibold text-center text-gray-900">Create a New Password</h2>
127-
<p className="text-center text-sm text-gray-600">Set your new password to continue</p>
127+
<h2 className="text-2xl font-semibold text-center text-gray-900">{translate("new-password-create-title")}</h2>
128+
<p className="text-center text-sm text-gray-600">{translate("new-password-subtitle")}</p>
128129
<form
129130
className="mt-8 space-y-6"
130131
onSubmit={(e) => {
@@ -135,7 +136,7 @@ export default function NewPassword() {
135136
<InputComponent
136137
type="password"
137138
name="password"
138-
label="Password"
139+
label={translate("new-password-password-label")}
139140
placeholder=""
140141
value={state.inputValue.password}
141142
onChange={(e) =>
@@ -152,7 +153,7 @@ export default function NewPassword() {
152153
<InputComponent
153154
type="password"
154155
name="confirmPassword"
155-
label="Confirm Password"
156+
label={translate("new-password-confirm-password-label")}
156157
placeholder=""
157158
value={state.inputValue.confirmPassword}
158159
onChange={(e) =>
@@ -169,7 +170,7 @@ export default function NewPassword() {
169170
)}
170171

171172
<ButtonComponent isLoading={state.isLoading} type="submit" className="w-full">
172-
Change Password
173+
{translate("new-password-submit-button")}
173174
</ButtonComponent>
174175
</form>
175176
</>

0 commit comments

Comments
 (0)