mirror of
https://github.com/lukevella/rallly.git
synced 2025-05-14 17:36:49 +02:00
Update analytics (#432)
This commit is contained in:
parent
a4ca5f1676
commit
b0aa9db26d
18 changed files with 122 additions and 106 deletions
3
declarations/environment.d.ts
vendored
3
declarations/environment.d.ts
vendored
|
@ -6,7 +6,8 @@ declare global {
|
||||||
SECRET_PASSWORD: string;
|
SECRET_PASSWORD: string;
|
||||||
NEXT_PUBLIC_LEGACY_POLLS?: string;
|
NEXT_PUBLIC_LEGACY_POLLS?: string;
|
||||||
NEXT_PUBLIC_MAINTENANCE_MODE?: string;
|
NEXT_PUBLIC_MAINTENANCE_MODE?: string;
|
||||||
PLAUSIBLE_DOMAIN?: string;
|
NEXT_PUBLIC_POSTHOG_API_KEY?: string;
|
||||||
|
NEXT_PUBLIC_POSTHOG_API_HOST?: string;
|
||||||
NEXT_PUBLIC_CRISP_WEBSITE_ID?: string;
|
NEXT_PUBLIC_CRISP_WEBSITE_ID?: string;
|
||||||
LEGACY_MONGODB_URI?: string;
|
LEGACY_MONGODB_URI?: string;
|
||||||
SUPPORT_EMAIL: string;
|
SUPPORT_EMAIL: string;
|
||||||
|
|
|
@ -49,10 +49,10 @@
|
||||||
"nanoid": "^3.1.30",
|
"nanoid": "^3.1.30",
|
||||||
"next": "^13.1.3",
|
"next": "^13.1.3",
|
||||||
"next-i18next": "^12.1.0",
|
"next-i18next": "^12.1.0",
|
||||||
"next-plausible": "^3.6.4",
|
|
||||||
"next-seo": "^5.15.0",
|
"next-seo": "^5.15.0",
|
||||||
"nodemailer": "^6.7.2",
|
"nodemailer": "^6.7.2",
|
||||||
"postcss": "^8.4.21",
|
"postcss": "^8.4.21",
|
||||||
|
"posthog-js": "^1.40.2",
|
||||||
"prisma": "^4.9.0",
|
"prisma": "^4.9.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-big-calendar": "^1.5.0",
|
"react-big-calendar": "^1.5.0",
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { NextPage } from "next";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next";
|
||||||
import { usePlausible } from "next-plausible";
|
import posthog from "posthog-js";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useSessionStorage } from "react-use";
|
import { useSessionStorage } from "react-use";
|
||||||
|
|
||||||
|
@ -92,16 +92,12 @@ const Page: NextPage<CreatePollPageProps> = ({
|
||||||
|
|
||||||
const [isRedirecting, setIsRedirecting] = React.useState(false);
|
const [isRedirecting, setIsRedirecting] = React.useState(false);
|
||||||
|
|
||||||
const plausible = usePlausible();
|
|
||||||
|
|
||||||
const createPoll = trpc.useMutation(["polls.create"], {
|
const createPoll = trpc.useMutation(["polls.create"], {
|
||||||
onSuccess: (res) => {
|
onSuccess: (res) => {
|
||||||
setIsRedirecting(true);
|
setIsRedirecting(true);
|
||||||
plausible("Created poll", {
|
posthog.capture("created poll", {
|
||||||
props: {
|
numberOfOptions: formData.options?.options?.length,
|
||||||
numberOfOptions: formData.options?.options?.length,
|
optionsView: formData?.options?.view,
|
||||||
optionsView: formData?.options?.view,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
setPersistedFormData(initialNewEventData);
|
setPersistedFormData(initialNewEventData);
|
||||||
router.replace(`/admin/${res.urlId}?sharing=true`);
|
router.replace(`/admin/${res.urlId}?sharing=true`);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { AnimatePresence, motion } from "framer-motion";
|
import { AnimatePresence, motion } from "framer-motion";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next";
|
||||||
import { usePlausible } from "next-plausible";
|
import posthog from "posthog-js";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
|
|
||||||
|
@ -39,18 +39,16 @@ const Discussion: React.VoidFunctionComponent = () => {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const plausible = usePlausible();
|
|
||||||
|
|
||||||
const addComment = trpc.useMutation("polls.comments.add", {
|
const addComment = trpc.useMutation("polls.comments.add", {
|
||||||
onSuccess: (newComment) => {
|
onSuccess: (newComment) => {
|
||||||
session.refresh();
|
posthog.capture("created comment");
|
||||||
|
|
||||||
queryClient.setQueryData(
|
queryClient.setQueryData(
|
||||||
["polls.comments.list", { pollId }],
|
["polls.comments.list", { pollId }],
|
||||||
(existingComments = []) => {
|
(existingComments = []) => {
|
||||||
return [...existingComments, newComment];
|
return [...existingComments, newComment];
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
plausible("Created comment");
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -64,7 +62,7 @@ const Discussion: React.VoidFunctionComponent = () => {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
plausible("Deleted comment");
|
posthog.capture("deleted comment");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -83,13 +83,20 @@ const Dropdown: React.VoidFunctionComponent<DropdownProps> = ({
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const AnchorLink: React.VoidFunctionComponent<{
|
const AnchorLink = React.forwardRef<
|
||||||
href?: string;
|
HTMLAnchorElement,
|
||||||
children?: React.ReactNode;
|
{
|
||||||
className?: string;
|
href?: string;
|
||||||
}> = ({ href = "", className, children, ...forwardProps }) => {
|
children?: React.ReactNode;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
>(function AnchorLink(
|
||||||
|
{ href = "", className, children, ...forwardProps },
|
||||||
|
ref,
|
||||||
|
) {
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
|
ref={ref}
|
||||||
href={href}
|
href={href}
|
||||||
passHref
|
passHref
|
||||||
className={clsx(
|
className={clsx(
|
||||||
|
@ -101,7 +108,7 @@ const AnchorLink: React.VoidFunctionComponent<{
|
||||||
{children}
|
{children}
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
export const DropdownItem: React.VoidFunctionComponent<{
|
export const DropdownItem: React.VoidFunctionComponent<{
|
||||||
icon?: React.ComponentType<{ className?: string }>;
|
icon?: React.ComponentType<{ className?: string }>;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next";
|
||||||
import { usePlausible } from "next-plausible";
|
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -40,8 +39,6 @@ const MonthCalendar: React.VoidFunctionComponent<DateTimePickerProps> = ({
|
||||||
const { t } = useTranslation("app");
|
const { t } = useTranslation("app");
|
||||||
const isTimedEvent = options.some((option) => option.type === "timeSlot");
|
const isTimedEvent = options.some((option) => option.type === "timeSlot");
|
||||||
|
|
||||||
const plausible = usePlausible();
|
|
||||||
|
|
||||||
const optionsByDay = React.useMemo(() => {
|
const optionsByDay = React.useMemo(() => {
|
||||||
const res: Record<
|
const res: Record<
|
||||||
string,
|
string,
|
||||||
|
@ -355,7 +352,6 @@ const MonthCalendar: React.VoidFunctionComponent<DateTimePickerProps> = ({
|
||||||
disabled={datepicker.selection.length < 2}
|
disabled={datepicker.selection.length < 2}
|
||||||
label={t("applyToAllDates")}
|
label={t("applyToAllDates")}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
plausible("Applied options to all dates");
|
|
||||||
const times = optionsForDay.map(
|
const times = optionsForDay.map(
|
||||||
({ option }) => {
|
({ option }) => {
|
||||||
if (option.type === "date") {
|
if (option.type === "date") {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next";
|
||||||
import { usePlausible } from "next-plausible";
|
import posthog from "posthog-js";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
|
|
||||||
|
@ -18,7 +18,6 @@ const LoginForm: React.VoidFunctionComponent = () => {
|
||||||
|
|
||||||
const login = trpc.useMutation(["login"]);
|
const login = trpc.useMutation(["login"]);
|
||||||
|
|
||||||
const plausible = usePlausible();
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
return (
|
return (
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
|
@ -32,7 +31,7 @@ const LoginForm: React.VoidFunctionComponent = () => {
|
||||||
{!formState.isSubmitSuccessful ? (
|
{!formState.isSubmitSuccessful ? (
|
||||||
<form
|
<form
|
||||||
onSubmit={handleSubmit(async ({ email }) => {
|
onSubmit={handleSubmit(async ({ email }) => {
|
||||||
plausible("Login requested");
|
posthog.capture("login requested", { email });
|
||||||
await login.mutateAsync({ email, path: router.asPath });
|
await login.mutateAsync({ email, path: router.asPath });
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { NextPage } from "next";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next";
|
||||||
import { usePlausible } from "next-plausible";
|
import posthog from "posthog-js";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import { useMount } from "react-use";
|
import { useMount } from "react-use";
|
||||||
|
@ -43,7 +43,6 @@ const PollPage: NextPage = () => {
|
||||||
const session = useUser();
|
const session = useUser();
|
||||||
|
|
||||||
const queryClient = trpc.useContext();
|
const queryClient = trpc.useContext();
|
||||||
const plausible = usePlausible();
|
|
||||||
|
|
||||||
const { mutate: updatePollMutation } = useUpdatePollMutation();
|
const { mutate: updatePollMutation } = useUpdatePollMutation();
|
||||||
|
|
||||||
|
@ -55,7 +54,7 @@ const PollPage: NextPage = () => {
|
||||||
verified: true,
|
verified: true,
|
||||||
});
|
});
|
||||||
session.refresh();
|
session.refresh();
|
||||||
plausible("Verified email");
|
posthog.capture("verified email");
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: () => {
|
||||||
toast.error(t("linkHasExpired"));
|
toast.error(t("linkHasExpired"));
|
||||||
|
@ -81,7 +80,7 @@ const PollPage: NextPage = () => {
|
||||||
{
|
{
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
toast.success(t("notificationsDisabled"));
|
toast.success(t("notificationsDisabled"));
|
||||||
plausible("Unsubscribed from notifications");
|
posthog.capture("unsubscribed from notifications");
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -89,7 +88,7 @@ const PollPage: NextPage = () => {
|
||||||
shallow: true,
|
shallow: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [plausible, urlId, router, updatePollMutation, t]);
|
}, [urlId, router, updatePollMutation, t]);
|
||||||
|
|
||||||
const checkIfWideScreen = () => window.innerWidth > 640;
|
const checkIfWideScreen = () => window.innerWidth > 640;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { Trans, useTranslation } from "next-i18next";
|
import { Trans, useTranslation } from "next-i18next";
|
||||||
import { usePlausible } from "next-plausible";
|
import posthog from "posthog-js";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
|
|
||||||
|
@ -19,13 +19,11 @@ export const DeletePollForm: React.VoidFunctionComponent<{
|
||||||
const { register, handleSubmit, formState, watch } =
|
const { register, handleSubmit, formState, watch } =
|
||||||
useForm<{ confirmation: string }>();
|
useForm<{ confirmation: string }>();
|
||||||
|
|
||||||
const plausible = usePlausible();
|
|
||||||
|
|
||||||
const confirmationText = watch("confirmation");
|
const confirmationText = watch("confirmation");
|
||||||
const canDelete = confirmationText === confirmText;
|
const canDelete = confirmationText === confirmText;
|
||||||
const deletePoll = trpc.useMutation("polls.delete", {
|
const deletePoll = trpc.useMutation("polls.delete", {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
plausible("Deleted poll");
|
posthog.capture("deleted poll");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import { usePlausible } from "next-plausible";
|
import posthog from "posthog-js";
|
||||||
|
|
||||||
import { trpc } from "../../utils/trpc";
|
import { trpc } from "../../utils/trpc";
|
||||||
import { usePoll } from "../poll-context";
|
import { usePoll } from "../poll-context";
|
||||||
import { useUser } from "../user-provider";
|
|
||||||
import { ParticipantForm } from "./types";
|
import { ParticipantForm } from "./types";
|
||||||
|
|
||||||
export const normalizeVotes = (
|
export const normalizeVotes = (
|
||||||
|
@ -17,12 +16,12 @@ export const normalizeVotes = (
|
||||||
|
|
||||||
export const useAddParticipantMutation = () => {
|
export const useAddParticipantMutation = () => {
|
||||||
const queryClient = trpc.useContext();
|
const queryClient = trpc.useContext();
|
||||||
const session = useUser();
|
|
||||||
const plausible = usePlausible();
|
|
||||||
|
|
||||||
return trpc.useMutation(["polls.participants.add"], {
|
return trpc.useMutation(["polls.participants.add"], {
|
||||||
onSuccess: (participant) => {
|
onSuccess: (participant) => {
|
||||||
plausible("Add participant");
|
posthog.capture("add participant", {
|
||||||
|
name: participant.name,
|
||||||
|
});
|
||||||
queryClient.setQueryData(
|
queryClient.setQueryData(
|
||||||
["polls.participants.list", { pollId: participant.pollId }],
|
["polls.participants.list", { pollId: participant.pollId }],
|
||||||
(existingParticipants = []) => {
|
(existingParticipants = []) => {
|
||||||
|
@ -33,17 +32,17 @@ export const useAddParticipantMutation = () => {
|
||||||
"polls.participants.list",
|
"polls.participants.list",
|
||||||
{ pollId: participant.pollId },
|
{ pollId: participant.pollId },
|
||||||
]);
|
]);
|
||||||
session.refresh();
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useUpdateParticipantMutation = () => {
|
export const useUpdateParticipantMutation = () => {
|
||||||
const queryClient = trpc.useContext();
|
const queryClient = trpc.useContext();
|
||||||
const plausible = usePlausible();
|
|
||||||
return trpc.useMutation("polls.participants.update", {
|
return trpc.useMutation("polls.participants.update", {
|
||||||
onSuccess: (participant) => {
|
onSuccess: (participant) => {
|
||||||
plausible("Update participant");
|
posthog.capture("update participant", {
|
||||||
|
name: participant.name,
|
||||||
|
});
|
||||||
queryClient.setQueryData(
|
queryClient.setQueryData(
|
||||||
["polls.participants.list", { pollId: participant.pollId }],
|
["polls.participants.list", { pollId: participant.pollId }],
|
||||||
(existingParticipants = []) => {
|
(existingParticipants = []) => {
|
||||||
|
@ -66,7 +65,6 @@ export const useUpdateParticipantMutation = () => {
|
||||||
|
|
||||||
export const useDeleteParticipantMutation = () => {
|
export const useDeleteParticipantMutation = () => {
|
||||||
const queryClient = trpc.useContext();
|
const queryClient = trpc.useContext();
|
||||||
const plausible = usePlausible();
|
|
||||||
return trpc.useMutation("polls.participants.delete", {
|
return trpc.useMutation("polls.participants.delete", {
|
||||||
onMutate: ({ participantId, pollId }) => {
|
onMutate: ({ participantId, pollId }) => {
|
||||||
queryClient.setQueryData(
|
queryClient.setQueryData(
|
||||||
|
@ -76,20 +74,23 @@ export const useDeleteParticipantMutation = () => {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: (_, { participantId }) => {
|
||||||
plausible("Remove participant");
|
posthog.capture("remove participant", {
|
||||||
|
participantId,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useUpdatePollMutation = () => {
|
export const useUpdatePollMutation = () => {
|
||||||
const { urlId, admin } = usePoll();
|
const { urlId, admin } = usePoll();
|
||||||
const plausible = usePlausible();
|
|
||||||
const queryClient = trpc.useContext();
|
const queryClient = trpc.useContext();
|
||||||
return trpc.useMutation(["polls.update"], {
|
return trpc.useMutation(["polls.update"], {
|
||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
queryClient.setQueryData(["polls.get", { urlId, admin }], data);
|
queryClient.setQueryData(["polls.get", { urlId, admin }], data);
|
||||||
plausible("Updated poll");
|
posthog.capture("updated poll", {
|
||||||
|
id: data.id,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { Trans, useTranslation } from "next-i18next";
|
import { Trans, useTranslation } from "next-i18next";
|
||||||
import { usePlausible } from "next-plausible";
|
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
|
||||||
import { Button } from "@/components/button";
|
import { Button } from "@/components/button";
|
||||||
|
@ -18,7 +17,6 @@ const NotificationsToggle: React.VoidFunctionComponent = () => {
|
||||||
|
|
||||||
const { mutate: updatePollMutation } = useUpdatePollMutation();
|
const { mutate: updatePollMutation } = useUpdatePollMutation();
|
||||||
|
|
||||||
const plausible = usePlausible();
|
|
||||||
return (
|
return (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
content={
|
content={
|
||||||
|
@ -63,12 +61,7 @@ const NotificationsToggle: React.VoidFunctionComponent = () => {
|
||||||
notifications: !poll.notifications,
|
notifications: !poll.notifications,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
onSuccess: ({ notifications }) => {
|
onSuccess: () => {
|
||||||
plausible(
|
|
||||||
notifications
|
|
||||||
? "Turned notifications on"
|
|
||||||
: "Turned notifications off",
|
|
||||||
);
|
|
||||||
setIsUpdatingNotifications(false);
|
setIsUpdatingNotifications(false);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next";
|
||||||
import { usePlausible } from "next-plausible";
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { useDayjs } from "../utils/dayjs";
|
import { useDayjs } from "../utils/dayjs";
|
||||||
|
@ -14,7 +13,6 @@ const Preferences: React.VoidFunctionComponent = () => {
|
||||||
useDayjs();
|
useDayjs();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const plausible = usePlausible();
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="mb-4 space-y-2">
|
<div className="mb-4 space-y-2">
|
||||||
|
@ -36,11 +34,6 @@ const Preferences: React.VoidFunctionComponent = () => {
|
||||||
})}
|
})}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setWeekStartsOn("monday");
|
setWeekStartsOn("monday");
|
||||||
plausible("Change week start", {
|
|
||||||
props: {
|
|
||||||
timeFormat: "monday",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
|
@ -52,11 +45,6 @@ const Preferences: React.VoidFunctionComponent = () => {
|
||||||
})}
|
})}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setWeekStartsOn("sunday");
|
setWeekStartsOn("sunday");
|
||||||
plausible("Change week start", {
|
|
||||||
props: {
|
|
||||||
timeFormat: "sunday",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
|
@ -76,11 +64,6 @@ const Preferences: React.VoidFunctionComponent = () => {
|
||||||
})}
|
})}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setTimeFormat("12h");
|
setTimeFormat("12h");
|
||||||
plausible("Change time format", {
|
|
||||||
props: {
|
|
||||||
timeFormat: "12h",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
|
@ -92,11 +75,6 @@ const Preferences: React.VoidFunctionComponent = () => {
|
||||||
})}
|
})}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setTimeFormat("24h");
|
setTimeFormat("24h");
|
||||||
plausible("Change time format", {
|
|
||||||
props: {
|
|
||||||
timeFormat: "24h",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next";
|
||||||
|
import posthog from "posthog-js";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
|
|
||||||
|
@ -33,7 +34,8 @@ export const UserDetails: React.VoidFunctionComponent<UserDetailsProps> = ({
|
||||||
const { refresh } = useUser();
|
const { refresh } = useUser();
|
||||||
|
|
||||||
const changeName = trpc.useMutation("user.changeName", {
|
const changeName = trpc.useMutation("user.changeName", {
|
||||||
onSuccess: () => {
|
onSuccess: (_, { name }) => {
|
||||||
|
posthog.people.set({ name });
|
||||||
refresh();
|
refresh();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next";
|
||||||
|
import posthog from "posthog-js";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { useMount } from "react-use";
|
||||||
|
|
||||||
import { UserSession } from "@/utils/auth";
|
import { UserSession } from "@/utils/auth";
|
||||||
|
|
||||||
|
@ -49,12 +51,44 @@ export const UserProvider = (props: { children?: React.ReactNode }) => {
|
||||||
const { t } = useTranslation("app");
|
const { t } = useTranslation("app");
|
||||||
|
|
||||||
const { data: user, refetch } = trpcNext.whoami.get.useQuery();
|
const { data: user, refetch } = trpcNext.whoami.get.useQuery();
|
||||||
const logout = trpcNext.whoami.destroy.useMutation();
|
|
||||||
|
const logout = trpcNext.whoami.destroy.useMutation({
|
||||||
|
onSuccess: () => {
|
||||||
|
posthog.reset();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
useMount(() => {
|
||||||
|
if (!process.env.NEXT_PUBLIC_POSTHOG_API_KEY) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_API_KEY, {
|
||||||
|
api_host: process.env.NEXT_PUBLIC_POSTHOG_API_HOST,
|
||||||
|
opt_out_capturing_by_default: false,
|
||||||
|
capture_pageview: false,
|
||||||
|
capture_pageleave: false,
|
||||||
|
autocapture: false,
|
||||||
|
loaded: (posthog) => {
|
||||||
|
if (process.env.NODE_ENV === "development") {
|
||||||
|
posthog.opt_out_capturing();
|
||||||
|
}
|
||||||
|
if (user && posthog.get_distinct_id() !== user.id) {
|
||||||
|
posthog.identify(
|
||||||
|
user.id,
|
||||||
|
!user.isGuest
|
||||||
|
? { email: user.email, name: user.name }
|
||||||
|
: { name: user.id },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
const shortName = user
|
const shortName = user
|
||||||
? user.isGuest === false
|
? user.isGuest === false
|
||||||
? user.name
|
? user.name
|
||||||
: `${t("guest")}-${user.id.substring(user.id.length - 4)}`
|
: user.id.substring(0, 10)
|
||||||
: t("guest");
|
: t("guest");
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
|
|
|
@ -8,7 +8,6 @@ import { NextPage } from "next";
|
||||||
import { AppProps } from "next/app";
|
import { AppProps } from "next/app";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import { appWithTranslation } from "next-i18next";
|
import { appWithTranslation } from "next-i18next";
|
||||||
import PlausibleProvider from "next-plausible";
|
|
||||||
import { DefaultSeo } from "next-seo";
|
import { DefaultSeo } from "next-seo";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Toaster } from "react-hot-toast";
|
import { Toaster } from "react-hot-toast";
|
||||||
|
@ -44,13 +43,7 @@ const MyApp: NextPage<AppProps> = ({ Component, pageProps }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PlausibleProvider
|
<>
|
||||||
domain="rallly.co"
|
|
||||||
customDomain={process.env.NEXT_PUBLIC_PLAUSIBLE_DOMAIN}
|
|
||||||
trackOutboundLinks={true}
|
|
||||||
selfHosted={true}
|
|
||||||
enabled={!!process.env.NEXT_PUBLIC_PLAUSIBLE_DOMAIN}
|
|
||||||
>
|
|
||||||
<DefaultSeo
|
<DefaultSeo
|
||||||
openGraph={{
|
openGraph={{
|
||||||
siteName: "Rallly",
|
siteName: "Rallly",
|
||||||
|
@ -84,7 +77,7 @@ const MyApp: NextPage<AppProps> = ({ Component, pageProps }) => {
|
||||||
}
|
}
|
||||||
`}</style>
|
`}</style>
|
||||||
<Component {...pageProps} />
|
<Component {...pageProps} />
|
||||||
</PlausibleProvider>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import { NextPage } from "next";
|
import { NextPage } from "next";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next";
|
||||||
import { usePlausible } from "next-plausible";
|
import posthog from "posthog-js";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useMount } from "react-use";
|
import { useMount } from "react-use";
|
||||||
|
|
||||||
import FullPageLoader from "../components/full-page-loader";
|
import FullPageLoader from "../components/full-page-loader";
|
||||||
|
import { withSession } from "../components/user-provider";
|
||||||
|
import { withSessionSsr } from "../utils/auth";
|
||||||
import { trpc } from "../utils/trpc";
|
import { trpc } from "../utils/trpc";
|
||||||
import { withPageTranslations } from "../utils/with-page-translations";
|
import { withPageTranslations } from "../utils/with-page-translations";
|
||||||
|
|
||||||
|
@ -13,18 +15,19 @@ const Demo: NextPage = () => {
|
||||||
const { t } = useTranslation("app");
|
const { t } = useTranslation("app");
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const plausible = usePlausible();
|
|
||||||
const createDemo = trpc.useMutation(["polls.demo.create"]);
|
const createDemo = trpc.useMutation(["polls.demo.create"]);
|
||||||
|
|
||||||
useMount(async () => {
|
useMount(async () => {
|
||||||
const urlId = await createDemo.mutateAsync();
|
const urlId = await createDemo.mutateAsync();
|
||||||
plausible("Create demo poll");
|
posthog.capture("create demo poll");
|
||||||
router.replace(`/admin/${urlId}`);
|
router.replace(`/admin/${urlId}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
return <FullPageLoader>{t("creatingDemo")}</FullPageLoader>;
|
return <FullPageLoader>{t("creatingDemo")}</FullPageLoader>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getServerSideProps = withPageTranslations(["common", "app"]);
|
export const getServerSideProps = withSessionSsr(
|
||||||
|
withPageTranslations(["common", "app"]),
|
||||||
|
);
|
||||||
|
|
||||||
export default Demo;
|
export default withSession(Demo);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { GetServerSideProps, NextPage } from "next";
|
import { GetServerSideProps, NextPage } from "next";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { usePlausible } from "next-plausible";
|
import posthog from "posthog-js";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import { useTimeoutFn } from "react-use";
|
import { useTimeoutFn } from "react-use";
|
||||||
|
@ -20,14 +20,13 @@ const Page: NextPage<{ success: boolean; redirectTo: string }> = ({
|
||||||
redirectTo,
|
redirectTo,
|
||||||
}) => {
|
}) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const pluasible = usePlausible();
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
toast.error("Login failed! Link is expired or invalid");
|
toast.error("Login failed! Link is expired or invalid");
|
||||||
}
|
}
|
||||||
|
|
||||||
useTimeoutFn(() => {
|
useTimeoutFn(() => {
|
||||||
if (success) {
|
if (success) {
|
||||||
pluasible("Login completed");
|
posthog.capture("login completed");
|
||||||
}
|
}
|
||||||
router.replace(redirectTo);
|
router.replace(redirectTo);
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
29
yarn.lock
29
yarn.lock
|
@ -1677,6 +1677,11 @@
|
||||||
"@sentry/utils" "7.32.1"
|
"@sentry/utils" "7.32.1"
|
||||||
tslib "^1.9.3"
|
tslib "^1.9.3"
|
||||||
|
|
||||||
|
"@sentry/types@7.22.0":
|
||||||
|
version "7.22.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.22.0.tgz#58e4ce77b523048e0f31e2ea4b597946d76f6079"
|
||||||
|
integrity sha512-LhCL+wb1Jch+OesB2CIt6xpfO1Ab6CRvoNYRRzVumWPLns1T3ZJkarYfhbLaOEIb38EIbPgREdxn2AJT560U4Q==
|
||||||
|
|
||||||
"@sentry/types@7.32.1":
|
"@sentry/types@7.32.1":
|
||||||
version "7.32.1"
|
version "7.32.1"
|
||||||
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.32.1.tgz#24728cf098694d31ceb4f556164674477c6433d6"
|
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.32.1.tgz#24728cf098694d31ceb4f556164674477c6433d6"
|
||||||
|
@ -3482,6 +3487,11 @@ fastq@^1.6.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
reusify "^1.0.4"
|
reusify "^1.0.4"
|
||||||
|
|
||||||
|
fflate@^0.4.1:
|
||||||
|
version "0.4.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.4.8.tgz#f90b82aefbd8ac174213abb338bd7ef848f0f5ae"
|
||||||
|
integrity sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==
|
||||||
|
|
||||||
file-entry-cache@^6.0.1:
|
file-entry-cache@^6.0.1:
|
||||||
version "6.0.1"
|
version "6.0.1"
|
||||||
resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz"
|
resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz"
|
||||||
|
@ -4504,11 +4514,6 @@ next-i18next@^12.1.0:
|
||||||
i18next-fs-backend "^1.1.5"
|
i18next-fs-backend "^1.1.5"
|
||||||
react-i18next "^11.18.4"
|
react-i18next "^11.18.4"
|
||||||
|
|
||||||
next-plausible@^3.6.4:
|
|
||||||
version "3.6.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/next-plausible/-/next-plausible-3.6.4.tgz#15684340736e47d3ffa49f9c8fae598e3cfefca6"
|
|
||||||
integrity sha512-aHL4IL+gkkjs5ScB18LZ3LMEWXKR5VTvnMDs/fHNFHadOh23i37fD+VP5oAQLALR8Mde63l9JJljrw9DkvjWjQ==
|
|
||||||
|
|
||||||
next-seo@^5.15.0:
|
next-seo@^5.15.0:
|
||||||
version "5.15.0"
|
version "5.15.0"
|
||||||
resolved "https://registry.yarnpkg.com/next-seo/-/next-seo-5.15.0.tgz#b1a90508599774982909ea44803323c6fb7b50f4"
|
resolved "https://registry.yarnpkg.com/next-seo/-/next-seo-5.15.0.tgz#b1a90508599774982909ea44803323c6fb7b50f4"
|
||||||
|
@ -4925,6 +4930,15 @@ postcss@^8.4.21:
|
||||||
picocolors "^1.0.0"
|
picocolors "^1.0.0"
|
||||||
source-map-js "^1.0.2"
|
source-map-js "^1.0.2"
|
||||||
|
|
||||||
|
posthog-js@^1.40.2:
|
||||||
|
version "1.40.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.40.2.tgz#f9658f532653789287015f7df9f61988949e08e9"
|
||||||
|
integrity sha512-jVq/g5J/339u2uHulfpTR57iyG8xmbSKpB9xtbEqp5gQpr/eu0P4OAdfye12tsjm8IB3+7RR/SDArQ7PI/m6Yg==
|
||||||
|
dependencies:
|
||||||
|
"@sentry/types" "7.22.0"
|
||||||
|
fflate "^0.4.1"
|
||||||
|
rrweb-snapshot "^1.1.14"
|
||||||
|
|
||||||
prelude-ls@^1.2.1:
|
prelude-ls@^1.2.1:
|
||||||
version "1.2.1"
|
version "1.2.1"
|
||||||
resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz"
|
resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz"
|
||||||
|
@ -5330,6 +5344,11 @@ rollup@2.78.0:
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "~2.3.2"
|
fsevents "~2.3.2"
|
||||||
|
|
||||||
|
rrweb-snapshot@^1.1.14:
|
||||||
|
version "1.1.14"
|
||||||
|
resolved "https://registry.yarnpkg.com/rrweb-snapshot/-/rrweb-snapshot-1.1.14.tgz#9d4d9be54a28a893373428ee4393ec7e5bd83fcc"
|
||||||
|
integrity sha512-eP5pirNjP5+GewQfcOQY4uBiDnpqxNRc65yKPW0eSoU1XamDfc4M8oqpXGMyUyvLyxFDB0q0+DChuxxiU2FXBQ==
|
||||||
|
|
||||||
rtl-css-js@^1.14.0:
|
rtl-css-js@^1.14.0:
|
||||||
version "1.15.0"
|
version "1.15.0"
|
||||||
resolved "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.15.0.tgz"
|
resolved "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.15.0.tgz"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue