Skip to content

Commit

Permalink
This is painful.
Browse files Browse the repository at this point in the history
  • Loading branch information
davepeck committed Jan 30, 2024
1 parent aaf87bb commit 8c42204
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 80 deletions.
14 changes: 9 additions & 5 deletions src/components/Icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const CornerDownLeft: React.FC<{ className?: string }> = ({
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<g clip-path="url(#clip0_2319_784)">
<g clipPath="url(#clip0_2319_784)">
<path
d="M7 8L2 13L7 18"
stroke="currentColor"
Expand All @@ -31,31 +31,35 @@ export const CornerDownLeft: React.FC<{ className?: string }> = ({
</svg>
);

export const Share: React.FC<{ className?: string }> = ({ className }) => (
export const Share: React.FC<{ className?: string; onClick: () => void }> = ({
className,
onClick,
}) => (
<svg
viewBox="0 0 32 32"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={className}
onClick={onClick}
>
<path
d="M5.33594 16V26.6667C5.33594 27.3739 5.61689 28.0522 6.11699 28.5523C6.61708 29.0524 7.29536 29.3333 8.0026 29.3333H24.0026C24.7098 29.3333 25.3881 29.0524 25.8882 28.5523C26.3883 28.0522 26.6693 27.3739 26.6693 26.6667V16"
strokeWidth="3"
stroke-color="currentColor"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M21.3268 7.99837L15.9935 2.66504L10.6602 7.99837"
strokeWidth="3"
stroke-color="currentColor"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M16 2.66504V19.9984"
strokeWidth="3"
stroke-color="currentColor"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
/>
Expand Down
159 changes: 84 additions & 75 deletions src/components/More.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { useState } from "react";
import type { ReactNode } from "react";
import clsx from "clsx";

import { bestRegistrationUrl } from "../vote_gov";
import { ArrowDown, CornerDownLeft } from "./Icons";
import { ArrowDown, CornerDownLeft, Share } from "./Icons";
import { STATE_NAMES } from "../states";
import type { State } from "../states";
import { browserSupportsShare, defaultShare } from "./ShareButton";

/** Countmore power rankings */
const POWER_RANKINGS: { [st: string]: number } = {
Expand All @@ -30,76 +31,6 @@ const powerRanking = (st: string): number => POWER_RANKINGS[st] || 0;
/** Which state is most impactful to vote in for the 2024 presidential election? */
type StateSelection = "home" | "school" | "toss-up";

/** Selection description */
const SELECTION_DESCRIPTION: {
[sel in StateSelection]: (homeSt: State, schoolSt: State) => ReactNode;
} = {
home: (homeSt: State, __: State) => (
<div>
<div className="font-cabinet text-[36px] leading-[43.2px] font-bold">
Your vote counts more in{" "}
<span className="text-point">{STATE_NAMES[homeSt]}</span>.
</div>
<p className="py-8">Put some explanatory text here.</p>
{bestRegistrationUrl(homeSt) && (
<a
className="inline-block g-black py-4 px-8 text-white text-xl font-bold hover:bg-red-500"
href={bestRegistrationUrl(homeSt)!}
target="_blank"
>
Register to vote
</a>
)}
</div>
),
school: (_: State, schoolSt: State) => (
<div>
<div className="font-cabinet text-[36px] leading-[43.2px] font-bold">
Your vote counts more in{" "}
<span className="text-point">{STATE_NAMES[schoolSt]}</span>.
</div>
<p className="py-8">Put some explanatory text here.</p>
{bestRegistrationUrl(schoolSt) && (
<a
className="inline-block bg-black py-4 px-8 text-white text-xl font-bold hover:bg-red-500"
href={bestRegistrationUrl(schoolSt)!}
target="_blank"
>
Register to vote
</a>
)}
</div>
),
"toss-up": (homeSt: State, schoolSt: State) => (
<div>
<div className="font-cabinet text-[36px] leading-[43.2px] font-bold">
Your vote counts the same in{" "}
<span className="text-point">{STATE_NAMES[homeSt]}</span> and{" "}
<span className="text-point">{STATE_NAMES[schoolSt]}</span>.
</div>
<p className="py-8">Put some explanatory text here.</p>
{bestRegistrationUrl(homeSt) && (
<a
className="inline-block bg-black mb-8 py-4 px-8 text-white text-xl font-bold hover:bg-red-500"
href={bestRegistrationUrl(homeSt)!}
target="_blank"
>
Register to vote in {STATE_NAMES[homeSt]}
</a>
)}{" "}
{bestRegistrationUrl(schoolSt) && (
<a
className="inline-block bg-black py-4 px-8 text-white text-xl font-bold hover:bg-red-500"
href={bestRegistrationUrl(schoolSt)!}
target="_blank"
>
Register to vote in {STATE_NAMES[schoolSt]}
</a>
)}
</div>
),
};

/** Return the state selection for a state */
const stateSelection = (homeSt: string, schoolSt: string): StateSelection => {
const homeRank = powerRanking(homeSt);
Expand Down Expand Up @@ -157,9 +88,10 @@ const SelectStates: React.FC<{
className="text-black invalid:text-gray-400 w-full rounded-none flex-grow font-cabinet font-extrabold text-[24px] leading-[32px] appearance-none bg-transparent border-b-2 border-black"
value={homeSt}
required
defaultValue=""
onChange={(e) => setHomeSt(e.target.value as State)}
>
<option value="" disabled selected>
<option value="" disabled>
choose...
</option>
{Object.entries(STATE_NAMES).map(([st, name]) => (
Expand All @@ -186,9 +118,10 @@ const SelectStates: React.FC<{
className="text-black invalid:text-gray-400 w-full rounded-none flex-grow font-cabinet font-extrabold text-[24px] leading-[32px] appearance-none bg-transparent border-b-2 border-black focus:ring-hover"
value={schoolSt}
required
defaultValue=""
onChange={(e) => setSchoolSt(e.target.value as State)}
>
<option value="" disabled selected>
<option value="" disabled>
choose...
</option>
{Object.entries(STATE_NAMES).map(([st, name]) => (
Expand Down Expand Up @@ -230,7 +163,83 @@ const DescribeSelection: React.FC<{ result: StateSelectionResult }> = ({
result,
}) => {
const { selection, homeSt, schoolSt } = result;
return <div>{SELECTION_DESCRIPTION[selection](homeSt, schoolSt)}</div>;

return (
<div>
<div className="font-cabinet text-[36px] leading-[43.2px] font-bold">
{selection !== "toss-up" && (
<>
Your vote counts more in{" "}
<span className="text-point">
{STATE_NAMES[selection === "home" ? homeSt : schoolSt]}
</span>
.
</>
)}
{selection === "toss-up" && (
<>
Your vote counts the same in{" "}
<span className="text-point">{STATE_NAMES[homeSt]}</span> and{" "}
<span className="text-point">{STATE_NAMES[schoolSt]}</span>.
</>
)}
</div>
<p className="py-8">Put some explanatory text here.</p>
<div className="flex flex-row justify-between items-center">
<div className="flex-none">
{browserSupportsShare() ? (
<Share
className="text-black hover:text-hover cursor-pointer w-8 h-8 transition-colors duration-200"
onClick={defaultShare}
/>
) : (
" "
)}
</div>
<div className="flex-1 flex flex-row flex-wrap justify-end -mb-2">
{selection !== "school" && bestRegistrationUrl(homeSt) && (
<a
className="inline-block bg-point rounded-md py-4 px-8 text-white text-xl font-bold hover:bg-hover transition-colors duration-200 mb-2"
href={bestRegistrationUrl(homeSt)!}
target="_blank"
>
Register to vote
{selection === "toss-up" && (
<>
{" "}
in{" "}
<span className="font-cabinet inline-block w-8 min-w-8 max-w-8">
{homeSt.toUpperCase()}
</span>
</>
)}
</a>
)}
{selection !== "home" && bestRegistrationUrl(schoolSt) && (
<a
className={clsx(
"inline-block bg-point rounded-md py-4 px-8 text-white text-xl font-bold hover:bg-hover transition-colors duration-200 mb-2",
selection === "toss-up" && "ml-4"
)}
href={bestRegistrationUrl(schoolSt)!}
target="_blank"
>
Register to vote
{selection === "toss-up" && (
<>
{" "}
in{" "}
<span className="font-cabinet inline-block w-8 min-w-8 max-w-8">
{schoolSt.toUpperCase()}
</span>
</>
)}
</a>
)}
</div>
</div>
</div>
);
};

export const More: React.FC = () => {
Expand Down
23 changes: 23 additions & 0 deletions src/components/ShareButton.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
import React, { useEffect, useState } from "react";

/** Return `true` if this browser has native sharing panel support. */
export const browserSupportsShare = () =>
Boolean(window.navigator && window.navigator.share);

/** Invoke a generic native share, if safe. */
export const nativeShare = (title: string, text: string, url: string) => {
if (browserSupportsShare()) {
navigator.share({
title,
text,
url,
});
}
};

/** Share the default countmore information if possible. */
export const defaultShare = () =>
nativeShare(
"Count More",
"Every vote counts... but some count more. Find out where *your* vote counts more in 2024.",
"https://countmore.us"
);

const ShareButton: React.FC = () => {
const [showShare, setShowShare] = useState<boolean>(false);

Expand Down
22 changes: 22 additions & 0 deletions src/vote_gov.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,28 @@ export const VOTE_GOV_DATA: StateVotingInfo[] = [
url: "https://portaldir.ct.gov/sots/LookUp.aspx?ref=countmoreus_en",
},
},
{
state: "DC",
name: "District of Columbia",
scrapeUrl: "https://vote.gov/register/dc/",
hasRegistration: true,
online: {
url: "https://vr.dcboe.org/213324797239968?agency_code=12&?ref=countmoreus_en",
deadline: 21,
},
mail: {
url: "https://www.dcboe.org/voters/register-to-vote/register-update-voter-registration?ref=countmoreus_en",
deadline: 21,
timeframe: "received",
},
inPerson: {
url: "https://www.dcboe.org/voters/register-to-vote/register-update-voter-registration?ref=countmoreus_en",
deadline: 0,
},
confirm: {
url: "https://vr.dcboe.org/213324797239968?agency_code=12&?ref=countmoreus_en",
},
},
{
state: "DE",
name: "Delaware",
Expand Down

0 comments on commit 8c42204

Please sign in to comment.