From 12e939380e0e9783daa9cc892a432b2b5a9a5795 Mon Sep 17 00:00:00 2001 From: mertbagt Date: Sun, 19 Jul 2026 13:35:29 -0400 Subject: [PATCH 01/14] remove value overrriden property --- components/OurTeam/Partners.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/OurTeam/Partners.tsx b/components/OurTeam/Partners.tsx index 5ab695e1b..0b11ce8fc 100644 --- a/components/OurTeam/Partners.tsx +++ b/components/OurTeam/Partners.tsx @@ -14,7 +14,7 @@ export const LocalizedContent = (props: { components={{ a: ( Date: Tue, 1 Sep 2026 20:40:21 -0400 Subject: [PATCH 02/14] cleanup --- .../SidebarComponents/UpcomingHearings.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/components/LegislatorProfile/SidebarComponents/UpcomingHearings.tsx b/components/LegislatorProfile/SidebarComponents/UpcomingHearings.tsx index 4bbb86c2e..facf49a4a 100644 --- a/components/LegislatorProfile/SidebarComponents/UpcomingHearings.tsx +++ b/components/LegislatorProfile/SidebarComponents/UpcomingHearings.tsx @@ -78,20 +78,18 @@ export function UpcomingHearings({ committeeList }: { committeeList: any[] }) { } } - const LegislatorCommitteCodes = committeeList.map(code => code.CommitteeCode) + const LegislatorCommitteeCodes = committeeList.map(code => code.CommitteeCode) let legislatorEvents: any[] = [] if (events) { eventList.forEach(event => { - if (LegislatorCommitteCodes.includes(event.code)) { + if (LegislatorCommitteeCodes.includes(event.code)) { legislatorEvents.push(event) } }) } - console.log("legislatorEvents", legislatorEvents) - return ( {t("upcomingHearings")} From 36c2e5d40419de039302f6e487a0ce157d63b06e Mon Sep 17 00:00:00 2001 From: mertbagt Date: Thu, 3 Sep 2026 11:12:51 -0400 Subject: [PATCH 03/14] initial --- .../LegislatorProfile/LegislatorProfilePage.tsx | 1 + components/LegislatorProfile/LegislatorSidebar.tsx | 6 ++++-- .../SidebarComponents/OtherTestimony.tsx | 11 ++++++++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/components/LegislatorProfile/LegislatorProfilePage.tsx b/components/LegislatorProfile/LegislatorProfilePage.tsx index e65576a90..000122c27 100644 --- a/components/LegislatorProfile/LegislatorProfilePage.tsx +++ b/components/LegislatorProfile/LegislatorProfilePage.tsx @@ -381,6 +381,7 @@ export function LegislatorProfilePage({ legislatorData={legislatorData} legislatorId={legislatorId} memberCode={memberCode} + sponsoredBills={member.SponsoredBills} /> diff --git a/components/LegislatorProfile/LegislatorSidebar.tsx b/components/LegislatorProfile/LegislatorSidebar.tsx index 155006208..b04dcfaca 100644 --- a/components/LegislatorProfile/LegislatorSidebar.tsx +++ b/components/LegislatorProfile/LegislatorSidebar.tsx @@ -9,17 +9,19 @@ export function LegislatorSidebar({ court, legislatorData, legislatorId, - memberCode + memberCode, + sponsoredBills }: { committeeList: any[] court: number legislatorData: any[] legislatorId: string memberCode: string + sponsoredBills: any[] }) { return ( <> - + {t("otherTestimony")} From 2175d4a25ea3cae5b1476537b804d6992105d48c Mon Sep 17 00:00:00 2001 From: mertbagt Date: Thu, 3 Sep 2026 13:36:55 -0400 Subject: [PATCH 04/14] testimony results --- .../LegislatorProfile/LegislatorSidebar.tsx | 2 +- .../SidebarComponents/OtherTestimony.tsx | 26 +++++++++++++++---- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/components/LegislatorProfile/LegislatorSidebar.tsx b/components/LegislatorProfile/LegislatorSidebar.tsx index b04dcfaca..b5f66dbdc 100644 --- a/components/LegislatorProfile/LegislatorSidebar.tsx +++ b/components/LegislatorProfile/LegislatorSidebar.tsx @@ -21,7 +21,7 @@ export function LegislatorSidebar({ }) { return ( <> - + { + const data = usePublishedTestimonyListing({ + billId: bill, + court: court + }) - console.log("Test: ", test) + data.items.result?.length + ? testimonyOnLegislatorBills.push(data.items.result) + : null + }) + + console.log("X: ", testimonyOnLegislatorBills) + + // console.log("S: ", sponsoredBills) return ( From 1f55af24bd8c50a0368b80afa62923a0bd79413d Mon Sep 17 00:00:00 2001 From: mertbagt Date: Thu, 3 Sep 2026 15:16:14 -0400 Subject: [PATCH 05/14] display --- .../LegislatorProfile/LegislatorSidebar.tsx | 12 ++ .../SidebarComponents/OtherTestimony.tsx | 137 +++++++++++++++++- .../SidebarComponents/UpcomingHearings.tsx | 17 +-- public/locales/en/legislators.json | 9 +- 4 files changed, 155 insertions(+), 20 deletions(-) diff --git a/components/LegislatorProfile/LegislatorSidebar.tsx b/components/LegislatorProfile/LegislatorSidebar.tsx index b5f66dbdc..22266e56d 100644 --- a/components/LegislatorProfile/LegislatorSidebar.tsx +++ b/components/LegislatorProfile/LegislatorSidebar.tsx @@ -1,5 +1,7 @@ import styled from "styled-components" +import * as links from "../links" + import { Biography } from "./SidebarComponents/Biography" import { OtherTestimony } from "./SidebarComponents/OtherTestimony" import { UpcomingHearings } from "./SidebarComponents/UpcomingHearings" @@ -43,6 +45,16 @@ export const SidebarBlock = styled.div` padding: 16px; ` +export const SidebarLink = styled(links.Internal)` + font-size: 12px; + font-weight: 700; + color: #1a3185; + padding: 10px; + display: block; + text-align: center; + text-decoration: none; +` + export const SidebarTitle = styled.div` font-weight: 700; color: #0b0a3e; diff --git a/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx b/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx index d07c1f543..80bb1b8b4 100644 --- a/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx +++ b/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx @@ -1,9 +1,94 @@ import { useTranslation } from "next-i18next" +import styled from "styled-components" -import { SidebarBlock, SidebarTitle } from "../LegislatorSidebar" +import { Col } from "../../bootstrap" +import { SidebarBlock, SidebarLink, SidebarTitle } from "../LegislatorSidebar" import { usePublishedTestimonyListing } from "components/db" +const TestimonyBlock = styled.div` + background: #f8f9fa; + border-radius: 6px; + padding: 10px; + margin-bottom: 6px; +` + +/* Position Components */ + +const EndorseBubble = styled.div.attrs(props => ({ + className: `${props.className}` +}))` + background: #d4edda; + color: #155724; + + font-size: 10px; + font-weight: 700; + padding: 2px 7px; + border-radius: 999px; + margin-bottom: 4px; + display: inline-block; +` + +const NeutralBubble = styled.div.attrs(props => ({ + className: `${props.className}` +}))` + background: #d1d6e7; + color: #1a3185; + + font-size: 10px; + font-weight: 700; + padding: 2px 7px; + border-radius: 999px; + margin-bottom: 4px; + display: inline-block; +` + +const OpposeBubble = styled.div.attrs(props => ({ + className: `${props.className}` +}))` + background: #f4d2d6; + color: #8b0000; + + font-size: 10px; + font-weight: 700; + padding: 2px 7px; + border-radius: 999px; + margin-bottom: 4px; + display: inline-block; +` + +function PositionButton(props: { position: string }) { + const { t } = useTranslation("legislators") + + switch (props.position) { + case "endorse": + return {t("position.endorse")} + case "oppose": + return {t("position.oppose")} + default: + return {t("position.neutral")} + } +} + +/* Misc Testimony Components */ + +const TestimonyBorder = styled.div` + border-bottom: 1px solid #b8c0c9; +` + +const TestimonyMeta = styled.div` + color: #6c757d; + font-size: 10px; +` + +const TestimonyText = styled.div` + color: #495057; + line-height: 1.5; + font-size: 12px; + font-style: italic; + margin-bottom: 3px; +` + export function OtherTestimony({ court, sponsoredBills @@ -22,18 +107,60 @@ export function OtherTestimony({ }) data.items.result?.length - ? testimonyOnLegislatorBills.push(data.items.result) + ? testimonyOnLegislatorBills.push( + ...data.items.result + .sort((a, b) => b.updatedAt.toMillis() - a.updatedAt.toMillis()) + .slice(0, 3) + ) : null }) - console.log("X: ", testimonyOnLegislatorBills) + testimonyOnLegislatorBills + .sort((a, b) => b.updatedAt.toMillis() - a.updatedAt.toMillis()) + .slice(0, 3) + + /* formatted Testimony On Legislator Bills */ + const formattedTOLB = testimonyOnLegislatorBills.map(obj => { + const date = new Date(obj.updatedAt.toMillis()) - // console.log("S: ", sponsoredBills) + const monthYear = date.toLocaleString("en-US", { + month: "long", + year: "numeric", + timeZone: "UTC" + }) + + return { + ...obj, + formattedDate: monthYear + } + }) return ( {t("otherTestimony")} -
Content To Be Added
+ {formattedTOLB ? ( + <> + {formattedTOLB.map(t => ( + + + {t.content} + + {t.authorDisplayName} {" · "} {t.billId} {" · "} + {t.formattedDate} + + + ))} + + ) : ( +
{t("noTestimony")}
+ )} + + + + {t("viewAllTestimony")} + {" ↗"} + +
) } diff --git a/components/LegislatorProfile/SidebarComponents/UpcomingHearings.tsx b/components/LegislatorProfile/SidebarComponents/UpcomingHearings.tsx index facf49a4a..72e9bbdc2 100644 --- a/components/LegislatorProfile/SidebarComponents/UpcomingHearings.tsx +++ b/components/LegislatorProfile/SidebarComponents/UpcomingHearings.tsx @@ -2,9 +2,8 @@ import { DateTime } from "luxon" import { useTranslation } from "next-i18next" import styled from "styled-components" -import * as links from "../../links" import { Col } from "../../bootstrap" -import { SidebarBlock, SidebarTitle } from "../LegislatorSidebar" +import { SidebarBlock, SidebarLink, SidebarTitle } from "../LegislatorSidebar" import { useUpcomingEvents } from "components/db/events" import { EventData } from "components/HearingsScheduled" @@ -33,16 +32,6 @@ const EventLocation = styled.div` margin-top: 1px; ` -export const HearingsLink = styled(links.Internal)` - font-size: 12px; - font-weight: 700; - color: #1a3185; - padding: 10px; - display: block; - text-align: center; - text-decoration: none; -` - export function UpcomingHearings({ committeeList }: { committeeList: any[] }) { const { t } = useTranslation("legislators") @@ -109,10 +98,10 @@ export function UpcomingHearings({ committeeList }: { committeeList: any[] }) {
{t("noEvents")}
)} - + {t("viewAllHearings")} {" ↗"} - +
) diff --git a/public/locales/en/legislators.json b/public/locales/en/legislators.json index 79d2da6fc..331f60739 100644 --- a/public/locales/en/legislators.json +++ b/public/locales/en/legislators.json @@ -45,6 +45,7 @@ "legislators": "Legislators", "loading": "Loading district...", "noEvents": "This legislator does not have hearings in the near term future", + "noTestimony": "This legislator does not yet have testimony for any of their bills", "notClaimed": "This legislator has not claimed their MAPLE account", "otherTestimony": "Others' testimony on their bills", "party": { @@ -52,6 +53,11 @@ "party": "Party", "republican": "Republican Party" }, + "position": { + "endorse": "Endorse", + "neutral": "Neutral", + "oppose": "Oppose" + }, "stateRepresentative": "State Representative", "stateSenator": "State Senator", "submit": "Submit", @@ -66,5 +72,6 @@ }, "termsServed": "Terms Served", "upcomingHearings": "Upcoming Hearings", - "viewAllHearings": "View all hearings" + "viewAllHearings": "View all hearings", + "viewAllTestimony": "View all testimony" } \ No newline at end of file From 8a3f91126a75ca446e5660d1813c3cede099b10a Mon Sep 17 00:00:00 2001 From: mertbagt Date: Thu, 3 Sep 2026 15:51:33 -0400 Subject: [PATCH 06/14] unrelated follow button text fix --- components/EditProfilePage/FollowersTab.tsx | 2 ++ public/locales/en/profile.json | 1 + 2 files changed, 3 insertions(+) diff --git a/components/EditProfilePage/FollowersTab.tsx b/components/EditProfilePage/FollowersTab.tsx index b03561bed..e1e622396 100644 --- a/components/EditProfilePage/FollowersTab.tsx +++ b/components/EditProfilePage/FollowersTab.tsx @@ -47,6 +47,7 @@ export const FollowersTab = ({ }) } } + useEffect(() => { if (uid) { setState(prev => ({ ...prev, loading: true, error: null })) @@ -55,6 +56,7 @@ export const FollowersTab = ({ setState({ items: [], loading: false, error: null }) } }, [uid]) + return ( Date: Tue, 8 Sep 2026 21:47:15 -0400 Subject: [PATCH 07/14] refactor testimony selector --- .../LegislatorComponents.tsx | 9 +++ .../OtherTestimony.module.css | 6 ++ .../SidebarComponents/OtherTestimony.tsx | 80 ++++++++++++------- 3 files changed, 65 insertions(+), 30 deletions(-) create mode 100644 components/LegislatorProfile/SidebarComponents/OtherTestimony.module.css diff --git a/components/LegislatorProfile/LegislatorComponents.tsx b/components/LegislatorProfile/LegislatorComponents.tsx index 38a48dbe2..9e22039dc 100644 --- a/components/LegislatorProfile/LegislatorComponents.tsx +++ b/components/LegislatorProfile/LegislatorComponents.tsx @@ -19,6 +19,15 @@ export const formatPhoneNumber = (value: string) => { ` } +export function shuffleArray(array: any) { + for (let i = array.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)) + + ;[array[i], array[j]] = [array[j], array[i]] + } + return array +} + export const TabBlock = styled.div` background-color: white; border: 1px #b8c0c9 solid; diff --git a/components/LegislatorProfile/SidebarComponents/OtherTestimony.module.css b/components/LegislatorProfile/SidebarComponents/OtherTestimony.module.css new file mode 100644 index 000000000..583358050 --- /dev/null +++ b/components/LegislatorProfile/SidebarComponents/OtherTestimony.module.css @@ -0,0 +1,6 @@ +.billTestimonyCard + ~ .billTestimonyCard + ~ .billTestimonyCard + ~ .billTestimonyCard { + display: none; +} diff --git a/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx b/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx index 80bb1b8b4..56be24903 100644 --- a/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx +++ b/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx @@ -1,4 +1,5 @@ import { useTranslation } from "next-i18next" +import { useMemo } from "react" import styled from "styled-components" import { Col } from "../../bootstrap" @@ -6,6 +7,11 @@ import { SidebarBlock, SidebarLink, SidebarTitle } from "../LegislatorSidebar" import { usePublishedTestimonyListing } from "components/db" +import { shuffleArray } from "../LegislatorComponents" + +import styles from "./OtherTestimony.module.css" +import { random } from "lodash" + const TestimonyBlock = styled.div` background: #f8f9fa; border-radius: 6px; @@ -89,38 +95,60 @@ const TestimonyText = styled.div` margin-bottom: 3px; ` -export function OtherTestimony({ +export const OtherTestimony = ({ court, sponsoredBills }: { court: number sponsoredBills: any[] -}) { +}) => { const { t } = useTranslation("legislators") - const testimonyOnLegislatorBills: any[] = [] + const randomBills: any[] = shuffleArray(sponsoredBills) - sponsoredBills.forEach(bill => { - const data = usePublishedTestimonyListing({ - billId: bill, - court: court - }) + return ( + + {t("otherTestimony")} + {randomBills.map(bill => ( + + ))} + + + + {t("viewAllTestimony")} + {" ↗"} + + + + ) +} - data.items.result?.length - ? testimonyOnLegislatorBills.push( - ...data.items.result - .sort((a, b) => b.updatedAt.toMillis() - a.updatedAt.toMillis()) - .slice(0, 3) - ) - : null - }) +const BillTestimonyList = ({ + billId, + court +}: { + billId: string + court: number +}) => { + const { t } = useTranslation("legislators") - testimonyOnLegislatorBills - .sort((a, b) => b.updatedAt.toMillis() - a.updatedAt.toMillis()) - .slice(0, 3) + const data = usePublishedTestimonyListing({ billId, court }) + const length = data?.items?.result?.length ?? 0 + const hasData = length > 0 + + const topTestimonies = useMemo(() => { + return data?.items?.result + ? [...data.items.result] + .sort((a, b) => b.updatedAt.toMillis() - a.updatedAt.toMillis()) + .slice(0, 1) + : [] + }, [data]) + + if (!hasData) + return
/* formatted Testimony On Legislator Bills */ - const formattedTOLB = testimonyOnLegislatorBills.map(obj => { + const formattedTOLB = topTestimonies.map(obj => { const date = new Date(obj.updatedAt.toMillis()) const monthYear = date.toLocaleString("en-US", { @@ -136,8 +164,7 @@ export function OtherTestimony({ }) return ( - - {t("otherTestimony")} +
{formattedTOLB ? ( <> {formattedTOLB.map(t => ( @@ -154,13 +181,6 @@ export function OtherTestimony({ ) : (
{t("noTestimony")}
)} - - - - {t("viewAllTestimony")} - {" ↗"} - - - +
) } From 3cdc4f1ab688ee74a2a0ae6f41e290ef98d69fbe Mon Sep 17 00:00:00 2001 From: mertbagt Date: Tue, 8 Sep 2026 22:00:32 -0400 Subject: [PATCH 08/14] limit results --- .../LegislatorProfile/SidebarComponents/OtherTestimony.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx b/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx index 56be24903..7b00573ad 100644 --- a/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx +++ b/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx @@ -104,7 +104,7 @@ export const OtherTestimony = ({ }) => { const { t } = useTranslation("legislators") - const randomBills: any[] = shuffleArray(sponsoredBills) + const randomBills: any[] = shuffleArray(sponsoredBills).slice(0, 10) return ( From 0685c46653713cad027c638e21d8a377e4353a8c Mon Sep 17 00:00:00 2001 From: mertbagt Date: Tue, 8 Sep 2026 22:02:23 -0400 Subject: [PATCH 09/14] revert limit --- .../LegislatorProfile/SidebarComponents/OtherTestimony.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx b/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx index 7b00573ad..56be24903 100644 --- a/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx +++ b/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx @@ -104,7 +104,7 @@ export const OtherTestimony = ({ }) => { const { t } = useTranslation("legislators") - const randomBills: any[] = shuffleArray(sponsoredBills).slice(0, 10) + const randomBills: any[] = shuffleArray(sponsoredBills) return ( From 29ad60ef35199ba07359d24f1de148382cf871a8 Mon Sep 17 00:00:00 2001 From: mertbagt Date: Tue, 8 Sep 2026 22:05:10 -0400 Subject: [PATCH 10/14] cleanup --- .../SidebarComponents/OtherTestimony.tsx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx b/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx index 56be24903..2f96755a8 100644 --- a/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx +++ b/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx @@ -3,14 +3,12 @@ import { useMemo } from "react" import styled from "styled-components" import { Col } from "../../bootstrap" -import { SidebarBlock, SidebarLink, SidebarTitle } from "../LegislatorSidebar" - -import { usePublishedTestimonyListing } from "components/db" - import { shuffleArray } from "../LegislatorComponents" +import { SidebarBlock, SidebarLink, SidebarTitle } from "../LegislatorSidebar" import styles from "./OtherTestimony.module.css" -import { random } from "lodash" + +import { usePublishedTestimonyListing } from "components/db" const TestimonyBlock = styled.div` background: #f8f9fa; From 162bf6635ae2fd1b963f4a179ddd0fb9faf42c4a Mon Sep 17 00:00:00 2001 From: mertbagt Date: Tue, 15 Sep 2026 20:34:40 -0400 Subject: [PATCH 11/14] integration --- .../LegislatorProfile/LegislatorSidebar.tsx | 2 +- .../SidebarComponents/OtherTestimony.tsx | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/components/LegislatorProfile/LegislatorSidebar.tsx b/components/LegislatorProfile/LegislatorSidebar.tsx index 22266e56d..e77171fdb 100644 --- a/components/LegislatorProfile/LegislatorSidebar.tsx +++ b/components/LegislatorProfile/LegislatorSidebar.tsx @@ -19,7 +19,7 @@ export function LegislatorSidebar({ legislatorData: any[] legislatorId: string memberCode: string - sponsoredBills: any[] + sponsoredBills?: string[] }) { return ( <> diff --git a/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx b/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx index 2f96755a8..925ceb952 100644 --- a/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx +++ b/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx @@ -10,6 +10,21 @@ import styles from "./OtherTestimony.module.css" import { usePublishedTestimonyListing } from "components/db" +import { DateTime } from "luxon" +import { + InstantSearch, + useConfigure, + useHits, + useInstantSearch +} from "react-instantsearch" +import TypesenseInstantSearchAdapter from "typesense-instantsearch-adapter" + +import { Spinner } from "components/bootstrap" +import { formatBillId, truncateText } from "components/formatting" +import { Internal, maple } from "components/links" +import { getServerConfig } from "components/search/common" +import { testimonySearchParams } from "components/search/searchParams" + const TestimonyBlock = styled.div` background: #f8f9fa; border-radius: 6px; @@ -98,7 +113,7 @@ export const OtherTestimony = ({ sponsoredBills }: { court: number - sponsoredBills: any[] + sponsoredBills?: string[] }) => { const { t } = useTranslation("legislators") From bc26775cb3fa10529fd769d49c3058311ff1dc6f Mon Sep 17 00:00:00 2001 From: mertbagt Date: Tue, 15 Sep 2026 20:52:01 -0400 Subject: [PATCH 12/14] params --- .../SidebarComponents/OtherTestimony.tsx | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx b/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx index 925ceb952..04bafdc31 100644 --- a/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx +++ b/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx @@ -108,6 +108,31 @@ const TestimonyText = styled.div` margin-bottom: 3px; ` +type TestimonyHitRecord = { + id: string + billId: string + court: number + position: "endorse" | "oppose" | "neutral" + content: string + authorDisplayName: string + publishedAt: number +} + +function ConfigureParams({ + court, + billIds +}: { + court: number + billIds: string[] +}) { + const configure = { + hitsPerPage: 3, + filters: `court:=${court} && billId:=[${billIds.join(",")}]` + } as any + useConfigure(configure) + return null +} + export const OtherTestimony = ({ court, sponsoredBills From 4e57e92b97ddb5bfc3d8bd9d5e0958f9069b009f Mon Sep 17 00:00:00 2001 From: mertbagt Date: Tue, 15 Sep 2026 21:54:35 -0400 Subject: [PATCH 13/14] finish refactor --- .../OtherTestimony.module.css | 6 - .../SidebarComponents/OtherTestimony.tsx | 226 +++++++++++------- public/locales/en/legislators.json | 2 +- 3 files changed, 143 insertions(+), 91 deletions(-) delete mode 100644 components/LegislatorProfile/SidebarComponents/OtherTestimony.module.css diff --git a/components/LegislatorProfile/SidebarComponents/OtherTestimony.module.css b/components/LegislatorProfile/SidebarComponents/OtherTestimony.module.css deleted file mode 100644 index 583358050..000000000 --- a/components/LegislatorProfile/SidebarComponents/OtherTestimony.module.css +++ /dev/null @@ -1,6 +0,0 @@ -.billTestimonyCard - ~ .billTestimonyCard - ~ .billTestimonyCard - ~ .billTestimonyCard { - display: none; -} diff --git a/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx b/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx index 04bafdc31..8decaad16 100644 --- a/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx +++ b/components/LegislatorProfile/SidebarComponents/OtherTestimony.tsx @@ -1,24 +1,18 @@ +import { DateTime } from "luxon" import { useTranslation } from "next-i18next" import { useMemo } from "react" -import styled from "styled-components" - -import { Col } from "../../bootstrap" -import { shuffleArray } from "../LegislatorComponents" -import { SidebarBlock, SidebarLink, SidebarTitle } from "../LegislatorSidebar" - -import styles from "./OtherTestimony.module.css" - -import { usePublishedTestimonyListing } from "components/db" - -import { DateTime } from "luxon" import { InstantSearch, useConfigure, useHits, useInstantSearch } from "react-instantsearch" +import styled from "styled-components" import TypesenseInstantSearchAdapter from "typesense-instantsearch-adapter" +import { Col } from "../../bootstrap" +import { SidebarBlock, SidebarLink, SidebarTitle } from "../LegislatorSidebar" + import { Spinner } from "components/bootstrap" import { formatBillId, truncateText } from "components/formatting" import { Internal, maple } from "components/links" @@ -91,6 +85,31 @@ function PositionButton(props: { position: string }) { /* Misc Testimony Components */ +const BillLink = styled(Internal)` + font-weight: 700; + color: #1a3185; + text-decoration: none; + + &:hover { + text-decoration: underline; + } +` + +const ContentSnippet = styled.div` + color: #212529; + font-size: 11px; + line-height: 1.4; +` + +const DateLine = styled.span` + whitespace: "nowrap"; +` + +const Interpunct = styled.span` + color: #3b3b3b; + font-weight: 700; +` + const TestimonyBorder = styled.div` border-bottom: 1px solid #b8c0c9; ` @@ -133,92 +152,131 @@ function ConfigureParams({ return null } -export const OtherTestimony = ({ - court, - sponsoredBills -}: { - court: number - sponsoredBills?: string[] -}) => { - const { t } = useTranslation("legislators") +function TestimonyList({ court }: { court: number }) { + const { t } = useTranslation(["legislators", "testimony"]) + const { hits } = useHits() + const { status, results } = useInstantSearch() + + const isLoading = + status === "loading" || status === "stalled" || !results._state + + if (isLoading && hits.length === 0) { + return ( +
+ + {t("loading", { defaultValue: "Loading testimony..." })} +
+ ) + } - const randomBills: any[] = shuffleArray(sponsoredBills) + if (hits.length === 0) { + return ( +
+ {t("noTestimony", { + defaultValue: "No testimony found for this legislator's bills." + })} +
+ ) + } return ( - - {t("otherTestimony")} - {randomBills.map(bill => ( - - ))} - - - - {t("viewAllTestimony")} - {" ↗"} - - - +
+ {hits.map(hit => { + const publishedDate = hit.publishedAt + ? DateTime.fromMillis(hit.publishedAt).toLocaleString( + DateTime.DATE_MED + ) + : null + + return ( + + + + {hit.content && ( + + + {truncateText(hit.content, 120)} + + + )} + + + {hit.authorDisplayName || "Anonymous"} + {" · "} + + {formatBillId(hit.billId)} + + {" · "} + + {publishedDate} + + + + ) + })} +
) } -const BillTestimonyList = ({ - billId, - court +export function OtherTestimony({ + court, + sponsoredBills = [] }: { - billId: string - court: number -}) => { + court?: number + sponsoredBills?: string[] +}) { const { t } = useTranslation("legislators") - const data = usePublishedTestimonyListing({ billId, court }) - const length = data?.items?.result?.length ?? 0 - const hasData = length > 0 - - const topTestimonies = useMemo(() => { - return data?.items?.result - ? [...data.items.result] - .sort((a, b) => b.updatedAt.toMillis() - a.updatedAt.toMillis()) - .slice(0, 1) - : [] - }, [data]) - - if (!hasData) - return
- - /* formatted Testimony On Legislator Bills */ - const formattedTOLB = topTestimonies.map(obj => { - const date = new Date(obj.updatedAt.toMillis()) - - const monthYear = date.toLocaleString("en-US", { - month: "long", - year: "numeric", - timeZone: "UTC" - }) - - return { - ...obj, - formattedDate: monthYear - } - }) + const billIds = useMemo(() => { + return Array.from(new Set(sponsoredBills)) + }, [sponsoredBills]) + + const searchClient = useMemo( + () => + new TypesenseInstantSearchAdapter({ + server: getServerConfig(), + additionalSearchParameters: testimonySearchParams + }).searchClient, + [] + ) + + const courtNumber = court ?? 193 return ( -
- {formattedTOLB ? ( + + {t("otherTestimony")} + {billIds.length === 0 ? ( +
+ {t("noTestimony", { + defaultValue: "No testimony found for this legislator's bills." + })} +
+ ) : ( <> - {formattedTOLB.map(t => ( - - - {t.content} - - {t.authorDisplayName} {" · "} {t.billId} {" · "} - {t.formattedDate} - - - ))} + + + + + + + + {t("viewAllTestimony")} + {" ↗"} + + - ) : ( -
{t("noTestimony")}
)} -
+ ) } diff --git a/public/locales/en/legislators.json b/public/locales/en/legislators.json index 17f755b96..8c3a21ae9 100644 --- a/public/locales/en/legislators.json +++ b/public/locales/en/legislators.json @@ -45,7 +45,7 @@ "legislators": "Legislators", "loading": "Loading district...", "noEvents": "This legislator does not have hearings in the near term future", - "noTestimony": "This legislator does not yet have testimony for any of their bills", + "noTestimony": "No testimony found for this legislator's bills.", "notClaimed": "This legislator has not claimed their MAPLE account", "otherTestimony": "Others' testimony on their bills", "party": { From 6560bde71a7c4ae7cd34771df66c72cb60e111e5 Mon Sep 17 00:00:00 2001 From: mertbagt Date: Tue, 15 Sep 2026 21:58:13 -0400 Subject: [PATCH 14/14] cleanup --- components/LegislatorProfile/LegislatorComponents.tsx | 9 --------- 1 file changed, 9 deletions(-) diff --git a/components/LegislatorProfile/LegislatorComponents.tsx b/components/LegislatorProfile/LegislatorComponents.tsx index 9e22039dc..38a48dbe2 100644 --- a/components/LegislatorProfile/LegislatorComponents.tsx +++ b/components/LegislatorProfile/LegislatorComponents.tsx @@ -19,15 +19,6 @@ export const formatPhoneNumber = (value: string) => { ` } -export function shuffleArray(array: any) { - for (let i = array.length - 1; i > 0; i--) { - const j = Math.floor(Math.random() * (i + 1)) - - ;[array[i], array[j]] = [array[j], array[i]] - } - return array -} - export const TabBlock = styled.div` background-color: white; border: 1px #b8c0c9 solid;