Skip to content

Commit f6480e8

Browse files
jasrosemertbagt
andauthored
refactor CardTitle to be generic; update usage (#1942)
* refactor CardTitle to be generic; update usage * ran prettier --------- Co-authored-by: Merritt Baggett <mertbagt@gmail.com>
1 parent f569d7f commit f6480e8

File tree

6 files changed

+274
-255
lines changed

6 files changed

+274
-255
lines changed

components/Card/Card.tsx

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,18 @@ export const Card = (CardProps: CardProps) => {
4343
} = CardProps
4444

4545
const headerContent = header ? (
46-
<CardTitle
47-
header={header}
48-
subheader={subheader}
49-
timestamp={timestamp}
50-
imgSrc={imgSrc}
51-
inHeaderElement={inHeaderElement}
52-
/>
53-
) : headerElement ? (
54-
headerElement
55-
) : null
46+
<CardBootstrap.Body className="align-items-center d-flex px-2 pt-2 pb-0">
47+
<CardBootstrap.Body className="px-3 py-0">
48+
<CardTitle>
49+
<CardBootstrap.Title className="align-items-start fs-6 lh-sm mb-1 text-secondary">
50+
<strong>{header}</strong>
51+
</CardBootstrap.Title>
52+
</CardTitle>
53+
</CardBootstrap.Body>
54+
</CardBootstrap.Body>
55+
) : (
56+
headerElement ?? null
57+
)
5658

