Skip to content

Commit

Permalink
Calendar v0.1 (#143)
Browse files Browse the repository at this point in the history
* working on calendar viewing pages/add stay dialogs

* working ViewEvents + fixes

* basic timeline view

* styling and timeline controls

* styling and fixes
  • Loading branch information
hingobway authored Aug 25, 2024
1 parent 0b1d894 commit b12c8c9
Show file tree
Hide file tree
Showing 28 changed files with 1,903 additions and 33 deletions.
2 changes: 1 addition & 1 deletion client/.prettierrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"plugins": ["prettier-plugin-tailwindcss"],
"tailwindFunctions": ["clx"],
"tailwindFunctions": ["clx", "clmx"],
"tailwindAttributes": ["classNames"],

"singleQuote": true
Expand Down
2 changes: 2 additions & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@mantine/tiptap": "^7.10.2",
"@passwordlessdev/passwordless-client": "^1.1.2",
"@tabler/icons-react": "^3.9.0",
"@tailwindcss/container-queries": "^0.1.1",
"@tanstack/react-query": "^5.40.1",
"@tiptap-pro/extension-file-handler": "^2.9.2",
"@tiptap/core": "^2.4.0",
Expand All @@ -47,6 +48,7 @@
"@trpc/server": "11.0.0-rc.396",
"dayjs": "^1.11.11",
"fast-deep-equal": "^3.1.3",
"framer-motion": "^11.3.30",
"gql.tada": "^1.7.5",
"graphql": "^16.8.1",
"graphql-request": "^7.0.1",
Expand Down
42 changes: 39 additions & 3 deletions client/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

149 changes: 149 additions & 0 deletions client/src/app/_components/_base/FloatingWindow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
'use client';

import { useEffect, useState } from 'react';

import { Dialog, DialogPanel } from '@headlessui/react';
import { ActionIcon, ScrollArea } from '@mantine/core';
import { useDisclosure, useToggle } from '@mantine/hooks';
import {
IconChevronLeftPipe,
IconChevronRightPipe,
IconMinus,
IconPlus,
IconX,
} from '@tabler/icons-react';
import { motion } from 'framer-motion';

import { Children } from '@/util/propTypes';
import {
ReverseCbProp,
useReverseCb,
type useReverseCbTrigger,
} from '@/util/reverseCb';
import { clx } from '@/util/classConcat';

// COMPONENT
export default function FloatingWindow({
triggerOpen,
children,
title,
width,
}: {
/** use a {@link useReverseCbTrigger} call to open the window. */
triggerOpen: ReverseCbProp;
title?: React.ReactNode;
width?: string;
} & Children) {
const [isOpen, { open, close }] = useDisclosure();
useReverseCb(triggerOpen, open);

// panel state
const [side, setSide] = useToggle(['RIGHT', 'LEFT'] as const);
const [minimized, setMinimized] = useState(false);

function safeClose() {
if (!minimized) return setMinimized(true);
close();
}
useEffect(() => {
if (!isOpen) return;
setMinimized(false);
setTimeout(() => {
document.documentElement.style.overflow = 'unset';
document.documentElement.style.padding = '0';
});
}, [isOpen]);

return (
<>
<Dialog open={isOpen} onClose={safeClose}>
{/* frame */}
<div
className={clx(
'group fixed inset-2 z-[199] flex flex-row items-end sm:inset-6',
side === 'LEFT' && 'justify-start',
side === 'RIGHT' && 'justify-end',
)}
data-m={minimized || null}
>
{/* panel */}
<motion.div
layout
className="flex h-full max-w-screen-sm flex-col justify-end group-data-[m]:!w-96"
style={{
width: width ?? '48rem',
}}
>
<DialogPanel
transition
className={clx(
'flex max-h-full w-full flex-col overflow-hidden rounded-xl border border-slate-300 bg-dwhite shadow-xl',
/* transitions */ 'translate-y-0 scale-100 transition duration-200 data-[closed]:translate-y-12 data-[closed]:opacity-0',
)}
>
{/* HEADER */}
<div
className="group flex flex-row items-center justify-between border-b border-slate-300 bg-slate-50 p-2 group-data-[m]:border-none"
onClick={() => {
if (minimized) setMinimized(false);
}}
>
{/* switch sides */}
<ActionIcon
aria-label="switch to other side"
size="sm"
variant="subtle"
color="slate"
className="invisible group-data-[m]:invisible md:visible"
onClick={() => setSide()}
>
{side === 'RIGHT' && <IconChevronLeftPipe />}
{side === 'LEFT' && <IconChevronRightPipe />}
</ActionIcon>

{/* panel name */}
<div className="select-none text-sm">{title}</div>

<div className="flex flex-row items-center gap-1">
{/* minimize */}
<ActionIcon
aria-label="minimize"
size="sm"
variant="subtle"
color="slate"
onClick={() => setMinimized((b) => !b)}
>
{!minimized && <IconMinus />}
{minimized && <IconPlus />}
</ActionIcon>
{/* close */}
<ActionIcon
aria-label="close window"
size="sm"
variant="subtle"
color="slate"
onClick={close}
>
<IconX />
</ActionIcon>
</div>
</div>

{/* BODY */}
<ScrollArea
classNames={{
root: 'flex-1 transition-all group-data-[m]:max-h-0',
scrollbar: 'm-1',
}}
>
<div className="flex h-full w-full flex-col @container">
{children}
</div>
</ScrollArea>
</DialogPanel>
</motion.div>
</div>
</Dialog>
</>
);
}
11 changes: 11 additions & 0 deletions client/src/app/calendar/_components/CalendarWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
'use client';

import ViewEvents from './ViewEvents';

export default function CalendarWrapper() {
return (
<>
<ViewEvents />
</>
);
}
Loading

0 comments on commit b12c8c9

Please sign in to comment.