Updated query hooks for teams and websites.

This commit is contained in:
Mike Cao 2024-01-29 01:32:05 -08:00
parent 9448aa3ab5
commit 2fa50892d8
61 changed files with 508 additions and 539 deletions

View file

@ -1,35 +0,0 @@
import { useState } from 'react';
import { Button, LoadingButton, Form, FormButtons } from 'react-basics';
import { useMessages } from 'components/hooks';
export interface ConfirmDeleteFormProps {
name: string;
onConfirm?: () => void;
onClose?: () => void;
}
export function ConfirmDeleteForm({ name, onConfirm, onClose }: ConfirmDeleteFormProps) {
const [loading, setLoading] = useState(false);
const { formatMessage, labels, messages, FormattedMessage } = useMessages();
const handleConfirm = () => {
setLoading(true);
onConfirm();
};
return (
<Form>
<p>
<FormattedMessage {...messages.confirmDelete} values={{ target: <b>{name}</b> }} />
</p>
<FormButtons flex>
<LoadingButton isLoading={loading} onClick={handleConfirm} variant="danger">
{formatMessage(labels.delete)}
</LoadingButton>
<Button onClick={onClose}>{formatMessage(labels.cancel)}</Button>
</FormButtons>
</Form>
);
}
export default ConfirmDeleteForm;

View file

@ -0,0 +1,39 @@
import { ReactNode } from 'react';
import { Button, LoadingButton, Form, FormButtons } from 'react-basics';
import { useMessages } from 'components/hooks';
export interface ConfirmationFormProps {
message: ReactNode;
buttonLabel?: ReactNode;
buttonVariant?: 'none' | 'primary' | 'secondary' | 'quiet' | 'danger';
isLoading?: boolean;
error?: string | Error;
onConfirm?: () => void;
onClose?: () => void;
}
export function ConfirmationForm({
message,
buttonLabel,
buttonVariant,
isLoading,
error,
onConfirm,
onClose,
}: ConfirmationFormProps) {
const { formatMessage, labels } = useMessages();
return (
<Form error={error}>
<p>{message}</p>
<FormButtons flex>
<LoadingButton isLoading={isLoading} onClick={onConfirm} variant={buttonVariant}>
{buttonLabel || formatMessage(labels.ok)}
</LoadingButton>
<Button onClick={onClose}>{formatMessage(labels.cancel)}</Button>
</FormButtons>
</Form>
);
}
export default ConfirmationForm;

View file

@ -0,0 +1,58 @@
import {
Button,
Form,
FormButtons,
FormRow,
FormInput,
TextField,
SubmitButton,
} from 'react-basics';
import { useMessages } from 'components/hooks';
export function TypeConfirmationForm({
confirmationValue,
buttonLabel,
buttonVariant,
isLoading,
error,
onConfirm,
onClose,
}: {
confirmationValue: string;
buttonLabel?: string;
buttonVariant?: 'none' | 'primary' | 'secondary' | 'quiet' | 'danger';
isLoading?: boolean;
error?: string | Error;
onConfirm?: () => void;
onClose?: () => void;
}) {
const { formatMessage, labels, messages, FormattedMessage } = useMessages();
if (!confirmationValue) {
return null;
}
return (
<Form onSubmit={onConfirm} error={error}>
<p>
<FormattedMessage
{...messages.actionConfirmation}
values={{ confirmation: <b>{confirmationValue}</b> }}
/>
</p>
<FormRow label={formatMessage(labels.confirm)}>
<FormInput name="confirm" rules={{ validate: value => value === confirmationValue }}>
<TextField autoComplete="off" />
</FormInput>
</FormRow>
<FormButtons flex>
<SubmitButton isLoading={isLoading} variant={buttonVariant}>
{buttonLabel || formatMessage(labels.ok)}
</SubmitButton>
<Button onClick={onClose}>{formatMessage(labels.cancel)}</Button>
</FormButtons>
</Form>
);
}
export default TypeConfirmationForm;

View file

@ -8,7 +8,9 @@ export * from './queries/useShareToken';
export * from './queries/useTeam';
export * from './queries/useTeamWebsites';
export * from './queries/useUser';
export * from './queries/useUsers';
export * from './queries/useWebsite';
export * from './queries/useWebsites';
export * from './useCountryNames';
export * from './useDateRange';
export * from './useDocumentClick';

View file

