mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 19:49:50 +02:00
feat: popover
This commit is contained in:
1 parent
0523619aee
commit
e2cef42667
3 files changed
+117
-34
No files matched your search
@@ -1,10 +1,19 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { ExclamationTriangleIcon } from '@radix-ui/react-icons';
|
import { ExclamationTriangleIcon } from '@radix-ui/react-icons';
|
||||||
import { Box, Callout, Flex, Heading, Tabs, Text } from '@radix-ui/themes';
|
import {
|
||||||
|
Box,
|
||||||
|
Callout,
|
||||||
|
Flex,
|
||||||
|
Heading,
|
||||||
|
Popover,
|
||||||
|
Tabs,
|
||||||
|
Text,
|
||||||
|
} from '@radix-ui/themes';
|
||||||
import { use, useMemo, useState } from 'react';
|
import { use, useMemo, useState } from 'react';
|
||||||
import { BkniIndicator } from '../../../../components/BkniIndicator';
|
import { BkniIndicator } from '../../../../components/BkniIndicator';
|
||||||
import { DatePicker } from '../../../../components/DatePicker';
|
import { DatePicker } from '../../../../components/DatePicker';
|
||||||
|
import { DummyLink } from '../../../../components/DummyLink';
|
||||||
import PageWrapper from '../../../../components/PageWrapper';
|
import PageWrapper from '../../../../components/PageWrapper';
|
||||||
import { getAccountInfo } from '../../../../core/blitz/getAccountInfo';
|
import { getAccountInfo } from '../../../../core/blitz/getAccountInfo';
|
||||||
import { getClanAccountInfo } from '../../../../core/blitz/getClanAccountInfo';
|
import { getClanAccountInfo } from '../../../../core/blitz/getClanAccountInfo';
|
||||||
@@ -23,8 +32,7 @@ export default function Page({ params }: { params: { id: string } }) {
|
|||||||
[id],
|
[id],
|
||||||
);
|
);
|
||||||
const clanAccountInfo = use(clanAccountInfoPromise);
|
const clanAccountInfo = use(clanAccountInfoPromise);
|
||||||
const bkni = Math.random() * 2 - 1;
|
const bkni = ((Math.round(Date.now() / 1000 / 60) / 100) % 2) - 1;
|
||||||
// const bkni = 0.87;
|
|
||||||
const [period, setPeriod] = useState<'custom' | number>(30);
|
const [period, setPeriod] = useState<'custom' | number>(30);
|
||||||
const { bkniColor } = parseBkni(bkni);
|
const { bkniColor } = parseBkni(bkni);
|
||||||
const isTracking = false;
|
const isTracking = false;
|
||||||
@@ -100,10 +108,22 @@ export default function Page({ params }: { params: { id: string } }) {
|
|||||||
<FlippedTrigger value="custom">Custom</FlippedTrigger>
|
<FlippedTrigger value="custom">Custom</FlippedTrigger>
|
||||||
</Tabs.List>
|
</Tabs.List>
|
||||||
</Tabs.Root>
|
</Tabs.Root>
|
||||||
</PageWrapper>
|
|
||||||
|
|
||||||
<PageWrapper color={bkniColor} noFlex1>
|
{period === 'custom' && (
|
||||||
<DatePicker />
|
<Text>
|
||||||
|
From{' '}
|
||||||
|
<Popover.Root>
|
||||||
|
<Popover.Trigger>
|
||||||
|
<DummyLink underline="always">June 1, 2021</DummyLink>
|
||||||
|
</Popover.Trigger>
|
||||||
|
|
||||||
|
<Popover.Content>
|
||||||
|
<DatePicker />
|
||||||
|
</Popover.Content>
|
||||||
|
</Popover.Root>{' '}
|
||||||
|
to <DummyLink underline="always">June 7, 2024</DummyLink>
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
</PageWrapper>
|
</PageWrapper>
|
||||||
|
|
||||||
{!isTracking && (
|
{!isTracking && (
|
||||||
|
|||||||
@@ -17,25 +17,48 @@ import {
|
|||||||
} from '@radix-ui/themes';
|
} from '@radix-ui/themes';
|
||||||
import { times } from 'lodash';
|
import { times } from 'lodash';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { Vector3Tuple } from 'three';
|
||||||
|
|
||||||
const DAY_TITLES = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
const DAY_TITLES = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
||||||
const YEAR_OPTIONS = 7;
|
const YEAR_OPTIONS = 7;
|
||||||
|
|
||||||
export function DatePicker() {
|
interface DatePickerProps {
|
||||||
|
onDateChange?: (date: Vector3Tuple) => void;
|
||||||
|
defaultDate?: Vector3Tuple;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function DatePicker({ onDateChange, defaultDate }: DatePickerProps) {
|
||||||
const initialDate = new Date();
|
const initialDate = new Date();
|
||||||
|
|
||||||
const [year, setYear] = useState(initialDate.getFullYear());
|
const [year, setYear] = useState(
|
||||||
const [month, setMonth] = useState(initialDate.getMonth());
|
defaultDate?.[2] ?? initialDate.getFullYear(),
|
||||||
const [day, setDay] = useState(initialDate.getDate());
|
);
|
||||||
|
const [month, setMonth] = useState(
|
||||||
|
defaultDate?.[1] ?? initialDate.getMonth(),
|
||||||
|
);
|
||||||
|
const [day, setDay] = useState(defaultDate?.[0] ?? initialDate.getDate());
|
||||||
|
const [yearScroll, setYearScroll] = useState(0);
|
||||||
const [yearOffset, setYearOffset] = useState(0);
|
const [yearOffset, setYearOffset] = useState(0);
|
||||||
const [monthOffset, setMonthOffset] = useState(0);
|
const [monthOffset, setMonthOffset] = useState(0);
|
||||||
const date = new Date(year + yearOffset, month + monthOffset, day);
|
const date = new Date(year + yearOffset, month + monthOffset, day);
|
||||||
|
|
||||||
const daysInLastMonth = new Date(year, month + monthOffset, 0).getDate();
|
const daysInLastMonth = new Date(
|
||||||
const daysInMonth = new Date(year, month + monthOffset + 1, 0).getDate();
|
year + yearOffset,
|
||||||
const firstDayOfMonth = new Date(year, month + monthOffset, 1).getDay();
|
month + monthOffset,
|
||||||
|
0,
|
||||||
|
).getDate();
|
||||||
|
const daysInMonth = new Date(
|
||||||
|
year + yearOffset,
|
||||||
|
month + monthOffset + 1,
|
||||||
|
0,
|
||||||
|
).getDate();
|
||||||
|
const firstDayOfMonth = new Date(
|
||||||
|
year + yearOffset,
|
||||||
|
month + monthOffset,
|
||||||
|
1,
|
||||||
|
).getDay();
|
||||||
const lastDayOfMonth = new Date(
|
const lastDayOfMonth = new Date(
|
||||||
year,
|
year + yearOffset,
|
||||||
month + monthOffset,
|
month + monthOffset,
|
||||||
daysInMonth,
|
daysInMonth,
|
||||||
).getDay();
|
).getDay();
|
||||||
@@ -50,7 +73,14 @@ export function DatePicker() {
|
|||||||
<IconButton
|
<IconButton
|
||||||
size="3"
|
size="3"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={() => setMonthOffset((state) => state - 1)}
|
onClick={() => {
|
||||||
|
if (monthOffset === 0) {
|
||||||
|
setYearOffset((state) => state - 1);
|
||||||
|
setMonthOffset(11);
|
||||||
|
} else {
|
||||||
|
setMonthOffset((state) => state - 1);
|
||||||
|
}
|
||||||
|
}}
|
||||||
ml="2"
|
ml="2"
|
||||||
>
|
>
|
||||||
<ChevronLeftIcon />
|
<ChevronLeftIcon />
|
||||||
@@ -72,9 +102,13 @@ export function DatePicker() {
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
|
|
||||||
<Flex gap="1">
|
<Flex gap="1">
|
||||||
<Text>{date.toLocaleString(undefined, { month: 'long' })} </Text>
|
<Text>
|
||||||
|
{date.toLocaleString(undefined, {
|
||||||
|
month: 'long',
|
||||||
|
})}
|
||||||
|
</Text>
|
||||||
|
|
||||||
<Popover.Root onOpenChange={() => setYearOffset(0)}>
|
<Popover.Root onOpenChange={() => setYearScroll(0)}>
|
||||||
<Popover.Trigger>
|
<Popover.Trigger>
|
||||||
<Link underline="always" href="#">
|
<Link underline="always" href="#">
|
||||||
{date.getFullYear()}
|
{date.getFullYear()}
|
||||||
@@ -85,7 +119,7 @@ export function DatePicker() {
|
|||||||
<Flex direction="column" gap="1">
|
<Flex direction="column" gap="1">
|
||||||
<IconButton
|
<IconButton
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={() => setYearOffset((state) => state + 1)}
|
onClick={() => setYearScroll((state) => state + 1)}
|
||||||
mb="2"
|
mb="2"
|
||||||
>
|
>
|
||||||
<ChevronUpIcon />
|
<ChevronUpIcon />
|
||||||
@@ -93,22 +127,31 @@ export function DatePicker() {
|
|||||||
|
|
||||||
{times(YEAR_OPTIONS, (index) => {
|
{times(YEAR_OPTIONS, (index) => {
|
||||||
const thisYear =
|
const thisYear =
|
||||||
year - index + Math.floor(YEAR_OPTIONS / 2) + yearOffset;
|
year +
|
||||||
|
yearOffset -
|
||||||
|
index +
|
||||||
|
Math.floor(YEAR_OPTIONS / 2) +
|
||||||
|
yearScroll;
|
||||||
|
const selected = year + yearOffset === thisYear;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Popover.Close key={thisYear}>
|
||||||
variant={year === thisYear ? 'solid' : 'soft'}
|
<Button
|
||||||
radius="large"
|
variant={selected ? 'solid' : 'soft'}
|
||||||
onClick={() => setYear(thisYear)}
|
radius="large"
|
||||||
>
|
onClick={() => {
|
||||||
{thisYear}
|
setYearOffset(thisYear - year);
|
||||||
</Button>
|
}}
|
||||||
|
>
|
||||||
|
{thisYear}
|
||||||
|
</Button>
|
||||||
|
</Popover.Close>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|
||||||
<IconButton
|
<IconButton
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={() => setYearOffset((state) => state - 1)}
|
onClick={() => setYearScroll((state) => state - 1)}
|
||||||
mt="2"
|
mt="2"
|
||||||
>
|
>
|
||||||
<ChevronDownIcon />
|
<ChevronDownIcon />
|
||||||
@@ -122,7 +165,14 @@ export function DatePicker() {
|
|||||||
<IconButton
|
<IconButton
|
||||||
size="3"
|
size="3"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={() => setMonthOffset((state) => state + 1)}
|
onClick={() => {
|
||||||
|
if (monthOffset === 11) {
|
||||||
|
setYearOffset((state) => state + 1);
|
||||||
|
setMonthOffset(0);
|
||||||
|
} else {
|
||||||
|
setMonthOffset((state) => state + 1);
|
||||||
|
}
|
||||||
|
}}
|
||||||
mr="2"
|
mr="2"
|
||||||
>
|
>
|
||||||
<ChevronRightIcon />
|
<ChevronRightIcon />
|
||||||
@@ -153,7 +203,8 @@ export function DatePicker() {
|
|||||||
))}
|
))}
|
||||||
|
|
||||||
{times(daysInMonth, (index) => {
|
{times(daysInMonth, (index) => {
|
||||||
const selected = index === day - 1 && monthOffset === 0;
|
const selected =
|
||||||
|
index === day - 1 && monthOffset === 0 && yearOffset === 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<IconButton
|
<IconButton
|
||||||
@@ -161,11 +212,18 @@ export function DatePicker() {
|
|||||||
key={index}
|
key={index}
|
||||||
variant={selected ? 'solid' : 'soft'}
|
variant={selected ? 'solid' : 'soft'}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setYear(year + yearOffset);
|
const newYear =
|
||||||
setMonth((month + monthOffset) % 12);
|
year + yearOffset + Math.floor((month + monthOffset) / 12);
|
||||||
setDay(index + 1);
|
const newMonth = (month + monthOffset) % 12;
|
||||||
|
const newDay = index + 1;
|
||||||
|
|
||||||
|
setYear(newYear);
|
||||||
|
setMonth(newMonth);
|
||||||
|
setDay(newDay);
|
||||||
setYearOffset(0);
|
setYearOffset(0);
|
||||||
setMonthOffset(0);
|
setMonthOffset(0);
|
||||||
|
|
||||||
|
onDateChange?.([newDay, newMonth, newYear]);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{index + 1}
|
{index + 1}
|
||||||
@@ -179,8 +237,6 @@ export function DatePicker() {
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
))}
|
))}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
{/* {`${day} ${month} ${year}`} */}
|
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { Link, LinkProps } from '@radix-ui/themes';
|
||||||
|
|
||||||
|
export function DummyLink({ href = '#', onClick, ...props }: LinkProps) {
|
||||||
|
return (
|
||||||
|
<Link href={href} onClick={(event) => event.preventDefault()} {...props} />
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in new issue
Block a user