diff --git a/package-lock.json b/package-lock.json index f6ac171..fe35b86 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "@radix-ui/react-separator": "^1.0.3", "@radix-ui/react-slider": "^1.1.2", "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-toggle": "^1.1.0", "@radix-ui/react-tooltip": "^1.0.7", "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", @@ -3068,6 +3069,119 @@ } } }, + "node_modules/@radix-ui/react-toggle": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle/-/react-toggle-1.1.0.tgz", + "integrity": "sha512-gwoxaKZ0oJ4vIgzsfESBuSgJNdc0rv12VhHgcqN0TEJmmZixXG/2XpsLK8kzNWYcnaoRIEEQc0bEi3dIvdUpjw==", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-controllable-state": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-toggle/node_modules/@radix-ui/primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", + "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==" + }, + "node_modules/@radix-ui/react-toggle/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", + "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-toggle/node_modules/@radix-ui/react-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", + "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", + "dependencies": { + "@radix-ui/react-slot": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-toggle/node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-toggle/node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", + "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-toggle/node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", + "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-tooltip": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.0.7.tgz", diff --git a/package.json b/package.json index fb8bb13..b0ac89e 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "@radix-ui/react-separator": "^1.0.3", "@radix-ui/react-slider": "^1.1.2", "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-toggle": "^1.1.0", "@radix-ui/react-tooltip": "^1.0.7", "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", diff --git a/src/popup/components/graph.tsx b/src/popup/components/graph.tsx index c84267b..c4be065 100644 --- a/src/popup/components/graph.tsx +++ b/src/popup/components/graph.tsx @@ -9,7 +9,7 @@ import { import { BalloonName, HistoryNode } from '@/const'; import remote from '@/remote'; -export default (props: { startDate: Date; endDate: Date }) => { +export default (props: { startDate: Date; endDate: Date; global: boolean }) => { const [data, setData] = useState({} as (HistoryNode & { total: number })[]); const [poppedBalloonTypes, setPoppedBalloonTypes] = useState( [] @@ -20,7 +20,8 @@ export default (props: { startDate: Date; endDate: Date }) => { const fetchData = async () => { const response = await remote.getPopHistory( props.startDate, - props.endDate + props.endDate, + props.global ); const allBalloonNames = [ @@ -62,7 +63,7 @@ export default (props: { startDate: Date; endDate: Date }) => { }; fetchData(); - }, [props.startDate, props.endDate]); + }, [props.startDate, props.endDate, props.global]); return ( <> diff --git a/src/popup/components/ui/toggle.tsx b/src/popup/components/ui/toggle.tsx new file mode 100644 index 0000000..dae1a8b --- /dev/null +++ b/src/popup/components/ui/toggle.tsx @@ -0,0 +1,42 @@ +import * as TogglePrimitive from '@radix-ui/react-toggle'; +import { cva, type VariantProps } from 'class-variance-authority'; +import * as React from 'react'; +import { cn } from '@/utils'; + +const toggleVariants = cva( + 'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground', + { + variants: { + variant: { + default: 'bg-transparent', + outline: + 'border border-input bg-transparent hover:bg-accent hover:text-accent-foreground', + }, + size: { + default: 'h-10 px-3', + sm: 'h-9 px-2.5', + lg: 'h-11 px-5', + }, + }, + defaultVariants: { + variant: 'default', + size: 'default', + }, + } +); + +const Toggle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, variant, size, ...props }, ref) => ( + +)); + +Toggle.displayName = TogglePrimitive.Root.displayName; + +export { Toggle, toggleVariants }; diff --git a/src/popup/pages/Statistics.tsx b/src/popup/pages/Statistics.tsx index 6752270..410034f 100644 --- a/src/popup/pages/Statistics.tsx +++ b/src/popup/pages/Statistics.tsx @@ -1,11 +1,16 @@ import { format, subDays } from 'date-fns'; -import { Calendar as CalendarIcon } from 'lucide-react'; +import { Calendar as CalendarIcon, Globe, CircleUser } from 'lucide-react'; import React from 'react'; import { DateRange } from 'react-day-picker'; import Main from '@/components/Main'; import Graph from '@/components/graph'; import { Button } from '@/components/ui/button'; import { Calendar } from '@/components/ui/calendar'; +import { + HoverCard, + HoverCardContent, + HoverCardTrigger, +} from '@/components/ui/hover-card'; import { Popover, PopoverContent, @@ -19,6 +24,7 @@ import { SelectValue, } from '@/components/ui/select'; import { Skeleton } from '@/components/ui/skeleton'; +import { Toggle } from '@/components/ui/toggle'; import storage from '@/managers/storage'; import { cn } from '@/utils'; @@ -27,6 +33,7 @@ export default () => { from: subDays(new Date(), 7), to: new Date(), }); + const [global, setGlobal] = React.useState(true); const handleDatePresetChange = async (value: string) => { const minDate = new Date('2024-07-01'); @@ -67,61 +74,86 @@ export default () => { return (
- - - + + - - {date?.from ? ( - date.to ? ( - <> - {format(date.from, 'LLL dd, y')} -{' '} - {format(date.to, 'LLL dd, y')} - + + + + + + + setGlobal(!global)} + > + {global ? ( + ) : ( - format(date.from, 'LLL dd, y') - ) - ) : ( - Pick a date - )} - - - - - - - + + )} + + + +

+ Toggle global history +

+

+ View global history or your own history. +

+
+
+ {date?.from && date?.to ? ( - + ) : ( )}