diff --git a/src/components/faqs/PlannerFaqs.tsx b/src/components/faqs/PlannerFaqs.tsx
index f48a579c..a7b1fcbb 100644
--- a/src/components/faqs/PlannerFaqs.tsx
+++ b/src/components/faqs/PlannerFaqs.tsx
@@ -1,6 +1,7 @@
import classNames from 'classnames'
import { Transition, Disclosure } from '@headlessui/react'
import { ChevronUpIcon } from '@heroicons/react/24/outline'
+import { AnalyticsTracker } from '../../utils/AnalyticsTracker'
const PlannerFaqs = () => {
const data = [
@@ -158,7 +159,14 @@ const PlannerFaqs = () => {
as="div"
defaultOpen={faqIdx === 0}
key={`planner-faq-${faqIdx}`}
- className="rounded-2xl bg-white p-3 dark:bg-dark"
+ className={`rounded-2xl bg-white p-3 dark:bg-dark faq-disclosure-${faqIdx}`}
+ onClick={() => {
+ const disclosure = document.querySelector(`.faq-disclosure-${faqIdx}`);
+ const isOpen = disclosure?.getAttribute('data-headlessui-state') !== 'open';
+ if (isOpen && faq.question.type === 'span') {
+ AnalyticsTracker.trackFaq(faq.question.props.children)
+ }
+ }}
>
{({ open }) => (
<>
diff --git a/src/components/planner/schedule/PrintSchedule.tsx b/src/components/planner/schedule/PrintSchedule.tsx
index 75e5b8d7..671e3037 100644
--- a/src/components/planner/schedule/PrintSchedule.tsx
+++ b/src/components/planner/schedule/PrintSchedule.tsx
@@ -4,6 +4,7 @@ import { Button } from '../../ui/button'
import { CameraIcon } from '@heroicons/react/24/outline'
import { toPng } from 'html-to-image'
import { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from '../../ui/tooltip'
+import { AnalyticsTracker, Feature } from '../../../utils/AnalyticsTracker'
const PrintSchedule = ({ component }) => {
const { enabled } = useContext(ThemeContext)
@@ -24,6 +25,8 @@ const PrintSchedule = ({ component }) => {
.catch((err) => {
console.log(err)
})
+
+ AnalyticsTracker.trackFeature(Feature.SCREENSHOT)
},
[component]
)
diff --git a/src/components/planner/schedule/ToggleScheduleGrid.tsx b/src/components/planner/schedule/ToggleScheduleGrid.tsx
index de7ee9cc..0c39f1cb 100644
--- a/src/components/planner/schedule/ToggleScheduleGrid.tsx
+++ b/src/components/planner/schedule/ToggleScheduleGrid.tsx
@@ -1,6 +1,7 @@
import { Button } from '../../ui/button'
import { ViewColumnsIcon } from '@heroicons/react/24/outline'
import { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from '../../ui/tooltip'
+import { AnalyticsTracker, Feature } from '../../../utils/AnalyticsTracker'
const ToggleScheduleGrid = ({ showGridHook }) => {
const [showGrid, setShowGrid] = showGridHook
@@ -12,7 +13,10 @@ const ToggleScheduleGrid = ({ showGridHook }) => {
diff --git a/src/components/planner/sidebar/CoursesController/ClassSelector.tsx b/src/components/planner/sidebar/CoursesController/ClassSelector.tsx
index cdae8f66..a8082405 100644
--- a/src/components/planner/sidebar/CoursesController/ClassSelector.tsx
+++ b/src/components/planner/sidebar/CoursesController/ClassSelector.tsx
@@ -9,6 +9,7 @@ import { teacherIdsFromCourseInfo, uniqueTeachersFromCourseInfo, getAllPickedSlo
import { Button } from '../../../ui/button'
import ProfessorItem from './ProfessorItem'
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuPortal, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from '../../../ui/dropdown-menu'
+import { AnalyticsTracker, Feature } from '../../../../utils/AnalyticsTracker'
import ClassSelectorDropdownController from './ClassSelectorDropdownController'
type Props = {
@@ -58,6 +59,8 @@ const ClassSelector = ({ course }: Props) => {
newMultipleOptions[selectedOption].course_options = courseOptions;
setMultipleOptions(newMultipleOptions);
setLocked(!locked)
+
+ AnalyticsTracker.trackFeature(Feature.LOCK_TOGGLE);
}
useEffect(() => {
diff --git a/src/components/planner/sidebar/OptionsController.tsx b/src/components/planner/sidebar/OptionsController.tsx
index 78ef3c25..cf535d82 100644
--- a/src/components/planner/sidebar/OptionsController.tsx
+++ b/src/components/planner/sidebar/OptionsController.tsx
@@ -4,6 +4,7 @@ import { EllipsisHorizontalIcon } from '@heroicons/react/24/outline'
import { useContext } from 'react'
import MultipleOptionsContext from '../../../contexts/MultipleOptionsContext';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../ui/tooltip';
+import { AnalyticsTracker, Feature } from '../../../utils/AnalyticsTracker';
/**
* Sortable list of schedule options
@@ -28,6 +29,9 @@ const OptionsController = () => {
animation={200}
delay={2}
multiDrag
+ onEnd={() => {
+ AnalyticsTracker.trackFeature(Feature.OPTION_REORDER);
+ }}
>
{multipleOptions.map((option: Option) => (
{
setMultipleOptions((prevMultipleOptions) => {
const updatedMultipleOptions = prevMultipleOptions.map((item) =>
- item.id === multipleOptions[selectedOption].id ? { ...item, icon: newIcon } : item
+ item.id === multipleOptions[selectedOption].id ? { ...item, icon: newIcon.imageUrl } : item
)
return updatedMultipleOptions;
})
+ AnalyticsTracker.trackFeature(Feature.OPTION_EMOJI);
+ AnalyticsTracker.emoji(newIcon.emoji);
}
return (
@@ -92,7 +96,7 @@ const SelectedOptionController = ({
suggestedEmojisMode={SuggestionMode.RECENT}
emojiStyle={EmojiStyle.APPLE}
onEmojiClick={(emojiData, e) => {
- changeOptionIcon(emojiData.imageUrl)
+ changeOptionIcon(emojiData)
setEmojiPickerOpen(false)
}}
/>
diff --git a/src/components/planner/sidebar/selectedOptionController/CopyOption.tsx b/src/components/planner/sidebar/selectedOptionController/CopyOption.tsx
index e6b8d00b..26b29ade 100644
--- a/src/components/planner/sidebar/selectedOptionController/CopyOption.tsx
+++ b/src/components/planner/sidebar/selectedOptionController/CopyOption.tsx
@@ -5,6 +5,8 @@ import { useToast } from '../../../ui/use-toast'
import { Buffer } from 'buffer'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../../ui/tooltip'
import { CourseOption } from '../../../../@types'
+import { plausible } from '../../../../utils'
+import { AnalyticsTracker, Feature } from '../../../../utils/AnalyticsTracker'
type Props = {
currentOption: CourseOption[]
@@ -48,6 +50,7 @@ const CopyOption = ({ currentOption, className }: Props) => {
setTimeout(() => {
setIcon(false)
}, 1500)
+ AnalyticsTracker.trackFeature(Feature.COPY);
}
return (
diff --git a/src/components/planner/sidebar/selectedOptionController/PasteOption.tsx b/src/components/planner/sidebar/selectedOptionController/PasteOption.tsx
index b5438963..4f1115c6 100644
--- a/src/components/planner/sidebar/selectedOptionController/PasteOption.tsx
+++ b/src/components/planner/sidebar/selectedOptionController/PasteOption.tsx
@@ -11,6 +11,7 @@ import MultipleOptionsContext from '../../../../contexts/MultipleOptionsContext'
import { convertCourseInfoToCourseOption } from '../../../../utils'
import { Button } from '../../../ui/button'
import { useToast } from '../../../ui/use-toast'
+import { AnalyticsTracker, Feature } from '../../../../utils/AnalyticsTracker'
const PasteOption = () => {
const { multipleOptions, setMultipleOptions, selectedOption } = useContext(MultipleOptionsContext)
@@ -97,6 +98,8 @@ const PasteOption = () => {
description: 'A opção foi colada com sucesso',
duration: 1500,
})
+
+ AnalyticsTracker.trackFeature(Feature.PASTE);
}
/**
diff --git a/src/components/planner/sidebar/selectedOptionController/RandomFill.tsx b/src/components/planner/sidebar/selectedOptionController/RandomFill.tsx
index 1ff052bb..3008369e 100644
--- a/src/components/planner/sidebar/selectedOptionController/RandomFill.tsx
+++ b/src/components/planner/sidebar/selectedOptionController/RandomFill.tsx
@@ -8,6 +8,7 @@ import { Checkbox } from '../../../ui/checkbox'
import { Separator } from '../../../ui/separator'
import CourseContext from '../../../../contexts/CourseContext'
import MultipleOptionsContext from '../../../../contexts/MultipleOptionsContext'
+import { AnalyticsTracker, Feature } from '../../../../utils/AnalyticsTracker'
type Props = {
className?: string
@@ -165,6 +166,8 @@ const RandomFill = ({ className }: Props) => {
// Choose a random permutation
const randomNumber = Math.floor(Math.random() * (newPermutations.length - 1))
applySchedule(newPermutations[randomNumber])
+
+ AnalyticsTracker.trackFeature(Feature.RANDOM_FILL);
}
const applySchedule = (classesCombinations: ClassInfo[]) => {
diff --git a/src/components/planner/sidebar/sessionController/CsvExport.tsx b/src/components/planner/sidebar/sessionController/CsvExport.tsx
index 490ae45c..d0b63cea 100644
--- a/src/components/planner/sidebar/sessionController/CsvExport.tsx
+++ b/src/components/planner/sidebar/sessionController/CsvExport.tsx
@@ -2,6 +2,7 @@ import { ArrowUpOnSquareIcon } from '@heroicons/react/24/outline'
import { useContext } from 'react'
import CourseContext from '../../../../contexts/CourseContext'
import MultipleOptionsContext from '../../../../contexts/MultipleOptionsContext'
+import { AnalyticsTracker, Feature } from '../../../../utils/AnalyticsTracker'
//TODO: utils??
const csvEncode = (text: string | null | undefined) => {
@@ -43,6 +44,8 @@ const CsvExport = () => {
a.download = 'schedule.csv'
a.click()
URL.revokeObjectURL(url)
+
+ AnalyticsTracker.trackFeature(Feature.EXPORT_TO_CSV)
}
return (
@@ -52,7 +55,7 @@ const CsvExport = () => {
>
Exportar Opções (CSV)
-
+
)
}
diff --git a/src/components/planner/sidebar/sessionController/course-picker/MajorSearchCombobox.tsx b/src/components/planner/sidebar/sessionController/course-picker/MajorSearchCombobox.tsx
index 82f207be..6254a27c 100644
--- a/src/components/planner/sidebar/sessionController/course-picker/MajorSearchCombobox.tsx
+++ b/src/components/planner/sidebar/sessionController/course-picker/MajorSearchCombobox.tsx
@@ -6,6 +6,7 @@ import MajorContext from '../../../../../contexts/MajorContext'
import { cn, plausible } from '../../../../../utils'
import { Button } from '../../../../ui/button'
import { Popover, PopoverContent, PopoverTrigger } from '../../../../ui/popover'
+import { AnalyticsTracker } from '../../../../../utils/AnalyticsTracker'
interface Props {
selectedMajor: Major | null
@@ -77,9 +78,7 @@ const MajorSearchCombobox = ({ selectedMajor, setSelectedMajor }: Props) => {
setSelectedMajor(currentMajor.id === selectedMajor?.id ? null : currentMajor)
setOpen(false)
- const { trackEvent } = plausible
- trackEvent('Major Selected', { props: { major: currentMajor.name } })
- trackEvent('Faculty', { props: { faculty: currentMajor.faculty_id.toUpperCase() } })
+ AnalyticsTracker.majorSelected(currentMajor)
}}
>
{`${major.name} (${major.acronym}) - ${major.faculty_id.toUpperCase()}`}
diff --git a/src/utils/AnalyticsTracker.ts b/src/utils/AnalyticsTracker.ts
new file mode 100644
index 00000000..7000a47b
--- /dev/null
+++ b/src/utils/AnalyticsTracker.ts
@@ -0,0 +1,50 @@
+
+import Plausible from "plausible-tracker";
+import { Major } from "../@types";
+
+const plausible = Plausible({
+ domain: import.meta.env.VITE_APP_PLAUSIBLE_DOMAIN,
+ apiHost: import.meta.env.VITE_APP_PLAUSIBLE_HOST,
+ trackLocalhost: !Number(import.meta.env.VITE_APP_PROD),
+})
+
+const { trackEvent } = plausible;
+
+export enum Feature {
+ COPY = 'Copy Schedule',
+ PASTE = 'Paste Schedule',
+ RANDOM_FILL = 'Random Fill',
+
+ OPTION_REORDER = 'Options Order Changed',
+ OPTION_RENAME = 'Option Renamed',
+ OPTION_EMOJI = 'Schedule Emoji Changed',
+
+ SCREENSHOT = 'Screenshot',
+ GRID = 'Grid View Toggle',
+
+ EXPORT_TO_CSV = 'Export to CSV',
+
+ LOCK_TOGGLE = 'Class Lock Toggled',
+}
+
+export class AnalyticsTracker {
+ static majorSelected = (major: Major) => {
+ if (major) {
+ trackEvent('Major Selected', { props: { major: major.name } })
+ trackEvent('Faculty', { props: { faculty: major.faculty_id.toUpperCase() } })
+ }
+ }
+
+ static trackFeature = (feature: Feature) => {
+ trackEvent('Feature', { props: { feature_counter: feature } })
+ }
+
+ static trackFaq = (faq: string) => {
+ if (faq) trackEvent('FAQ', { props: { faq } })
+ }
+
+ static emoji = (emoji: string) => {
+ if (emoji) trackEvent('Emoji', { props: { emoji } })
+ }
+}
+