Skip to content

Commit 629dea3

Browse files
committed
Merge branch 'release-1.5'
2 parents 150ed64 + 5932753 commit 629dea3

File tree

4 files changed

+110
-63
lines changed

4 files changed

+110
-63
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"start-with-latest-migrations": "prisma migrate deploy && next start",
2121
"d": "pnpm dx && pnpm dev",
2222
"dx": "pnpm i && pnpm dx:up && pnpm db:dev",
23-
"dx:up": "docker compose -f docker/dev/compose.yml up -d",
23+
"dx:up": "docker compose -f docker/dev/compose.yml --env-file .env up -d",
2424
"dx:down": "docker compose -f docker/dev/compose.yml down",
2525
"test": "jest",
2626
"test:watch": "jest --watch",

public/locales/en/common.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@
118118
"errors": {
119119
"currency_conversion_error": "Error while setting currency conversion",
120120
"email_invalid": "Email is invalid, please try the signin flow again.",
121+
"no_providers": "Error when fetching authentication providers. Please check backend logs.",
121122
"email_required": "Email is required",
122123
"feedback_min_length": "Feedback should be at least 10 characters",
123124
"feedback_required": "Feedback is required",

src/components/Friend/GroupSettleup.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { BigMath } from '~/utils/numbers';
1010
import { EntityAvatar } from '../ui/avatar';
1111
import { CurrencyInput } from '../ui/currency-input';
1212
import { AppDrawer } from '../ui/drawer';
13+
import { useSession } from 'next-auth/react';
1314

1415
export const GroupSettleUp: React.FC<{
1516
amount: bigint;
@@ -19,6 +20,7 @@ export const GroupSettleUp: React.FC<{
1920
children: ReactNode;
2021
groupId: number;
2122
}> = ({ amount: _amount, currency, friend, user, children, groupId }) => {
23+
const { data } = useSession();
2224
const { displayName, t, getCurrencyHelpersCached } = useTranslationWithUtils();
2325
const [amount, setAmount] = useState<bigint>(BigMath.abs(_amount));
2426
const [amountStr, setAmountStr] = useState(getCurrencyHelpersCached(currency).toUIString(amount));
@@ -38,8 +40,8 @@ export const GroupSettleUp: React.FC<{
3840
const addExpenseMutation = api.expense.addOrEditExpense.useMutation();
3941
const utils = api.useUtils();
4042

41-
const sender = 0 > amount ? user : friend;
42-
const receiver = 0 > amount ? friend : user;
43+
const sender = 0 > _amount ? user : friend;
44+
const receiver = 0 > _amount ? friend : user;
4345

4446
const saveExpense = React.useCallback(() => {
4547
if (!amount) {
@@ -97,7 +99,9 @@ export const GroupSettleUp: React.FC<{
9799
<EntityAvatar entity={receiver} />
98100
</div>
99101
<p className="mt-2 text-center text-sm text-gray-400">
100-
{displayName(sender)} {t('ui.expense.user.pay')} {displayName(receiver)}
102+
{displayName(sender, data?.user.id)}{' '}
103+
{t(`ui.expense.${sender.id === data?.user.id ? 'you' : 'user'}.pay`)}{' '}
104+
{displayName(receiver, data?.user.id)}
101105
</p>
102106
</div>
103107
<CurrencyInput

src/pages/auth/signin.tsx

Lines changed: 101 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
FormMessage,
2626
} from '~/components/ui/form';
2727
import { Input } from '~/components/ui/input';
28+
import { LoadingSpinner } from '~/components/ui/spinner';
2829
import { env } from '~/env';
2930
import { getServerAuthSession } from '~/server/auth';
3031
import { customServerSideTranslations } from '~/utils/i18n/server';
@@ -56,10 +57,12 @@ const Home: NextPage<{
5657
feedbackEmail: string;
5758
providers: ClientSafeProvider[];
5859
callbackUrl?: string;
59-
}> = ({ error, providers, feedbackEmail, callbackUrl }) => {
60+
}> = ({ error, providers: serverProviders, feedbackEmail, callbackUrl }) => {
6061
const { t } = useTranslation();
6162
const [emailStatus, setEmailStatus] = useState<'idle' | 'sending' | 'success'>('idle');
6263
const [showVerificationStep, setShowVerificationStep] = useState(false);
64+
const [providers, setProviders] = useState<ClientSafeProvider[]>(serverProviders);
65+
const [isLoadingProviders, setIsLoadingProviders] = useState(false);
6366

6467
const emailForm = useForm<EmailFormValues>({
6568
resolver: zodResolver(emailSchema(t)),
@@ -68,6 +71,30 @@ const Home: NextPage<{
6871
},
6972
});
7073

74+
// Client-side fallback for getProviders when server-side call fails
75+
useEffect(() => {
76+
if (serverProviders.length > 0) {
77+
return;
78+
}
79+
80+
void (async () => {
81+
setIsLoadingProviders(true);
82+
try {
83+
const clientProviders = await getProviders();
84+
if (clientProviders && Object.keys(clientProviders).length > 0) {
85+
setProviders(Object.values(clientProviders));
86+
} else {
87+
throw new Error('No providers returned from getProviders()');
88+
}
89+
} catch (error) {
90+
console.error('Error fetching providers client-side:', error);
91+
toast.error(t('errors.no_providers'), { duration: 8000 });
92+
} finally {
93+
setIsLoadingProviders(false);
94+
}
95+
})();
96+
}, [serverProviders.length, t]);
97+
7198
useEffect(() => {
7299
if (error) {
73100
if ('SignupDisabled' === error) {
@@ -148,75 +175,85 @@ const Home: NextPage<{
148175
<LanguageSelector />
149176
</div>
150177

151-
{providers.length === 0 ? (
152-
<div className="text-muted-foreground flex w-[300px] flex-col items-center gap-4 text-center">
153-
<p className="text-lg font-semibold">{t('auth.no_providers_configured')}</p>
154-
<p className="text-sm">
155-
{t('auth.no_providers_instructions')}{' '}
156-
<a
157-
className="text-primary underline"
158-
href="https://github.com/oss-apps/split-pro/blob/main/docker/README.md"
159-
target="_blank"
160-
rel="noopener noreferrer"
161-
>
162-
{t('auth.setup_instructions')}
163-
</a>
164-
.
165-
</p>
178+
{isLoadingProviders ? (
179+
<div className="flex h-[200px] w-[300px] items-center justify-center">
180+
<LoadingSpinner className="h-8 w-8" />
166181
</div>
167182
) : (
168183
<>
169-
{providers
170-
.filter((provider) => 'email' !== provider.id)
171-
.map((provider) => (
172-
<Button
173-
className="mx-auto flex w-[300px] items-center gap-3 bg-white hover:bg-gray-100 focus:bg-gray-100"
174-
onClick={handleProviderSignIn(provider.id)}
175-
key={provider.id}
176-
>
177-
{providerTypeGuard(provider.id) && providerSvgs[provider.id]}
178-
{t('auth.continue_with', { provider: provider.name })}
179-
</Button>
180-
))}
181-
{providers && 2 === providers.length && (
182-
<div className="mt-6 flex w-[300px] items-center justify-between gap-2">
183-
<p className="bg-background z-10 ml-[150px] -translate-x-1/2 px-4 text-sm">
184-
{t('ui.or')}
184+
{providers.length === 0 ? (
185+
<div className="text-muted-foreground flex w-[300px] flex-col items-center gap-4 text-center">
186+
<p className="text-lg font-semibold">{t('auth.no_providers_configured')}</p>
187+
<p className="text-sm">
188+
{t('auth.no_providers_instructions')}{' '}
189+
<a
190+
className="text-primary underline"
191+
href="https://github.com/oss-apps/split-pro/blob/main/docker/README.md"
192+
target="_blank"
193+
rel="noopener noreferrer"
194+
>
195+
{t('auth.setup_instructions')}
196+
</a>
197+
.
185198
</p>
186-
<div className="absolute h-px w-[300px] bg-linear-to-r from-zinc-800 via-zinc-300 to-zinc-800" />
187199
</div>
188-
)}
189-
{providers.find((provider) => 'email' === provider.id) ? (
200+
) : (
190201
<>
191-
<Form {...emailForm}>
192-
<form
193-
onSubmit={emailForm.handleSubmit(onEmailSubmit)}
194-
className="mt-6 space-y-8"
195-
>
196-
<FormField control={emailForm.control} name="email" render={field} />
202+
{providers
203+
.filter((provider) => 'email' !== provider.id)
204+
.map((provider) => (
197205
<Button
198-
className="mt-6 w-[300px] bg-white hover:bg-gray-100 focus:bg-gray-100"
199-
type="submit"
200-
disabled={'sending' === emailStatus}
206+
className="mx-auto flex w-[300px] items-center gap-3 bg-white hover:bg-gray-100 focus:bg-gray-100"
207+
onClick={handleProviderSignIn(provider.id)}
208+
key={provider.id}
201209
>
202-
{'sending' === emailStatus ? t('auth.sending') : t('auth.send_magic_link')}
210+
{providerTypeGuard(provider.id) && providerSvgs[provider.id]}
211+
{t('auth.continue_with', { provider: provider.name })}
203212
</Button>
204-
</form>
205-
</Form>
213+
))}
214+
{providers && 2 === providers.length && (
215+
<div className="mt-6 flex w-[300px] items-center justify-between gap-2">
216+
<p className="bg-background z-10 ml-[150px] -translate-x-1/2 px-4 text-sm">
217+
{t('ui.or')}
218+
</p>
219+
<div className="absolute h-px w-[300px] bg-linear-to-r from-zinc-800 via-zinc-300 to-zinc-800" />
220+
</div>
221+
)}
222+
{providers.find((provider) => 'email' === provider.id) ? (
223+
<>
224+
<Form {...emailForm}>
225+
<form
226+
onSubmit={emailForm.handleSubmit(onEmailSubmit)}
227+
className="mt-6 space-y-8"
228+
>
229+
<FormField control={emailForm.control} name="email" render={field} />
230+
<Button
231+
className="mt-6 w-[300px] bg-white hover:bg-gray-100 focus:bg-gray-100"
232+
type="submit"
233+
disabled={'sending' === emailStatus}
234+
>
235+
{'sending' === emailStatus
236+
? t('auth.sending')
237+
: t('auth.send_magic_link')}
238+
</Button>
239+
</form>
240+
</Form>
241+
</>
242+
) : null}
206243
</>
207-
) : null}
244+
)}
245+
{feedbackEmail && (
246+
<p className="text-muted-foreground mt-6 w-[300px] text-center text-sm">
247+
{t('auth.trouble_logging_in')}
248+
<br />
249+
{/* oxlint-disable-next-line next/no-html-link-for-pages */}
250+
<a className="underline" href={feedbackEmailLink}>
251+
{feedbackEmail ?? ''}
252+
</a>
253+
</p>
254+
)}
208255
</>
209256
)}
210-
{feedbackEmail && (
211-
<p className="text-muted-foreground mt-6 w-[300px] text-center text-sm">
212-
{t('auth.trouble_logging_in')}
213-
<br />
214-
{/* oxlint-disable-next-line next/no-html-link-for-pages */}
215-
<a className="underline" href={feedbackEmailLink}>
216-
{feedbackEmail ?? ''}
217-
</a>
218-
</p>
219-
)}
220257
</div>
221258
</main>
222259
</>
@@ -227,7 +264,12 @@ export default Home;
227264

228265
export const getServerSideProps: GetServerSideProps = async (context) => {
229266
const session = await getServerAuthSession(context);
230-
const providers = await getProviders();
267+
let providers: Record<string, ClientSafeProvider> | null = null;
268+
try {
269+
providers = await getProviders();
270+
} catch (error) {
271+
console.error(error);
272+
}
231273
const { callbackUrl, error } = context.query;
232274

233275
if (session) {

0 commit comments

Comments
 (0)