@bloom-housing/ui-components 6.0.0 → 6.0.1-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +214 -9
- package/package.json +3 -5
- package/src/actions/Button.tsx +1 -0
- package/src/actions/LinkButton.tsx +1 -0
- package/src/blocks/FormCard.scss +1 -0
- package/src/blocks/HousingCounselor.tsx +8 -3
- package/src/blocks/ImageCard.tsx +24 -13
- package/src/blocks/MediaCard.docs.mdx +37 -0
- package/src/blocks/MediaCard.scss +10 -11
- package/src/blocks/MediaCard.tsx +4 -4
- package/src/blocks/StandardCard.tsx +1 -1
- package/src/blocks/StatusItem.tsx +17 -6
- package/src/forms/DOBField.tsx +20 -8
- package/src/forms/DateField.tsx +16 -7
- package/src/forms/Dropzone.scss +7 -0
- package/src/forms/Dropzone.tsx +18 -5
- package/src/forms/Field.tsx +5 -0
- package/src/forms/FieldGroup.tsx +14 -3
- package/src/forms/HouseholdMemberForm.tsx +4 -1
- package/src/forms/HouseholdSizeField.tsx +16 -6
- package/src/forms/TimeField.tsx +15 -6
- package/src/global/custom_counter.scss +1 -1
- package/src/global/forms.scss +38 -5
- package/src/global/headers.scss +1 -1
- package/src/global/markdown.scss +2 -2
- package/src/headers/Hero.tsx +8 -1
- package/src/headers/PageHeader.scss +1 -1
- package/src/headers/PageHeader.tsx +5 -1
- package/src/headers/SiteHeader.tsx +11 -4
- package/src/helpers/formOptions.tsx +4 -1
- package/src/helpers/formatYesNoLabel.ts +8 -6
- package/src/locales/es.json +1 -1
- package/src/locales/general.json +9 -4
- package/src/locales/tl.json +1 -1
- package/src/locales/vi.json +1 -1
- package/src/locales/zh.json +1 -1
- package/src/navigation/Breadcrumbs.tsx +1 -1
- package/src/navigation/FooterNav.tsx +5 -1
- package/src/navigation/LanguageNav.tsx +1 -1
- package/src/navigation/ProgressNav.docs.mdx +47 -0
- package/src/navigation/ProgressNav.scss +101 -56
- package/src/navigation/ProgressNav.tsx +45 -15
- package/src/navigation/TabNav.scss +1 -1
- package/src/navigation/TabNav.tsx +1 -1
- package/src/notifications/AlertBox.docs.mdx +41 -0
- package/src/notifications/AlertBox.scss +78 -41
- package/src/notifications/AlertBox.tsx +20 -14
- package/src/notifications/SiteAlert.tsx +3 -0
- package/src/notifications/StatusMessage.tsx +8 -2
- package/src/notifications/alertTypes.ts +1 -0
- package/src/overlays/Modal.scss +3 -1
- package/src/page_components/ApplicationTimeline.scss +6 -6
- package/src/page_components/ApplicationTimeline.tsx +17 -7
- package/src/page_components/forgot-password/FormForgotPassword.tsx +1 -1
- package/src/page_components/listing/AdditionalFees.tsx +1 -1
- package/src/page_components/listing/ListingCard.scss +4 -0
- package/src/page_components/listing/ListingCard.tsx +18 -3
- package/src/page_components/listing/listing_sidebar/Contact.tsx +2 -2
- package/src/page_components/listing/listing_sidebar/GetApplication.tsx +31 -16
- package/src/page_components/listing/listing_sidebar/ListingUpdated.tsx +5 -1
- package/src/page_components/listing/listing_sidebar/OrDivider.tsx +4 -2
- package/src/page_components/listing/listing_sidebar/ReferralApplication.tsx +7 -4
- package/src/page_components/listing/listing_sidebar/events/DownloadLotteryResults.tsx +6 -1
- package/src/page_components/sign-in/FormSignIn.tsx +1 -1
- package/src/page_components/sign-in/FormSignInErrorBox.tsx +1 -1
- package/src/sections/InfoCardGrid.scss +1 -1
- package/src/sections/InfoCardGrid.tsx +4 -1
- package/src/sections/ListSection.tsx +1 -1
- package/src/tables/AgTable.tsx +10 -4
- package/src/tables/StandardTable.tsx +19 -7
- package/src/text/Tag.scss +7 -0
- package/src/text/Tag.tsx +2 -0
|
@@ -1,86 +1,123 @@
|
|
|
1
1
|
.alert-box {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
--vertical-padding: var(--bloom-s3);
|
|
3
|
+
--horizontal-padding: var(--bloom-s4);
|
|
4
|
+
--background-color: var(--bloom-color-primary-light);
|
|
5
|
+
--alert-background-color: var(--bloom-color-alert-light);
|
|
6
|
+
--alert-invert-background-color: var(--bloom-color-alert);
|
|
7
|
+
--notice-background-color: var(--bloom-color-primary-light);
|
|
8
|
+
--notice-invert-background-color: var(--bloom-color-primary);
|
|
9
|
+
--success-background-color: var(--bloom-color-success-light);
|
|
10
|
+
--success-invert-background-color: var(--bloom-color-success);
|
|
11
|
+
--warn-background-color: var(--bloom-color-warn-light);
|
|
12
|
+
--warn-invert-background-color: var(--bloom-color-warn);
|
|
13
|
+
--text-color: var(--bloom-color-gray-900);
|
|
14
|
+
--close-icon-color: var(--bloom-color-gray-900);
|
|
15
|
+
--font-weight: 500;
|
|
16
|
+
--max-width: var(--bloom-width-5xl);
|
|
17
|
+
--line-height: 1.375;
|
|
18
|
+
|
|
19
|
+
padding: var(--vertical-padding) var(--horizontal-padding);
|
|
20
|
+
background-color: var(--background-color);
|
|
21
|
+
color: var(--text-color);
|
|
22
|
+
font-weight: var(--font-weight);
|
|
23
|
+
position: relative;
|
|
24
|
+
display: flex;
|
|
25
|
+
align-items: center;
|
|
26
|
+
line-height: var(--line-height);
|
|
8
27
|
|
|
9
28
|
.alert-box_inner {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
29
|
+
margin: auto;
|
|
30
|
+
max-width: var(--max-width);
|
|
31
|
+
padding-right: var(--horizontal-padding);
|
|
32
|
+
padding-left: var(--horizontal-padding);
|
|
33
|
+
flex: 1;
|
|
34
|
+
display: flex;
|
|
35
|
+
align-items: center;
|
|
16
36
|
}
|
|
17
37
|
|
|
18
38
|
&.narrow {
|
|
19
|
-
padding-top:
|
|
20
|
-
padding-bottom:
|
|
39
|
+
padding-top: var(--bloom-s1_5);
|
|
40
|
+
padding-bottom: var(--bloom-s1_5);
|
|
21
41
|
}
|
|
22
42
|
|
|
23
|
-
// Inverts color scheme of alert
|
|
24
43
|
&.invert {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
44
|
+
color: var(--bloom-color-white);
|
|
45
|
+
a {
|
|
46
|
+
color: var(--bloom-color-white);
|
|
47
|
+
text-decoration: underline;
|
|
29
48
|
}
|
|
30
49
|
}
|
|
31
50
|
|
|
32
51
|
&.alert {
|
|
33
|
-
|
|
52
|
+
background-color: var(--alert-background-color);
|
|
34
53
|
|
|
35
54
|
&.invert {
|
|
36
|
-
|
|
55
|
+
background-color: var(--alert-invert-background-color);
|
|
37
56
|
}
|
|
38
57
|
}
|
|
39
58
|
|
|
40
59
|
&.primary {
|
|
41
|
-
|
|
60
|
+
background-color: var(--notice-background-color);
|
|
42
61
|
|
|
43
62
|
&.invert {
|
|
44
|
-
|
|
63
|
+
background-color: var(--notice-invert-background-color);
|
|
45
64
|
}
|
|
46
65
|
}
|
|
47
66
|
|
|
48
67
|
&.success {
|
|
49
|
-
|
|
68
|
+
background-color: var(--success-background-color);
|
|
50
69
|
|
|
51
70
|
&.invert {
|
|
52
|
-
|
|
71
|
+
background-color: var(--success-invert-background-color);
|
|
53
72
|
}
|
|
54
73
|
}
|
|
55
74
|
|
|
56
75
|
&.warn {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
&.invert {
|
|
60
|
-
@apply bg-warn;
|
|
61
|
-
}
|
|
76
|
+
background-color: var(--warn-background-color);
|
|
62
77
|
}
|
|
63
78
|
}
|
|
64
79
|
|
|
65
80
|
.alert-box__head {
|
|
66
|
-
|
|
67
|
-
|
|
81
|
+
display: flex;
|
|
82
|
+
justify-content: space-between;
|
|
83
|
+
width: 100%;
|
|
68
84
|
}
|
|
69
85
|
|
|
70
86
|
.alert-box__title {
|
|
71
|
-
|
|
87
|
+
display: flex;
|
|
88
|
+
justify-content: space-between;
|
|
89
|
+
align-items: center;
|
|
72
90
|
}
|
|
73
91
|
|
|
74
92
|
.alert-box__body {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
@apply text-tiny;
|
|
93
|
+
font-weight: var(--font-weight);
|
|
94
|
+
font-size: var(--bloom-font-size-tiny);
|
|
78
95
|
}
|
|
79
96
|
|
|
80
97
|
.alert-box__close {
|
|
81
|
-
|
|
82
|
-
right:
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
line-height:
|
|
98
|
+
font-size: var(--bloom-font-size-3xl);
|
|
99
|
+
right: var(--horizontal-padding);
|
|
100
|
+
margin-left: var(--bloom-s3);
|
|
101
|
+
padding: 0;
|
|
102
|
+
line-height: var(--bloom-s4);
|
|
103
|
+
color: var(--close-icon-color);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.alert-box__icon {
|
|
107
|
+
margin-right: var(--bloom-s3);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.alert-box__sticky {
|
|
111
|
+
position: sticky;
|
|
112
|
+
top: var(--bloom-s3);
|
|
113
|
+
margin-top: var(--bloom-s3);
|
|
114
|
+
margin-right: var(--bloom-s3);
|
|
115
|
+
z-index: 10;
|
|
116
|
+
margin-left: auto;
|
|
117
|
+
width: fit-content;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.alert-box__sticky + * {
|
|
121
|
+
--alert-box-height: -3.6rem;
|
|
122
|
+
margin-top: var(--alert-box-height);
|
|
86
123
|
}
|
|
@@ -6,20 +6,23 @@ import { colorClasses } from "./alertTypes"
|
|
|
6
6
|
import "./AlertBox.scss"
|
|
7
7
|
|
|
8
8
|
export interface AlertBoxProps {
|
|
9
|
-
|
|
10
|
-
closeable?: boolean
|
|
11
|
-
onClose?: () => void
|
|
9
|
+
boundToLayoutWidth?: boolean
|
|
12
10
|
children: ReactNode
|
|
13
|
-
inverted?: boolean
|
|
14
11
|
className?: string
|
|
15
|
-
|
|
12
|
+
closeable?: boolean
|
|
13
|
+
customIcon?: IconTypes
|
|
14
|
+
inverted?: boolean
|
|
16
15
|
narrow?: boolean
|
|
16
|
+
onClose?: () => void
|
|
17
|
+
sticky?: boolean
|
|
18
|
+
type?: AlertTypes
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
const icons: { [k in AlertTypes]: IconTypes } = {
|
|
20
22
|
alert: "warning",
|
|
21
23
|
notice: "info",
|
|
22
24
|
success: "check",
|
|
25
|
+
warn: "warning",
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
const AlertBox = (props: AlertBoxProps) => {
|
|
@@ -28,11 +31,12 @@ const AlertBox = (props: AlertBoxProps) => {
|
|
|
28
31
|
|
|
29
32
|
const classNames = [
|
|
30
33
|
"alert-box",
|
|
31
|
-
colorClasses[props.type || "
|
|
34
|
+
colorClasses[props.type || ""],
|
|
32
35
|
...(props.inverted ? ["invert"] : []),
|
|
33
36
|
...(props.className ? [props.className] : []),
|
|
34
37
|
...(props.boundToLayoutWidth ? [] : ["fullWidth"]),
|
|
35
38
|
...(props.narrow ? ["narrow"] : []),
|
|
39
|
+
...(props.sticky ? ["alert-box__sticky"] : []),
|
|
36
40
|
].join(" ")
|
|
37
41
|
|
|
38
42
|
if (onClose) closeable = true
|
|
@@ -47,14 +51,16 @@ const AlertBox = (props: AlertBoxProps) => {
|
|
|
47
51
|
<>
|
|
48
52
|
<div className="alert-box__head">
|
|
49
53
|
<div className="alert-box__title">
|
|
50
|
-
|
|
51
|
-
<
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
{(props.type || props.customIcon) && (
|
|
55
|
+
<span className="alert-box__icon">
|
|
56
|
+
<Icon
|
|
57
|
+
size="medium"
|
|
58
|
+
symbol={props.type ? icons[props.type] : props.customIcon ?? "warning"}
|
|
59
|
+
fill={props.inverted ? IconFillColors.white : undefined}
|
|
60
|
+
ariaHidden={true}
|
|
61
|
+
/>
|
|
62
|
+
</span>
|
|
63
|
+
)}
|
|
58
64
|
<span className="alert-box__body">
|
|
59
65
|
{typeof props.children === "string" ? <p>{props.children}</p> : props.children}
|
|
60
66
|
</span>
|
|
@@ -11,6 +11,7 @@ type SiteAlertProps = {
|
|
|
11
11
|
type: AlertTypes
|
|
12
12
|
message: string
|
|
13
13
|
}
|
|
14
|
+
sticky?: boolean
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
export const setSiteAlertMessage = (message: string, type: AlertTypes) => {
|
|
@@ -30,6 +31,7 @@ export const SiteAlert = ({
|
|
|
30
31
|
type = "alert",
|
|
31
32
|
className,
|
|
32
33
|
alertMessage,
|
|
34
|
+
sticky,
|
|
33
35
|
}: SiteAlertProps) => {
|
|
34
36
|
const [open, setOpen] = useState(false)
|
|
35
37
|
const [message, setMessage] = useState("")
|
|
@@ -75,6 +77,7 @@ export const SiteAlert = ({
|
|
|
75
77
|
onClose={dismissable ? () => setOpen(false) : undefined}
|
|
76
78
|
className={className}
|
|
77
79
|
type={alertMessage?.type ?? type}
|
|
80
|
+
sticky={sticky}
|
|
78
81
|
>
|
|
79
82
|
{message}
|
|
80
83
|
</AlertBox>
|
|
@@ -8,6 +8,10 @@ import "./StatusMessage.scss"
|
|
|
8
8
|
export interface StatusMessagesProps {
|
|
9
9
|
lastTimestamp?: string
|
|
10
10
|
children?: React.ReactNode
|
|
11
|
+
strings?: {
|
|
12
|
+
lastUpdated?: string
|
|
13
|
+
statusHistory?: string
|
|
14
|
+
}
|
|
11
15
|
}
|
|
12
16
|
|
|
13
17
|
export const StatusMessages = (props: StatusMessagesProps) => {
|
|
@@ -17,7 +21,7 @@ export const StatusMessages = (props: StatusMessagesProps) => {
|
|
|
17
21
|
{props.lastTimestamp && (
|
|
18
22
|
<li className="status-message">
|
|
19
23
|
<div className="status-message__note text-center">
|
|
20
|
-
{t("t.lastUpdated")}: {props.lastTimestamp}
|
|
24
|
+
{props.strings?.lastUpdated ?? t("t.lastUpdated")}: {props.lastTimestamp}
|
|
21
25
|
</div>
|
|
22
26
|
</li>
|
|
23
27
|
)}
|
|
@@ -26,7 +30,9 @@ export const StatusMessages = (props: StatusMessagesProps) => {
|
|
|
26
30
|
} else {
|
|
27
31
|
return (
|
|
28
32
|
<>
|
|
29
|
-
<h3 className="status-messages__title">
|
|
33
|
+
<h3 className="status-messages__title">
|
|
34
|
+
{props.strings?.statusHistory ?? t("t.statusHistory")}
|
|
35
|
+
</h3>
|
|
30
36
|
<ul className="status-messages">{props.children}</ul>
|
|
31
37
|
</>
|
|
32
38
|
)
|
package/src/overlays/Modal.scss
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
position: relative;
|
|
18
18
|
max-width: var(--max-width);
|
|
19
|
+
max-height: 100vh;
|
|
19
20
|
margin: auto;
|
|
20
21
|
border: var(--modal-border);
|
|
21
22
|
background-color: var(--background-color);
|
|
@@ -33,7 +34,7 @@
|
|
|
33
34
|
|
|
34
35
|
.modal__title {
|
|
35
36
|
padding-block: var(--bloom-s6) var(--bloom-s3);
|
|
36
|
-
padding-inline: var(--bloom-s6);
|
|
37
|
+
padding-inline: var(--bloom-s6) var(--bloom-s12);
|
|
37
38
|
color: var(--title-color);
|
|
38
39
|
font-size: var(--title-font-size);
|
|
39
40
|
font-family: var(--title-font-family);
|
|
@@ -52,6 +53,7 @@
|
|
|
52
53
|
max-height: calc(100vh - 200px);
|
|
53
54
|
overflow-y: auto;
|
|
54
55
|
}
|
|
56
|
+
|
|
55
57
|
p {
|
|
56
58
|
color: var(--content-font-color);
|
|
57
59
|
}
|
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
.application-timeline {
|
|
7
|
-
.progress-
|
|
7
|
+
.progress-nav__dot-item {
|
|
8
8
|
@apply pt-0;
|
|
9
9
|
|
|
10
10
|
text-transform: unset;
|
|
11
11
|
|
|
12
12
|
.absolute {
|
|
13
|
-
margin-top: 0.
|
|
13
|
+
margin-top: 0.25rem;
|
|
14
14
|
z-index: 2;
|
|
15
15
|
margin-left: -0.4rem;
|
|
16
16
|
}
|
|
@@ -20,17 +20,17 @@
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
.progress-
|
|
24
|
-
.progress-
|
|
23
|
+
.progress-nav__dot-item.is-active::before,
|
|
24
|
+
.progress-nav__dot-item.is-disabled::before {
|
|
25
25
|
height: 2rem;
|
|
26
26
|
width: 2rem;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
.progress-
|
|
29
|
+
.progress-nav__dot-item.is-active::before {
|
|
30
30
|
@apply bg-green-700;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
.progress-
|
|
33
|
+
.progress-nav__dot-item::after {
|
|
34
34
|
top: 1rem;
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -4,27 +4,37 @@ import { Icon } from "../icons/Icon"
|
|
|
4
4
|
import { t } from "../helpers/translator"
|
|
5
5
|
import "./ApplicationTimeline.scss"
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
export interface ApplicationTimelineProps {
|
|
8
|
+
strings?: {
|
|
9
|
+
applicationReceived?: string
|
|
10
|
+
applicationsClosed?: string
|
|
11
|
+
applicationsRanked?: string
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
const ApplicationTimeline = (props: ApplicationTimelineProps) => (
|
|
8
15
|
<ul
|
|
9
16
|
className="progress-nav application-timeline"
|
|
10
17
|
aria-label="Steps of processing your application"
|
|
11
18
|
>
|
|
12
|
-
<li className="progress-
|
|
19
|
+
<li className="progress-nav__dot-item is-active" aria-current="step">
|
|
13
20
|
<span className="text-white absolute">
|
|
14
21
|
<Icon symbol="check" size="base" />
|
|
15
22
|
</span>
|
|
16
23
|
<Markdown className="font-bold" options={{ disableParsingRawHTML: true }}>
|
|
17
|
-
{
|
|
24
|
+
{props.strings?.applicationReceived ??
|
|
25
|
+
t("application.review.confirmation.applicationReceived")}
|
|
18
26
|
</Markdown>
|
|
19
27
|
</li>
|
|
20
|
-
<li className="progress-
|
|
28
|
+
<li className="progress-nav__dot-item is-disabled">
|
|
21
29
|
<Markdown options={{ disableParsingRawHTML: true }}>
|
|
22
|
-
{
|
|
30
|
+
{props.strings?.applicationsClosed ??
|
|
31
|
+
t("application.review.confirmation.applicationsClosed")}
|
|
23
32
|
</Markdown>
|
|
24
33
|
</li>
|
|
25
|
-
<li className="progress-
|
|
34
|
+
<li className="progress-nav__dot-item is-disabled">
|
|
26
35
|
<Markdown options={{ disableParsingRawHTML: true }}>
|
|
27
|
-
{
|
|
36
|
+
{props.strings?.applicationsRanked ??
|
|
37
|
+
t("application.review.confirmation.applicationsRanked")}
|
|
28
38
|
</Markdown>
|
|
29
39
|
</li>
|
|
30
40
|
</ul>
|
|
@@ -53,7 +53,7 @@ const FormForgotPassword = ({
|
|
|
53
53
|
<FormCard>
|
|
54
54
|
<div className="form-card__lead text-center border-b mx-0">
|
|
55
55
|
<Icon size="2xl" symbol="profile" />
|
|
56
|
-
<
|
|
56
|
+
<h1 className="form-card__title">{t("authentication.forgotPassword.sendEmail")}</h1>
|
|
57
57
|
</div>
|
|
58
58
|
|
|
59
59
|
{Object.entries(errors).length > 0 && !networkError.error && (
|
|
@@ -22,7 +22,7 @@ const AdditionalFees = ({
|
|
|
22
22
|
footerContent,
|
|
23
23
|
strings,
|
|
24
24
|
}: AdditionalFeesProps) => {
|
|
25
|
-
if (!deposit && !applicationFee && !
|
|
25
|
+
if (!deposit && !applicationFee && (!footerContent || footerContent?.length === 0)) return <></>
|
|
26
26
|
return (
|
|
27
27
|
<div className="info-card bg-gray-100 border-0">
|
|
28
28
|
<p className="info-card__title mb-2">{strings.sectionHeader}</p>
|
|
@@ -5,7 +5,7 @@ import { StackedTable, StackedTableProps } from "../../tables/StackedTable"
|
|
|
5
5
|
import { StandardTable, StandardTableProps } from "../../tables/StandardTable"
|
|
6
6
|
import { Heading, HeaderType } from "../../headers/Heading"
|
|
7
7
|
import { Tag } from "../../text/Tag"
|
|
8
|
-
import { AppearanceStyleType } from "../../global/AppearanceTypes"
|
|
8
|
+
import { AppearanceShadeType, AppearanceStyleType } from "../../global/AppearanceTypes"
|
|
9
9
|
import { Icon, IconFillColors } from "../../icons/Icon"
|
|
10
10
|
import "./ListingCard.scss"
|
|
11
11
|
import { NavigationContext } from "../../config/NavigationContext"
|
|
@@ -16,6 +16,8 @@ export interface CardHeader {
|
|
|
16
16
|
content: string | React.ReactNode
|
|
17
17
|
href?: string
|
|
18
18
|
customClass?: string
|
|
19
|
+
styleType?: AppearanceStyleType
|
|
20
|
+
isPillType?: boolean
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
export interface FooterButton {
|
|
@@ -74,12 +76,25 @@ const ListingCard = (props: ListingCardProps) => {
|
|
|
74
76
|
const getHeader = (
|
|
75
77
|
header: CardHeader | undefined,
|
|
76
78
|
priority: number,
|
|
77
|
-
|
|
79
|
+
styleType?: HeaderType,
|
|
78
80
|
customClass?: string
|
|
79
81
|
) => {
|
|
80
82
|
if (header && header.content) {
|
|
83
|
+
if (header.isPillType) {
|
|
84
|
+
return (
|
|
85
|
+
<Tag
|
|
86
|
+
className="listings-pill_header"
|
|
87
|
+
pillStyle
|
|
88
|
+
capitalized
|
|
89
|
+
styleType={header.styleType}
|
|
90
|
+
shade={AppearanceShadeType.light}
|
|
91
|
+
>
|
|
92
|
+
{header.content}
|
|
93
|
+
</Tag>
|
|
94
|
+
)
|
|
95
|
+
}
|
|
81
96
|
return (
|
|
82
|
-
<Heading priority={priority} style={
|
|
97
|
+
<Heading priority={priority} style={styleType} className={customClass}>
|
|
83
98
|
{header.href ? (
|
|
84
99
|
<LinkComponent className="is-card-link" href={header.href}>
|
|
85
100
|
{header.content}
|
|
@@ -95,12 +95,12 @@ const Contact = ({
|
|
|
95
95
|
|
|
96
96
|
{additionalInformation?.map((info) => {
|
|
97
97
|
return (
|
|
98
|
-
<
|
|
98
|
+
<div key={info.title} className={"my-3"}>
|
|
99
99
|
<Heading priority={3} style={"sidebarSubHeader"}>
|
|
100
100
|
{info.title}
|
|
101
101
|
</Heading>
|
|
102
102
|
<div className="text-gray-800 text-tiny markdown">{info.content}</div>
|
|
103
|
-
</
|
|
103
|
+
</div>
|
|
104
104
|
)
|
|
105
105
|
})}
|
|
106
106
|
</section>
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import React, { useState } from "react"
|
|
2
|
-
import
|
|
2
|
+
import Markdown from "markdown-to-jsx"
|
|
3
3
|
import { Button } from "../../../actions/Button"
|
|
4
4
|
import { LinkButton } from "../../../actions/LinkButton"
|
|
5
5
|
import { AppearanceStyleType } from "../../../global/AppearanceTypes"
|
|
6
6
|
import { Address } from "../../../helpers/MultiLineAddress"
|
|
7
|
-
import { ContactAddress } from "./ContactAddress"
|
|
8
|
-
import { OrDivider } from "./OrDivider"
|
|
9
7
|
import { Heading } from "../../../headers/Heading"
|
|
10
|
-
import
|
|
8
|
+
import { t } from "../../../helpers/translator"
|
|
9
|
+
import { OrDivider } from "./OrDivider"
|
|
10
|
+
import { ContactAddress } from "./ContactAddress"
|
|
11
11
|
|
|
12
12
|
export interface PaperApplication {
|
|
13
13
|
fileURL: string
|
|
@@ -33,6 +33,16 @@ export interface ApplicationsProps {
|
|
|
33
33
|
postmarkedApplicationsReceivedByDate?: string
|
|
34
34
|
/** Whether or not to hide actionable application buttons */
|
|
35
35
|
preview?: boolean
|
|
36
|
+
strings?: {
|
|
37
|
+
applicationsOpenInFuture?: string
|
|
38
|
+
applyOnline?: string
|
|
39
|
+
downloadApplication?: string
|
|
40
|
+
getAPaperApplication?: string
|
|
41
|
+
getDirections?: string
|
|
42
|
+
howToApply?: string
|
|
43
|
+
officeHoursHeading?: string
|
|
44
|
+
pickUpApplication?: string
|
|
45
|
+
}
|
|
36
46
|
}
|
|
37
47
|
/** Displays information regarding how to apply, including an online application link button, paper application downloads, and a paper application pickup address */
|
|
38
48
|
const GetApplication = (props: ApplicationsProps) => {
|
|
@@ -46,19 +56,22 @@ const GetApplication = (props: ApplicationsProps) => {
|
|
|
46
56
|
|
|
47
57
|
return (
|
|
48
58
|
<section className="aside-block" data-test-id="get-application-section">
|
|
49
|
-
<h2 className="text-caps-underline">
|
|
59
|
+
<h2 className="text-caps-underline">
|
|
60
|
+
{props.strings?.howToApply ?? t("listings.apply.howToApply")}
|
|
61
|
+
</h2>
|
|
50
62
|
{!props.applicationsOpen && (
|
|
51
63
|
<p className="mb-5 text-gray-700">
|
|
52
|
-
{
|
|
53
|
-
|
|
54
|
-
|
|
64
|
+
{props.strings?.applicationsOpenInFuture ??
|
|
65
|
+
t("listings.apply.applicationWillBeAvailableOn", {
|
|
66
|
+
openDate: props.applicationsOpenDate,
|
|
67
|
+
})}
|
|
55
68
|
</p>
|
|
56
69
|
)}
|
|
57
70
|
{props.applicationsOpen && props.onlineApplicationURL && (
|
|
58
71
|
<>
|
|
59
72
|
{props.preview ? (
|
|
60
73
|
<Button disabled className="w-full mb-2" data-test-id={"listing-view-apply-button"}>
|
|
61
|
-
{t("listings.apply.applyOnline")}
|
|
74
|
+
{props.strings?.applyOnline ?? t("listings.apply.applyOnline")}
|
|
62
75
|
</Button>
|
|
63
76
|
) : (
|
|
64
77
|
<LinkButton
|
|
@@ -67,7 +80,7 @@ const GetApplication = (props: ApplicationsProps) => {
|
|
|
67
80
|
href={props.onlineApplicationURL}
|
|
68
81
|
dataTestId={"listing-view-apply-button"}
|
|
69
82
|
>
|
|
70
|
-
{t("listings.apply.applyOnline")}
|
|
83
|
+
{props.strings?.applyOnline ?? t("listings.apply.applyOnline")}
|
|
71
84
|
</LinkButton>
|
|
72
85
|
)}
|
|
73
86
|
</>
|
|
@@ -76,7 +89,9 @@ const GetApplication = (props: ApplicationsProps) => {
|
|
|
76
89
|
{props.applicationsOpen && props.paperMethod && !!props.paperApplications?.length && (
|
|
77
90
|
<>
|
|
78
91
|
{props.onlineApplicationURL && <OrDivider bgColor="white" />}
|
|
79
|
-
<div className="text-serif-lg">
|
|
92
|
+
<div className="text-serif-lg">
|
|
93
|
+
{props.strings?.getAPaperApplication ?? t("listings.apply.getAPaperApplication")}
|
|
94
|
+
</div>
|
|
80
95
|
<Button
|
|
81
96
|
styleType={
|
|
82
97
|
!props.preview && props.onlineApplicationURL ? AppearanceStyleType.primary : undefined
|
|
@@ -85,7 +100,7 @@ const GetApplication = (props: ApplicationsProps) => {
|
|
|
85
100
|
onClick={toggleDownload}
|
|
86
101
|
disabled={props.preview}
|
|
87
102
|
>
|
|
88
|
-
{t("listings.apply.downloadApplication")}
|
|
103
|
+
{props.strings?.downloadApplication ?? t("listings.apply.downloadApplication")}
|
|
89
104
|
</Button>
|
|
90
105
|
</>
|
|
91
106
|
)}
|
|
@@ -94,7 +109,7 @@ const GetApplication = (props: ApplicationsProps) => {
|
|
|
94
109
|
<p key={index} className="text-center mt-2 mb-4 text-sm">
|
|
95
110
|
<a
|
|
96
111
|
href={paperApplication.fileURL}
|
|
97
|
-
title={t("listings.apply.downloadApplication")}
|
|
112
|
+
title={props.strings?.downloadApplication ?? t("listings.apply.downloadApplication")}
|
|
98
113
|
target="_blank"
|
|
99
114
|
>
|
|
100
115
|
{paperApplication.languageString}
|
|
@@ -107,16 +122,16 @@ const GetApplication = (props: ApplicationsProps) => {
|
|
|
107
122
|
<OrDivider bgColor="white" />
|
|
108
123
|
)}
|
|
109
124
|
<Heading priority={3} style={"sidebarSubHeader"}>
|
|
110
|
-
{t("listings.apply.pickUpAnApplication")}
|
|
125
|
+
{props.strings?.pickUpApplication ?? t("listings.apply.pickUpAnApplication")}
|
|
111
126
|
</Heading>
|
|
112
127
|
<ContactAddress
|
|
113
128
|
address={props.applicationPickUpAddress}
|
|
114
|
-
mapString={t("t.getDirections")}
|
|
129
|
+
mapString={props.strings?.getDirections ?? t("t.getDirections")}
|
|
115
130
|
/>
|
|
116
131
|
{props.applicationPickUpAddressOfficeHours && (
|
|
117
132
|
<>
|
|
118
133
|
<Heading priority={3} style={"sidebarSubHeader"}>
|
|
119
|
-
{t("leasingAgent.officeHours")}
|
|
134
|
+
{props.strings?.officeHoursHeading ?? t("leasingAgent.officeHours")}
|
|
120
135
|
</Heading>
|
|
121
136
|
<p className="text-gray-800 text-tiny markdown">
|
|
122
137
|
<Markdown
|
|
@@ -4,6 +4,9 @@ import dayjs from "dayjs"
|
|
|
4
4
|
|
|
5
5
|
interface ListingUpdatedProps {
|
|
6
6
|
listingUpdated: Date
|
|
7
|
+
strings?: {
|
|
8
|
+
listingUpdated?: string
|
|
9
|
+
}
|
|
7
10
|
}
|
|
8
11
|
|
|
9
12
|
const ListingUpdated = (props: ListingUpdatedProps) => {
|
|
@@ -11,7 +14,8 @@ const ListingUpdated = (props: ListingUpdatedProps) => {
|
|
|
11
14
|
return (
|
|
12
15
|
<section className="aside-block">
|
|
13
16
|
<p className="text-tiny text-gray-800">
|
|
14
|
-
{
|
|
17
|
+
{props?.strings?.listingUpdated ??
|
|
18
|
+
`${t("listings.listingUpdated")}: ${dayjs(listingUpdated).format("MMMM DD, YYYY")}`}
|
|
15
19
|
</p>
|
|
16
20
|
</section>
|
|
17
21
|
)
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import * as React from "react"
|
|
2
2
|
import { t } from "../../../helpers/translator"
|
|
3
3
|
|
|
4
|
-
const OrDivider = (props: { bgColor: string }) => (
|
|
4
|
+
const OrDivider = (props: { bgColor: string; strings?: { orString?: string } }) => (
|
|
5
5
|
<div className="aside-block__divider">
|
|
6
|
-
<span className={`bg-${props.bgColor} aside-block__conjunction`}>
|
|
6
|
+
<span className={`bg-${props.bgColor} aside-block__conjunction`}>
|
|
7
|
+
{props.strings?.orString ?? t("t.or")}
|
|
8
|
+
</span>
|
|
7
9
|
</div>
|
|
8
10
|
)
|
|
9
11
|
|