Skip to content

Commit

Permalink
Subscribe to calendar (#37)
Browse files Browse the repository at this point in the history
* Fixing calendar generation

* Ability to subscribe to calendar

* Hide devtools on prod

* Update src/components/CalendarSubscribeButton.tsx

Co-authored-by: Preston Mueller <git@prestonmueller.com>

* Fixing linting

---------

Co-authored-by: Preston Mueller <git@prestonmueller.com>
  • Loading branch information
devinmatte and mathcolo authored May 16, 2024
1 parent b12d048 commit 64a9ac0
Show file tree
Hide file tree
Showing 5 changed files with 208 additions and 7 deletions.
79 changes: 77 additions & 2 deletions package-lock.json

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

5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
},
"proxy": "http://localhost:5000",
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.5.2",
"@fortawesome/free-regular-svg-icons": "^6.5.2",
"@fortawesome/free-solid-svg-icons": "^6.5.2",
"@fortawesome/react-fontawesome": "^0.2.0",
"@headlessui/react": "^1.7.19",
"@heroicons/react": "^2.1.3",
"@tanstack/react-query": "^5.34.1",
Expand All @@ -38,6 +42,7 @@
"react-responsive": "^10.0.0",
"react-scroll": "^1.9.0",
"react-toggle-dark-mode": "^1.1.1",
"usehooks-ts": "^3.1.0",
"zustand": "^4.5.2"
},
"devDependencies": {
Expand Down
8 changes: 4 additions & 4 deletions server/app.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from datetime import datetime
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
from icalendar import Calendar, Event
import json
Expand Down Expand Up @@ -59,9 +59,9 @@ def calendar():

# Handle dates (set end date to day after stop date to include the whole day in the event)
start_date = datetime.strptime(shutdown["start_date"], "%Y-%m-%d").replace(tzinfo=EASTERN_TIME)
stop_date = datetime.strptime(shutdown["stop_date"], "%Y-%m-%d").replace(
tzinfo=EASTERN_TIME
) + datetime.timedelta(days=1)
stop_date = datetime.strptime(shutdown["stop_date"], "%Y-%m-%d").replace(tzinfo=EASTERN_TIME) + timedelta(
days=1
)
event.add("dtstart", start_date.date())
event.add("dtend", stop_date.date())

Expand Down
117 changes: 117 additions & 0 deletions src/components/CalendarSubscribeButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { faCalendarPlus } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Dialog, Transition } from '@headlessui/react';
import { CheckIcon, DocumentDuplicateIcon } from '@heroicons/react/16/solid';
import { useState } from 'react';
import { Fragment } from 'react/jsx-runtime';
import { useCopyToClipboard } from 'usehooks-ts';

interface SubscribeModalProps {
isOpen: boolean;
setIsOpen: (isOpen: boolean) => void;
}

const SubscribeModal: React.FC<SubscribeModalProps> = ({ isOpen, setIsOpen }) => {
const [, copy] = useCopyToClipboard();
const [copied, setCopied] = useState(false);

return (
<Transition.Root show={isOpen} as={Fragment}>
<Dialog className="relative z-10" onClose={setIsOpen}>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" />
</Transition.Child>

<div className="fixed inset-0 z-10 w-screen overflow-y-auto">
<div className="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
enterTo="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<Dialog.Panel className="relative transform overflow-hidden rounded-lg bg-white dark:bg-gray-500 px-4 pb-4 pt-5 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg sm:p-6">
<div>
<div className="mx-auto flex h-16 w-16 items-center justify-center rounded-full bg-yellow-400 text-white">
<FontAwesomeIcon icon={faCalendarPlus} size="xl" />
</div>
<div className="mt-3 text-center sm:mt-5">
<Dialog.Title
as="h3"
className="text-base font-semibold leading-6 text-slate-900 dark:text-slate-100"
>
Add to Calendar
</Dialog.Title>
<p className="text-slate-700 my-2 dark:text-slate-50">
Copy the link below to subscribe by URL in your calendar app. It will update
automatically as the shutdown schedule changes.
</p>
<button
onMouseLeave={() => setCopied(false)}
onClick={() => {
copy('https://shutdowns.labs.transitmatters.org/calendar');
setCopied(true);
}}
className="flex items-center justify-between gap-x-3 w-full px-4 py-2.5 lowercase bg-slate-400 hover:bg-slate-500 text-slate-50 rounded"
>
<div className="pr-3 font-normal text-sm">
https://shutdowns.labs.transitmatters.org/calendar
</div>
{copied ? (
<CheckIcon className="h-4 w-4 text-slate-50" />
) : (
<DocumentDuplicateIcon className="h-4 w-4 text-slate-50" />
)}
</button>
</div>
</div>
<div className="mt-5 sm:mt-6">
<button
type="button"
className="inline-flex w-full justify-center rounded-md bg-yellow-400 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-yellow-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-yellow-600"
onClick={() => setIsOpen(false)}
>
Back to tracker
</button>
</div>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition.Root>
);
};

export const CalendarSubscribeButton: React.FC = () => {
const [isOpen, setIsOpen] = useState(false);

const openModal = () => {
setIsOpen(true);
};

return (
<button
title={'Add to Calendar'}
onClick={openModal}
className={`p-2 group rounded-full sm:rounded-lg flex items-center justify-center text-white focus:outline-none h-1/2 bg-yellow-500`}
>
<span className="flex items-center">
<FontAwesomeIcon icon={faCalendarPlus} />
<span className="hidden group-hover:block p-0 text-xs ml-1">Add to Calendar</span>
</span>
<SubscribeModal isOpen={isOpen} setIsOpen={setIsOpen} />
</button>
);
};
6 changes: 5 additions & 1 deletion src/components/LineGraph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { shutdowns } from '../constants/shutdowns';
import { watermarkLayout } from '../utils/watermark';
import { useBreakpoint } from '../hooks/useBreakpoint';
import { cardStyles } from '../constants/styles';
import { CalendarSubscribeButton } from './CalendarSubscribeButton';

dayjs.extend(utc);

Expand Down Expand Up @@ -98,7 +99,10 @@ export const LineGraph: React.FunctionComponent<LineGraphProps> = ({

return (
<div className={`w-full overflow-y-hidden ${cardStyles}`}>
<div className="text-2xl font-medium">Timeline</div>
<div className="flex justify-between">
<div className="text-2xl font-medium">Timeline</div>
<CalendarSubscribeButton />
</div>
<div
ref={divRef as MutableRefObject<HTMLDivElement>}
className="ml-2 sm:ml-0 flex flex-row gap-4"
Expand Down

0 comments on commit 64a9ac0

Please sign in to comment.