Compare commits
2 Commits
main
...
gh-readonl
Author | SHA1 | Date | |
---|---|---|---|
781e0e361d | |||
e4a16a86a4 |
|
@ -51,15 +51,17 @@ export default function Login({
|
|||
}: inferSSRProps<typeof _getServerSideProps> & WithNonceProps) {
|
||||
const { t } = useLocale();
|
||||
const router = useRouter();
|
||||
const formSchema = z.object({
|
||||
email: z
|
||||
.string()
|
||||
.min(1, `${t("error_required_field")}`)
|
||||
.email(`${t("enter_valid_email")}`),
|
||||
password: z.string().min(1, `${t("error_required_field")}`),
|
||||
});
|
||||
const formSchema = z
|
||||
.object({
|
||||
email: z
|
||||
.string()
|
||||
.min(1, `${t("error_required_field")}`)
|
||||
.email(`${t("enter_valid_email")}`),
|
||||
password: z.string().min(1, `${t("error_required_field")}`),
|
||||
})
|
||||
// Passthrough other fields like totpCode
|
||||
.passthrough();
|
||||
const methods = useForm<LoginValues>({ resolver: zodResolver(formSchema) });
|
||||
|
||||
const { register, formState } = methods;
|
||||
const [twoFactorRequired, setTwoFactorRequired] = useState(!!totpEmail || false);
|
||||
const [errorMessage, setErrorMessage] = useState<string | null>(null);
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
import { useSession } from "next-auth/react";
|
||||
import { Fragment, useState, useEffect } from "react";
|
||||
import { Fragment, useState } from "react";
|
||||
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import type { RouterOutputs } from "@calcom/trpc/react";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import { AnimatedPopover } from "@calcom/ui";
|
||||
import { Checkbox } from "@calcom/ui";
|
||||
|
||||
import { groupBy } from "../groupBy";
|
||||
import { useFilterQuery } from "../lib/useFilterQuery";
|
||||
|
||||
export type IEventTypesFilters = RouterOutputs["viewer"]["eventTypes"]["listWithTeam"];
|
||||
export type IEventTypeFilter = IEventTypesFilters[0];
|
||||
|
@ -27,24 +29,32 @@ type GroupedEventTypeState = Record<
|
|||
export const EventTypeFilter = () => {
|
||||
const { t } = useLocale();
|
||||
const { data: user } = useSession();
|
||||
const eventTypes = trpc.viewer.eventTypes.listWithTeam.useQuery();
|
||||
const { data: query, pushItemToKey, removeItemByKeyAndValue } = useFilterQuery();
|
||||
|
||||
const [groupedEventTypes, setGroupedEventTypes] = useState<GroupedEventTypeState>();
|
||||
// Will be handled up the tree to redirect
|
||||
useEffect(() => {
|
||||
if (!eventTypes.data) return;
|
||||
// Group event types by team
|
||||
const grouped = groupBy<IEventTypeFilter>(
|
||||
eventTypes.data.filter((el) => el.team),
|
||||
(item) => item?.team?.name || ""
|
||||
); // Add the team name
|
||||
const individualEvents = eventTypes.data.filter((el) => !el.team);
|
||||
// push indivdual events to the start of grouped array
|
||||
setGroupedEventTypes({ user_own_event_types: individualEvents, ...grouped });
|
||||
}, [eventTypes.data, user]);
|
||||
|
||||
if (!user) return null;
|
||||
const eventTypes = trpc.viewer.eventTypes.listWithTeam.useQuery(undefined, {
|
||||
onSuccess: (data) => {
|
||||
// Will be handled up the tree to redirect
|
||||
// Group event types by team
|
||||
const grouped = groupBy<IEventTypeFilter>(
|
||||
data.filter((el) => el.team),
|
||||
(item) => item?.team?.name || ""
|
||||
); // Add the team name
|
||||
const individualEvents = data.filter((el) => !el.team);
|
||||
// push indivdual events to the start of grouped array
|
||||
setGroupedEventTypes(
|
||||
individualEvents.length > 0 ? { user_own_event_types: individualEvents, ...grouped } : grouped
|
||||
);
|
||||
},
|
||||
enabled: !!user,
|
||||
});
|
||||
|
||||
return (
|
||||
if (!eventTypes.data) return null;
|
||||
|
||||
const isNotEmpty = eventTypes.data.length > 0;
|
||||
|
||||
return eventTypes.status === "success" && isNotEmpty ? (
|
||||
<AnimatedPopover text={t("event_type")}>
|
||||
<div className="">
|
||||
{groupedEventTypes &&
|
||||
|
@ -54,25 +64,23 @@ export const EventTypeFilter = () => {
|
|||
{teamName === "user_own_event_types" ? t("individual") : teamName}
|
||||
</div>
|
||||
{groupedEventTypes[teamName].map((eventType) => (
|
||||
<Fragment key={eventType.id}>
|
||||
<div className="item-center flex px-4 py-[6px]">
|
||||
<p className="text-default block self-center truncate text-sm font-medium">
|
||||
{eventType.title}
|
||||
</p>
|
||||
<div className="ml-auto">
|
||||
<input
|
||||
type="checkbox"
|
||||
name=""
|
||||
id=""
|
||||
className="text-primary-600 focus:ring-primary-500 border-default h-4 w-4 rounded ltr:mr-2 rtl:ml-2 "
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Fragment>
|
||||
<div key={eventType.id} className="item-center flex px-4 py-1.5">
|
||||
<Checkbox
|
||||
checked={query.eventTypeIds?.includes(eventType.id)}
|
||||
onChange={(e) => {
|
||||
if (e.target.checked) {
|
||||
pushItemToKey("eventTypeIds", eventType.id);
|
||||
} else if (!e.target.checked) {
|
||||
removeItemByKeyAndValue("eventTypeIds", eventType.id);
|
||||
}
|
||||
}}
|
||||
description={eventType.title}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</Fragment>
|
||||
))}
|
||||
</div>
|
||||
</AnimatedPopover>
|
||||
);
|
||||
) : null;
|
||||
};
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import { Fragment, ReactNode } from "react";
|
||||
import type { ReactNode } from "react";
|
||||
import { Fragment } from "react";
|
||||
|
||||
import { EventTypeFilter } from "./EventTypeFilter";
|
||||
import { PeopleFilter } from "./PeopleFilter";
|
||||
import { TeamsMemberFilter } from "./TeamFilter";
|
||||
|
||||
type FilterTypes = "teams" | "people";
|
||||
type FilterTypes = "teams" | "people" | "eventType";
|
||||
|
||||
type Filter = {
|
||||
name: FilterTypes;
|
||||
|
@ -25,6 +27,12 @@ const filters: Filter[] = [
|
|||
controllingQueryParams: ["usersId"],
|
||||
showByDefault: true,
|
||||
},
|
||||
{
|
||||
name: "eventType",
|
||||
component: <EventTypeFilter />,
|
||||
controllingQueryParams: ["eventTypeId"],
|
||||
showByDefault: true,
|
||||
},
|
||||
];
|
||||
|
||||
export function FiltersContainer() {
|
||||
|
|
|
@ -102,6 +102,15 @@ export const getHandler = async ({ ctx, input }: GetOptions) => {
|
|||
},
|
||||
],
|
||||
},
|
||||
eventTypeIds: {
|
||||
AND: [
|
||||
{
|
||||
eventTypeId: {
|
||||
in: input.filters?.eventTypeIds,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const filtersCombined: Prisma.BookingWhereInput[] =
|
||||
|
|
Loading…
Reference in New Issue
Block a user