5759
const bodyContent = body ? (
5860
body

components/Card/CardTitle.tsx

Lines changed: 15 additions & 211 deletions
Original file line numberDiff line numberDiff line change
@@ -1,218 +1,22 @@
1-
import { useTranslation } from "next-i18next"
2-
import { ReactElement } from "react"
3-
import CardBootstrap from "react-bootstrap/Card"
4-
import { formatBillId } from "components/formatting"
5-
import { Internal } from "components/links"
1+
import clsx from "clsx"
2+
import React from "react"
63

7-
interface CardTitleProps {
8-
authorUid?: string
9-
billId?: string
10-
court?: string
11-
header?: string
12-
subheader?: string
13-
timestamp?: string
14-
imgSrc?: string
15-
inHeaderElement?: ReactElement
16-
isBillMatch?: boolean
17-
isUserMatch?: boolean
18-
type?: string
19-
userRole?: string
20-
isNewsfeed?: string
4+
type CardTitleBaseProps = {
5+
title?: React.ReactNode
6+
className?: string
7+
children?: React.ReactNode
218
}
229

23-
export const CardTitle = (props: CardTitleProps) => {
24-
const {
25-
authorUid,
26-
billId,
27-
court,
28-
header,
29-
isBillMatch,
30-
isUserMatch,
31-
subheader,
32-
type,
33-
userRole,
34-
isNewsfeed
35-
} = props
36-
10+
const CardTitle: React.FC<CardTitleBaseProps> = ({
11+
title,
12+
children,
13+
className
14+
}) => {
3715
return (
38-
<CardBootstrap.Body className={`align-items-center d-flex px-2 pt-2 pb-0`}>
39-
<CardHeaderImg type={type} userRole={userRole} />
40-
<CardBootstrap.Body className="px-3 py-0">
41-
<CardTitleHeadline
42-
authorUid={authorUid}
43-
billId={billId}
44-
court={court}
45-
header={header}
46-
subheader={subheader}
47-
type={type}
48-
/>
49-
{isNewsfeed ? (
50-
<CardTitleFollowing
51-
billId={billId}
52-
header={header}
53-
subheader={subheader}
54-
isBillMatch={isBillMatch}
55-
isUserMatch={isUserMatch}
56-
type={type}
57-
/>
58-
) : (
59-
<></>
60-
)}
61-
</CardBootstrap.Body>
62-
</CardBootstrap.Body>
16+
<div className={clsx("card-title", className)}>{title ?? children}</div>
6317
)
6418
}
6519

66-
const CardHeaderImg = (props: CardTitleProps) => {
67-
const { type, userRole } = props
68-
69-
let avatar = `individualUser.svg`
70-
if (userRole == `organization`) {
71-
avatar = `OrganizationUser.svg`
72-
}
73-
74-
switch (type) {
75-
case "testimony":
76-
return (
77-
<div className="justify-content-middle d-flex flex-column align-items-center">
78-
<img alt="capitol building" src={avatar} width="32" height="32" />
79-
</div>
80-
)
81-
case "bill":
82-
return (
83-
<div className="justify-content-middle d-flex flex-column align-items-center">
84-
<img
85-
alt="capitol building"
86-
src={`/images/bill-capitol.svg`}
87-
width="32"
88-
height="32"
89-
/>
90-
</div>
91-
)
92-
default:
93-
return <></>
94-
}
95-
}
96-
97-
const CardTitleHeadline = (props: CardTitleProps) => {
98-
const { authorUid, billId, court, header, subheader, type } = props
99-
const { t } = useTranslation("common")
100-
101-
switch (type) {
102-
case "testimony":
103-
return (
104-
<>
105-
{header && subheader && (
106-
<CardBootstrap.Title
107-
className={`align-items-start fs-6 lh-sm mb-1 text-secondary`}
108-
>
109-
<Internal href={`/profile?id=${authorUid}`}>
110-
<strong>{subheader}</strong>
111-
</Internal>
112-
113-
{t("newsfeed.endorsed")}
114-
<a href={`/bills/${court}/${billId}`}>
115-
{billId && <strong>{formatBillId(billId)}</strong>}
116-
</a>
117-
</CardBootstrap.Title>
118-
)}
119-
</>
120-
)
121-
case "bill":
122-
return (
123-
<>
124-
{header && (
125-
<CardBootstrap.Title
126-
className={`align-items-start fs-6 lh-sm mb-1 text-secondary`}
127-
>
128-
{billId && (
129-
<a href={`/bills/${court}/${billId}`}>
130-
<strong>{formatBillId(billId)}</strong>
131-
</a>
132-
)}{" "}
133-
{subheader && (
134-
<>
135-
{t("newsfeed.actionUpdate")}
136-
{subheader}
137-
</>
138-
)}
139-
</CardBootstrap.Title>
140-
)}
141-
</>
142-
)
143-
default:
144-
return (
145-
<CardBootstrap.Title
146-
className={`align-items-start fs-6 lh-sm mb-1 text-secondary`}
147-
>
148-
<strong>{header}</strong>
149-
</CardBootstrap.Title>
150-
)
151-
}
152-
}
153-
154-
const CardTitleFollowing = (props: CardTitleProps) => {
155-
const { billId, header, isBillMatch, isUserMatch, subheader, type } = props
156-
const { t } = useTranslation("common")
157-
158-
if (type == ``) {
159-
return <></>
160-
} else if (type === `bill`) {
161-
return (
162-
<>
163-
{header && (
164-
<CardBootstrap.Title
165-
className={`align-items-start fs-6 lh-sm mb-1 text-body-tertiary`}
166-
>
167-
{isBillMatch ? (
168-
<>{t("newsfeed.follow")}</>
169-
) : (
170-
<>{t("newsfeed.notFollow")}</>
171-
)}
172-
{billId && <strong>{formatBillId(billId)}</strong>}
173-
</CardBootstrap.Title>
174-
)}
175-
</>
176-
)
177-
} else if (isBillMatch && isUserMatch) {
178-
return (
179-
<CardBootstrap.Title
180-
className={`align-items-start fs-6 lh-sm mb-1 text-body-tertiary`}
181-
>
182-
{t("newsfeed.follow")}
183-
{billId && <strong>{formatBillId(billId)}</strong>}
184-
{t("newsfeed.and")}
185-
{subheader}
186-
</CardBootstrap.Title>
187-
)
188-
} else if (isBillMatch === true && isUserMatch === false) {
189-
return (
190-
<CardBootstrap.Title
191-
className={`align-items-start fs-6 lh-sm mb-1 text-body-tertiary`}
192-
>
193-
{t("newsfeed.follow")}
194-
{billId && <strong>{formatBillId(billId)}</strong>}
195-
</CardBootstrap.Title>
196-
)
197-
} else if (isBillMatch === false && isUserMatch === true) {
198-
return (
199-
<CardBootstrap.Title
200-
className={`align-items-start fs-6 lh-sm mb-1 text-body-tertiary`}
201-
>
202-
{t("newsfeed.follow")}
203-
{subheader}
204-
</CardBootstrap.Title>
205-
)
206-
} else {
207-
return (
208-
<CardBootstrap.Title
209-
className={`align-items-start fs-6 lh-sm mb-1 text-body-tertiary`}
210-
>
211-
{t("newsfeed.notFollowEither")}
212-
{billId && <strong>{formatBillId(billId)}</strong>}
213-
{t("newsfeed.or")}
214-
{subheader}
215-
</CardBootstrap.Title>
216-
)
217-
}
218-
}
20+
// keep both named + default so existing imports don’t break
21+
export { CardTitle }
22+
export default CardTitle

components/NewsfeedCard/NewsfeedCard.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
NewsfeedBillCardBody,
66
NewsfeedTestimonyCardBody
77
} from "./NewsfeedCardBody"
8-
import { CardTitle } from "components/Card"
8+
import NewsfeedCardTitle from "./NewsfeedCardTitle"
99

1010
const Container = styled.div`
1111
max-width: 700px;
@@ -30,7 +30,7 @@ export const NewsfeedCard = (props: {
3030
const date = props.timestamp.toDate()
3131
const formattedTimestamp = `${date.toLocaleDateString()}`
3232
const header = (
33-
<CardTitle
33+
<NewsfeedCardTitle
3434
authorUid={props.authorUid}
3535
billId={props.billId}
3636
court={props.court}

0 commit comments

Comments
 (0)