|
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" |
6 | 3 |
|
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 |
21 | 8 | } |
22 | 9 |
|
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 | +}) => { |
37 | 15 | 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> |
63 | 17 | ) |
64 | 18 | } |
65 | 19 |
|
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 |
0 commit comments