diff --git a/app/constituencies/[slug]/page.tsx b/app/constituencies/[slug]/page.tsx index a608f64..da1cd7f 100644 --- a/app/constituencies/[slug]/page.tsx +++ b/app/constituencies/[slug]/page.tsx @@ -1,24 +1,28 @@ import { Col, Container, Row, ButtonGroup, Button } from "react-bootstrap"; import Link from "next/link"; import Header from "@/components/Header"; -import ActionBox from "@/components/info_box/ActionBox"; import ImpliedChart from "@/components/info_box/ImpliedChart"; import MRPChart from "@/components/info_box/MRPChart"; import PlanToVoteBox from "@/components/info_box/PlanToVoteBox"; import TacticalReasoningBox from "@/components/info_box/TacticalReasoningBox"; -import { partyCssClassFromSlug, partyNameFromSlug } from "@/utils/Party"; +import { + progressiveSlugs, + partyCssClassFromSlug, + partyNameFromSlug, + shortPartyNameFromSlug, +} from "@/utils/Party"; import { getConstituenciesData, getConstituencySlugs, } from "@/utils/constituencyData"; import { notFound } from "next/navigation"; import { + FaUser, FaShare, FaPuzzlePiece, FaCopy, FaHandHoldingHeart, } from "react-icons/fa6"; -import PostcodeLookup from "@/components/constituency_lookup/ConstituencyLookup"; export const dynamicParams = false; // Don't allow params not in generateStaticParams @@ -62,30 +66,6 @@ export default async function ConstituencyPage({ (a, b) => b.votePercent - a.votePercent, ); - let tacticalVoteHeader = ""; - let tacticalVoteAdvice = ""; - let tacticalVoteClass = ""; - - if (constituencyData.otherVoteData.conservativeWinUnlikely) { - tacticalVoteHeader = "Tories unlikely to win here"; - tacticalVoteAdvice = "Vote with your heart"; - tacticalVoteClass = "party-your-heart"; - } else { - tacticalVoteHeader = "The Tactical Vote is"; - - if (constituencyData.recommendation.partySlug) { - tacticalVoteAdvice = partyNameFromSlug( - constituencyData.recommendation.partySlug, - ); - tacticalVoteClass = partyCssClassFromSlug( - constituencyData.recommendation.partySlug, - ); - } else { - tacticalVoteClass = "party-too-soon"; - tacticalVoteAdvice = "Too Soon to call"; - } - } - if (constituencyData.recommendation.partySlug === "None") { return ( <> @@ -136,27 +116,49 @@ export default async function ConstituencyPage({
- -

{tacticalVoteHeader}

-

- {tacticalVoteAdvice} -

+ + {!constituencyData.otherVoteData.conservativeWinUnlikely && ( +

Your situation

+ )} +

+ Tories{" "} + {constituencyData.otherVoteData.conservativeWinUnlikely ? ( + <> + + unlikely + {" "} + to win here + + ) : ( + <> + can{" "} + win here + + )} +

+

+ {" "} + Current MP is{" "} + + {partyNameFromSlug( + constituencyData.impliedPreviousResult.winningParty, + )} + +

+

- Why? + Info

-
-
-
-
- - - -

be counted, stick together!

+ + -
- - + +

Grow this movement

You're in! Now let's build our numbers

@@ -182,6 +184,18 @@ export default async function ConstituencyPage({
+
+
+
+
+ + + +

be counted, stick together!

+ +
+ +

Reasons to be counted @@ -264,3 +278,78 @@ export default async function ConstituencyPage({ ); } + +function TacticalAdvice({ + constituencyData, +}: { + constituencyData: ConstituencyData; +}) { + const getTopProgressives = ( + results: PartyVoteResult[], + ): [PartySlug, PartySlug] => { + const progResults = results + .filter((result) => progressiveSlugs.includes(result.partySlug)) + .sort((a, b) => b.votePercent - a.votePercent); + + return [progResults[0].partySlug, progResults[1].partySlug]; + }; + + const toryWinUnlikely = + constituencyData.otherVoteData.conservativeWinUnlikely; + //TODO add in a column for safe opposition seat definition + const clearAdvice = !!constituencyData.recommendation.partySlug; + const recommendation = constituencyData.recommendation.partySlug; + const [topProgressive, secondProgressive] = getTopProgressives( + constituencyData.pollingResults.partyVoteResults, + ); + + if (toryWinUnlikely) { + if (clearAdvice) { + return ( + <> +

Vote with your heart

+

Join up and together we can pressure them

+ + ); + } else { + return ( + <> +

+ Vote{" "} + + {shortPartyNameFromSlug(topProgressive)} + {" "} + or{" "} + + {shortPartyNameFromSlug(secondProgressive)} + {" "} +

+ +

BUT THAT'S NOT ENOUGH, JOIN UP

+ + ); + } + } else { + //Tories CAN win + if (clearAdvice) { + return ( + <> +

Your tactical vote

+

+ {partyNameFromSlug(recommendation)} +

+

But that's not enough, join up

+ + ); + } else { + return ( + <> + {" "} +

Your tactical vote

+

Too soon to call

+

Join up to be notified

+ + ); + } + } +} diff --git a/app/globals.scss b/app/globals.scss index 84d86de..20a30dd 100644 --- a/app/globals.scss +++ b/app/globals.scss @@ -679,15 +679,11 @@ section h3.party { font-size: 7vmax; font-weight: 800; text-transform: uppercase; - overflow: auto; } @include media-breakpoint-up(lg) { section h3.party { font-size: 4vmax; - font-weight: 800; - text-transform: uppercase; - overflow: auto; } } @@ -708,7 +704,8 @@ div.party-heart { /*border: solid 1px var(--bs-gray-300);*/ } -a span.party-none h3.party-none, +span.party-none, +h3.party-none, svg.party-none, i.party-none { color: var(--bs-gray-500); diff --git a/utils/Party.ts b/utils/Party.ts index e6945dc..e9fa53d 100644 --- a/utils/Party.ts +++ b/utils/Party.ts @@ -91,7 +91,10 @@ const partyCssClassFromSlug = (slug: PartySlug) => { } }; +const progressiveSlugs: PartySlug[] = ["Lab", "LD", "Green", "SNP", "PC"]; + export { + progressiveSlugs, partyColorFromSlug, partyNameFromSlug, shortPartyNameFromSlug,