@ -1,9 +1,11 @@
import useStore, { setUser } from 'store/app';
import useApi from './useApi';
import useUser from './useUser';
const selector = (state: { user: any }) => state.user;
export function useLogin() {
const { get, useQuery } = useApi();
const { user, setUser } = useUser();
const user = useStore(selector);
const query = useQuery({
queryKey: ['login'],
@ -14,6 +16,7 @@ export function useLogin() {
return data;
},
enabled: !user,
});
return { user, ...query };

View file

@ -1,11 +1,13 @@
import useStore, { setUser } from 'store/app';
import useApi from './useApi';
const selector = (state: { user: any }) => state.user;
export function useUser() {
const user = useStore(selector);
return { user, setUser };
export function useUser(userId: string, options?: { [key: string]: any }) {
const { get, useQuery } = useApi();
return useQuery({
queryKey: ['users', userId],
queryFn: () => get(`/users/${userId}`),
enabled: !!userId,
...options,
});
}
export default useUser;

View file

@ -0,0 +1,19 @@
import useApi from './useApi';
import useFilterQuery from './useFilterQuery';
import useCache from 'store/cache';
export function useUsers() {
const { get } = useApi();
const modified = useCache((state: any) => state?.users);
return useFilterQuery({
queryKey: ['users', { modified }],
queryFn: (params: any) => {
return get('/admin/users', {
...params,
});
},
});
}
export default useUsers;

View file

@ -1,11 +1,12 @@
import useApi from './useApi';
export function useWebsite(websiteId: string) {
export function useWebsite(websiteId: string, options?: { [key: string]: any }) {
const { get, useQuery } = useApi();
return useQuery({
queryKey: ['websites', websiteId],
queryFn: () => get(`/websites/${websiteId}`),
enabled: !!websiteId,
...options,
});
}

View file

@ -9,7 +9,7 @@ export function useWebsites({ userId, teamId }: { userId?: string; teamId?: stri
return useFilterQuery({
queryKey: ['websites', { userId, teamId, modified }],
queryFn: (params: any) => {
return get(teamId ? `/teams/${teamId}/websites` : '/websites', {
return get(teamId ? `/teams/${teamId}/websites` : `/users/${userId}/websites`, {
...params,
});
},

View file

@ -4,8 +4,8 @@ import { DATE_RANGE_CONFIG, DEFAULT_DATE_RANGE } from 'lib/constants';
import websiteStore, { setWebsiteDateRange } from 'store/websites';
import appStore, { setDateRange } from 'store/app';
import { DateRange } from 'lib/types';
import useLocale from './useLocale';
import { useApi } from 'components/hooks';
import { useLocale } from './useLocale';
import { useApi } from './queries/useApi';
export function useDateRange(websiteId?: string) {
const { get } = useApi();

View file

@ -2,14 +2,14 @@ import { Icon, Button, PopupTrigger, Popup, Menu, Item, Text } from 'react-basic
import { useRouter } from 'next/navigation';
import Icons from 'components/icons';
import { useMessages } from 'components/hooks';
import { useUser } from 'components/hooks';
import { useLogin } from 'components/hooks';
import { useLocale } from 'components/hooks';
import { CURRENT_VERSION } from 'lib/constants';
import styles from './ProfileButton.module.css';
export function ProfileButton() {
const { formatMessage, labels } = useMessages();
const { user } = useUser();
const { user } = useLogin();
const router = useRouter();
const { dir } = useLocale();
const cloudMode = Boolean(process.env.cloudMode);

View file

@ -1,6 +1,7 @@
import { defineMessages } from 'react-intl';
export const labels = defineMessages({
ok: { id: 'label.ok', defaultMessage: 'OK' },
unknown: { id: 'label.unknown', defaultMessage: 'Unknown' },
required: { id: 'label.required', defaultMessage: 'Required' },
save: { id: 'label.save', defaultMessage: 'Save' },
@ -50,6 +51,7 @@ export const labels = defineMessages({
websiteId: { id: 'label.website-id', defaultMessage: 'Website ID' },
resetWebsite: { id: 'label.reset-website', defaultMessage: 'Reset website' },
deleteWebsite: { id: 'label.delete-website', defaultMessage: 'Delete website' },
deleteReport: { id: 'label.delete-report', defaultMessage: 'Delete report' },
reset: { id: 'label.reset', defaultMessage: 'Reset' },
addWebsite: { id: 'label.add-website', defaultMessage: 'Add website' },
addMember: { id: 'label.add-member', defaultMessage: 'Add member' },