Skip to content

Commit

Permalink
refactor(general): small fixes and improvements (#857)
Browse files Browse the repository at this point in the history
  • Loading branch information
mkue authored Jun 22, 2024
1 parent 1da633b commit fd96d2f
Show file tree
Hide file tree
Showing 14 changed files with 64 additions and 72 deletions.
2 changes: 1 addition & 1 deletion admin/src/collections/Users.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const usersCollection = buildAuditedCollection<User>({
dataType: 'map',
properties: {
name: {
name: 'Name',
name: 'First Name',
dataType: 'string',
validation: { required: true },
},
Expand Down
9 changes: 6 additions & 3 deletions admin/src/collections/shared.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { UpdateData } from '@firebase/firestore';
import { DocumentData, UpdateData } from '@firebase/firestore';
import { getAuth } from 'firebase/auth';
import { DocumentReference, updateDoc } from 'firebase/firestore';
import { EntityOnSaveProps, buildCollection } from 'firecms';
Expand Down Expand Up @@ -56,7 +56,10 @@ export const buildAuditedCollection = <
return buildCollection(collection);
};

export function auditedUpdateDoc<T extends {}>(reference: DocumentReference<T>, data: UpdateData<T>) {
export function auditedUpdateDoc<AppModelType, DbModelType extends DocumentData>(
reference: DocumentReference<AppModelType, DbModelType>,
data: UpdateData<DbModelType>,
) {
const auth = getAuth();
return updateDoc<T>(reference, { ...data, last_updated_by: auth.currentUser?.email });
return updateDoc<AppModelType, DbModelType>(reference, { ...data, last_updated_by: auth.currentUser?.email });
}
4 changes: 3 additions & 1 deletion shared/src/firebase/admin/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Timestamp as FirestoreAdminTimestamp } from '@google-cloud/firestore';
import admin from 'firebase-admin';
import { DateTime } from 'luxon';
import { Timestamp } from '../../types/timestamp';

export const FirestoreAdminTimestamp = admin.firestore.Timestamp;

export function toFirebaseAdminTimestamp(dateTime: DateTime | Date): Timestamp {
if (dateTime instanceof Date) {
return FirestoreAdminTimestamp.fromDate(dateTime);
Expand Down
16 changes: 10 additions & 6 deletions shared/src/types/user.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { EntityReference } from 'firecms';
import _ from 'lodash';
import { CountryCode } from './country';
import { Currency } from './currency';
import { Employer } from './employers';
Expand Down Expand Up @@ -52,16 +51,21 @@ export type User = {
};

export const splitName = (name: string) => {
const stripeNames = name.split(' ');
const stripeNames = name.trim().split(' ');
const sanitizeName = (n: string) => n.charAt(0).toUpperCase() + n.slice(1).toLowerCase().trim();

if (stripeNames.length >= 2) {
return {
lastname: _.upperFirst(stripeNames.pop()!),
firstname: _.upperFirst(stripeNames.join(' ')),
lastname: sanitizeName(stripeNames.pop()!),
firstname: stripeNames
.map((n) => sanitizeName(n))
.filter(Boolean) // Remove empty strings
.join(' '),
};
} else {
return {
firstname: '',
lastname: _.upperFirst(name),
firstname: sanitizeName(name),
lastname: '',
};
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@ export default function Page({ params }: SurveyPageProps) {
const [password, setPassword] = useState<string | null>(null);
const [user, setUser] = useState<User>();
const searchParams = useSearchParams();
const queryClient = new QueryClient();
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 3600000, // 1 hour
},
},
});

useEffect(() => {
setEmail(searchParams.get('email'));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ export function Survey({ surveyId, recipientId, lang }: SurveyProps) {
const { data: survey } = useQuery({
queryFn: () => getDoc(surveyDocRef).then((snapshot) => snapshot.data() as SurveyModel),
queryKey: [recipientId, surveyId],
staleTime: 3600000, // 1 hour
});

// TODO: implement session storage caching
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ type ContributionsTableProps = {

export function ContributionsTable({ lang, translations }: ContributionsTableProps) {
const translator = useTranslator(lang, 'website-me');
const { contributions, loading } = useContributions();
const { contributions, isLoading } = useContributions();

if (loading) {
if (isLoading) {
return <SpinnerIcon />;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ type ContributionsTableProps = {
} & DefaultParams;

export function DonationCertificatesTable({ translations }: ContributionsTableProps) {
const { donationCertificates, loading } = useDonationCertificates();
const { donationCertificates, isLoading } = useDonationCertificates();

if (loading) {
if (isLoading) {
return <SpinnerIcon />;
}

Expand Down
20 changes: 5 additions & 15 deletions website/src/app/[lang]/[region]/(website)/me/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export const useContributions = () => {
const {
data: contributions,
isLoading,
isRefetching,
error,
} = useQuery({
queryKey: ['me', 'contributions'],
Expand All @@ -38,27 +37,24 @@ export const useContributions = () => {
orderBy('created', 'desc'),
),
),
staleTime: 3600000, // 1 hour
});
return { contributions, loading: isLoading || isRefetching, error };
return { contributions, isLoading, error };
};

export const useSubscriptions = () => {
const api = useApi();
const {
data: subscriptions,
isLoading,
isRefetching,
error,
} = useQuery({
queryKey: ['me', 'subscriptions'],
queryFn: async () => {
const response = await api.get('/api/stripe/subscriptions');
return (await response.json()) as Stripe.Subscription[];
},
staleTime: 3600000, // 1 hour
});
return { subscriptions, loading: isLoading || isRefetching, error };
return { subscriptions, isLoading, error };
};

export const useDonationCertificates = () => {
Expand All @@ -67,7 +63,6 @@ export const useDonationCertificates = () => {
const {
data: donationCertificates,
isLoading,
isRefetching,
error,
} = useQuery({
queryKey: ['me', 'donation-certificates'],
Expand All @@ -78,17 +73,15 @@ export const useDonationCertificates = () => {
orderBy('year', 'desc'),
),
),
staleTime: 3600000, // 1 hour
});
return { donationCertificates, loading: isLoading || isRefetching, error };
return { donationCertificates, isLoading, error };
};

export const useNewsletterSubscription = () => {
const api = useApi();
const {
data: status,
isLoading,
isRefetching,
error,
} = useQuery<string | null>({
queryKey: ['me', 'newsletter'],
Expand All @@ -101,9 +94,8 @@ export const useNewsletterSubscription = () => {
return responseData.status;
}
},
staleTime: 3600000, // 1 hour
});
return { status, loading: isLoading || isRefetching, error };
return { status, isLoading, error };
};

export const useUpsertNewsletterSubscription = () => {
Expand All @@ -128,7 +120,6 @@ export const useEmployers = () => {
const {
data: employers,
isLoading,
isRefetching,
error,
} = useQuery({
queryKey: ['me', 'employers'],
Expand All @@ -138,9 +129,8 @@ export const useEmployers = () => {
);
return data.docs.map((e) => ({ id: e.id, ...e.data() }) as EmployerWithId);
},
staleTime: 3600000, // 1 hour
});
return { employers, loading: isLoading || isRefetching, error };
return { employers, isLoading, error };
};

export const useArchiveEmployer = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import {
} from '@socialincome/ui';
import { useQueryClient } from '@tanstack/react-query';
import { doc, updateDoc } from 'firebase/firestore';
import { useEffect } from 'react';
import { useForm } from 'react-hook-form';
import toast from 'react-hot-toast';
import { useFirestore } from 'reactfire';
Expand Down Expand Up @@ -61,7 +60,7 @@ export function PersonalInfoForm({ lang, translations }: PersonalInfoFormProps)
const queryClient = useQueryClient();
const commonTranslator = useTranslator(lang, 'common');
const countryTranslator = useTranslator(lang, 'countries');
const { status, loading } = useNewsletterSubscription();
const { status, isLoading } = useNewsletterSubscription();
const upsertNewsletterSubscription = useUpsertNewsletterSubscription();

const formSchema = z.object({
Expand All @@ -73,42 +72,27 @@ export function PersonalInfoForm({ lang, translations }: PersonalInfoFormProps)
streetNumber: z.string(),
city: z.string(),
zip: z.coerce.number(),
country: z.enum(['', ...COUNTRY_CODES]).optional(),
country: z.enum(COUNTRY_CODES).optional(),
language: z.enum(['en', 'de']),
});

type FormSchema = z.infer<typeof formSchema>;
const form = useForm<FormSchema>({
resolver: zodResolver(formSchema),
defaultValues: {
firstname: '',
lastname: '',
gender: '' as any,
email: '',
street: '',
streetNumber: '',
city: '',
zip: '' as any,
country: '' as any,
language: '' as any,
firstname: user.get('personal.name'),
lastname: user.get('personal.lastname'),
gender: user.get('personal.gender'),
email: user.get('email'),
street: user.get('address.street'),
streetNumber: user.get('address.number'),
city: user.get('address.city'),
zip: user.get('address.zip'),
country: user.get('address.country'),
language: user.get('language'),
},
});

useEffect(() => {
form.reset({
firstname: user.get('personal.name') || '',
lastname: user.get('personal.lastname') || '',
gender: user.get('personal.gender') || '',
email: user.get('email') || '',
street: user.get('address.street') || '',
streetNumber: user.get('address.number') || '',
city: user.get('address.city') || '',
zip: user.get('address.zip') || '',
country: user.get('address.country') || '',
language: user.get('language') || '',
});
}, [user, form]);

const onSubmit = async (values: FormSchema) => {
await updateDoc<DocumentData, Partial<User>>(doc(firestore, USER_FIRESTORE_PATH, user.id), {
personal: {
Expand Down Expand Up @@ -261,7 +245,7 @@ export function PersonalInfoForm({ lang, translations }: PersonalInfoFormProps)
<Select onValueChange={field.onChange}>
<FormControl>
<SelectTrigger>
<SelectValue>{field.value && countryTranslator?.t(field.value)}</SelectValue>
<SelectValue placeholder={field.value && countryTranslator?.t(field.value)} />
</SelectTrigger>
</FormControl>
<SelectContent className="max-h-[16rem] overflow-y-auto">
Expand All @@ -287,7 +271,7 @@ export function PersonalInfoForm({ lang, translations }: PersonalInfoFormProps)
<Select onValueChange={field.onChange}>
<FormControl>
<SelectTrigger>
<SelectValue>{field.value && commonTranslator?.t(`languages.${field.value}`)}</SelectValue>
<SelectValue placeholder={field.value && commonTranslator?.t(`languages.${field.value}`)} />
</SelectTrigger>
</FormControl>
<SelectContent>
Expand All @@ -307,7 +291,7 @@ export function PersonalInfoForm({ lang, translations }: PersonalInfoFormProps)
<Switch
id="newsletter-switch"
checked={status === 'subscribed'}
disabled={loading}
disabled={isLoading}
onCheckedChange={async (enabled) => {
if (enabled) {
await upsertNewsletterSubscription('subscribed');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ type SubscriptionsTableProps = {

export function SubscriptionsClient({ lang, region, translations }: SubscriptionsTableProps) {
const translator = useTranslator(lang, 'website-me');
const { subscriptions, loading } = useSubscriptions();
const { subscriptions, isLoading } = useSubscriptions();

if (loading) {
if (isLoading) {
return <SpinnerIcon />;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ type EmployersListProps = {
} & DefaultParams;

export function EmployersList({ translations }: EmployersListProps) {
const { employers, loading } = useEmployers();
const { employers, isLoading } = useEmployers();
const archiveEmployer = useArchiveEmployer();
const deleteEmployer = useDeleteEmployer();

if (loading) {
if (isLoading) {
return <SpinnerIcon />;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ export function SuccessForm({
lastname: z.string().min(1),
email: z.string().email(),
country: z.enum([firstCountry, ...restCountries]),
gender: z.enum(GENDER_OPTIONS),
referral: z.nativeEnum(UserReferralSource),
gender: z.enum(GENDER_OPTIONS).optional(),
referral: z.nativeEnum(UserReferralSource).optional(),
termsAndConditions: z.literal<boolean>(true),
});

Expand Down Expand Up @@ -169,7 +169,7 @@ export function SuccessForm({
<Select onValueChange={field.onChange}>
<FormControl>
<SelectTrigger>
<SelectValue>{field.value && countryTranslator?.t(field.value)}</SelectValue>
<SelectValue placeholder={field.value && countryTranslator?.t(field.value)} />
</SelectTrigger>
</FormControl>
<SelectContent className="max-h-[16rem] overflow-y-auto">
Expand Down Expand Up @@ -248,7 +248,12 @@ export function SuccessForm({
</FormItem>
)}
/>
<Button type="submit" showLoadingSpinner={submitting} className="md:col-span-2 md:mt-4">
<Button
type="submit"
showLoadingSpinner={submitting}
disabled={!form.getValues('termsAndConditions')}
className="md:col-span-2 md:mt-4"
>
{translations.submitButton}
</Button>
</form>
Expand Down
1 change: 0 additions & 1 deletion website/src/components/providers/user-context-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export function UserContextProvider({ children }: PropsWithChildren) {
}
return null;
},
staleTime: 3600000, // 1 hour
});

useEffect(() => {
Expand Down

0 comments on commit fd96d2f

Please sign in to comment.