@bloom-housing/ui-components 3.0.1-alpha.6 → 4.0.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/.jest/setup-tests.js +3 -0
- package/CHANGELOG.md +406 -0
- package/index.ts +1 -8
- package/jest.config.js +0 -1
- package/package.json +4 -4
- package/src/actions/Button.tsx +6 -0
- package/src/actions/LinkButton.tsx +7 -2
- package/src/blocks/DashBlock.tsx +6 -1
- package/src/blocks/ViewItem.tsx +2 -1
- package/src/forms/DOBField.tsx +3 -0
- package/src/forms/DateField.tsx +4 -0
- package/src/forms/Field.tsx +3 -0
- package/src/forms/FieldGroup.tsx +100 -16
- package/src/forms/HouseholdMemberForm.tsx +2 -1
- package/src/forms/PhoneField.tsx +2 -1
- package/src/forms/Select.tsx +4 -0
- package/src/forms/TimeField.tsx +6 -0
- package/src/global/forms.scss +1 -0
- package/src/headers/Hero.scss +7 -0
- package/src/headers/Hero.tsx +3 -3
- package/src/headers/PageHeader.tsx +2 -2
- package/src/headers/SiteHeader.scss +6 -5
- package/src/icons/Icon.tsx +2 -1
- package/src/icons/Icons.tsx +7 -2
- package/src/locales/es.json +53 -6
- package/src/locales/general.json +188 -18
- package/src/locales/general_OLD.json +1 -1
- package/src/locales/missing-translations.ts +2 -0
- package/src/locales/tl.json +5 -0
- package/src/locales/vi.json +51 -5
- package/src/locales/zh.json +53 -7
- package/src/navigation/ProgressNav.tsx +5 -3
- package/src/notifications/AlertBox.tsx +1 -1
- package/src/notifications/ErrorMessage.tsx +6 -1
- package/src/overlays/Modal.scss +4 -1
- package/src/overlays/Modal.tsx +5 -6
- package/src/page_components/listing/AdditionalFees.tsx +2 -1
- package/src/page_components/listing/ListingCard.tsx +1 -1
- package/src/page_components/listing/listing_sidebar/GetApplication.tsx +8 -1
- package/src/page_components/listing/listing_sidebar/SubmitApplication.tsx +13 -3
- package/src/page_components/listing/listing_sidebar/Waitlist.tsx +31 -62
- package/src/page_components/listing/listing_sidebar/events/DownloadLotteryResults.tsx +4 -7
- package/src/tables/MinimalTable.tsx +2 -0
- package/src/tables/StandardTable.tsx +2 -1
- package/tsconfig.json +0 -1
- package/src/helpers/blankApplication.ts +0 -111
- package/src/helpers/localeRoute.tsx +0 -13
- package/src/helpers/nextjs.ts +0 -7
- package/src/helpers/occupancyFormatting.tsx +0 -46
- package/src/helpers/pdfs.ts +0 -19
- package/src/helpers/photos.ts +0 -19
- package/src/helpers/unitTypes.ts +0 -42
package/src/forms/FieldGroup.tsx
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
|
-
import React from "react"
|
|
1
|
+
import React, { useState, useEffect } from "react"
|
|
2
|
+
import { ExpandableContent } from "../actions/ExpandableContent"
|
|
2
3
|
import { ErrorMessage } from "../notifications/ErrorMessage"
|
|
3
4
|
import { UseFormMethods } from "react-hook-form"
|
|
5
|
+
import { Field } from "./Field"
|
|
6
|
+
import { t } from "../helpers/translator"
|
|
4
7
|
|
|
5
8
|
interface FieldSingle {
|
|
6
9
|
id: string
|
|
7
10
|
label: string
|
|
8
11
|
value?: string
|
|
9
12
|
defaultChecked?: boolean
|
|
13
|
+
description?: React.ReactNode
|
|
14
|
+
defaultText?: string
|
|
10
15
|
note?: string
|
|
11
16
|
inputProps?: Record<string, unknown>
|
|
17
|
+
subFields?: FieldSingle[]
|
|
18
|
+
type?: string
|
|
19
|
+
additionalText?: boolean
|
|
12
20
|
}
|
|
13
21
|
|
|
14
22
|
interface FieldGroupProps {
|
|
@@ -25,6 +33,7 @@ interface FieldGroupProps {
|
|
|
25
33
|
fieldGroupClassName?: string
|
|
26
34
|
fieldClassName?: string
|
|
27
35
|
fieldLabelClassName?: string
|
|
36
|
+
dataTestId?: string
|
|
28
37
|
}
|
|
29
38
|
|
|
30
39
|
const FieldGroup = ({
|
|
@@ -41,12 +50,94 @@ const FieldGroup = ({
|
|
|
41
50
|
fieldClassName,
|
|
42
51
|
fieldLabelClassName,
|
|
43
52
|
groupSubNote,
|
|
53
|
+
dataTestId,
|
|
44
54
|
}: FieldGroupProps) => {
|
|
45
55
|
// Always align two-option radio groups side by side
|
|
46
56
|
if (fields?.length === 2) {
|
|
47
57
|
fieldGroupClassName = `${fieldGroupClassName} flex`
|
|
48
58
|
fieldClassName = `${fieldClassName} flex-initial mr-4`
|
|
49
59
|
}
|
|
60
|
+
|
|
61
|
+
const [checkedInputs, setCheckedInputs] = useState<string[]>([])
|
|
62
|
+
|
|
63
|
+
const subfieldsExist = () => {
|
|
64
|
+
return fields?.filter((field) => field.subFields).length
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const getIndividualInput = (item: FieldSingle): React.ReactNode => {
|
|
68
|
+
return (
|
|
69
|
+
<div key={item.value}>
|
|
70
|
+
<input
|
|
71
|
+
aria-describedby={`${name}-error`}
|
|
72
|
+
aria-invalid={!!error || false}
|
|
73
|
+
type={type}
|
|
74
|
+
id={item.id}
|
|
75
|
+
defaultValue={item.value || item.id}
|
|
76
|
+
name={subfieldsExist() ? `${name}-${item.value}` : name}
|
|
77
|
+
onClick={(e) => {
|
|
78
|
+
// We cannot reliably target an individual checkbox in a field group since they have the same name, so we keep track on our own
|
|
79
|
+
if (e.currentTarget.checked) {
|
|
80
|
+
setCheckedInputs([...checkedInputs, item.label])
|
|
81
|
+
} else {
|
|
82
|
+
setCheckedInputs(checkedInputs.filter((subset) => item.label !== subset))
|
|
83
|
+
}
|
|
84
|
+
}}
|
|
85
|
+
defaultChecked={item.defaultChecked || false}
|
|
86
|
+
ref={register(validation)}
|
|
87
|
+
{...item.inputProps}
|
|
88
|
+
data-test-id={dataTestId}
|
|
89
|
+
/>
|
|
90
|
+
<label htmlFor={item.id} className={`font-semibold ${fieldLabelClassName}`}>
|
|
91
|
+
{item.label}
|
|
92
|
+
</label>
|
|
93
|
+
{item.note && <span className={"field-note font-normal"}>{item.note}</span>}
|
|
94
|
+
|
|
95
|
+
{item.description && (
|
|
96
|
+
<div className="ml-8 -mt-1 mb-5">
|
|
97
|
+
<ExpandableContent>
|
|
98
|
+
<p className="field-note mb-2 -mt-2">{item.description}</p>
|
|
99
|
+
</ExpandableContent>
|
|
100
|
+
</div>
|
|
101
|
+
)}
|
|
102
|
+
</div>
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const checkSelected = (formFields: FieldSingle[] | undefined, checkedValues: string[]) => {
|
|
107
|
+
formFields?.forEach((field) => {
|
|
108
|
+
if (field.defaultChecked) {
|
|
109
|
+
checkedValues.push(field.label)
|
|
110
|
+
}
|
|
111
|
+
if (field.subFields) {
|
|
112
|
+
checkSelected(field.subFields, checkedValues)
|
|
113
|
+
}
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
useEffect(() => {
|
|
118
|
+
const initialValues: string[] = []
|
|
119
|
+
checkSelected(fields, initialValues)
|
|
120
|
+
setCheckedInputs([...initialValues])
|
|
121
|
+
}, [])
|
|
122
|
+
|
|
123
|
+
const getInputSet = (item: FieldSingle): React.ReactNode => {
|
|
124
|
+
return (
|
|
125
|
+
<div key={item.value}>
|
|
126
|
+
{getIndividualInput(item)}
|
|
127
|
+
{item.additionalText && checkedInputs.indexOf(item.label) >= 0 && (
|
|
128
|
+
<Field
|
|
129
|
+
id={item.id}
|
|
130
|
+
key={`${item.value}-additionalText`}
|
|
131
|
+
name={`${name}-${item.value}`}
|
|
132
|
+
register={register}
|
|
133
|
+
defaultValue={item.defaultText}
|
|
134
|
+
placeholder={t("t.description")}
|
|
135
|
+
className={"mb-4"}
|
|
136
|
+
/>
|
|
137
|
+
)}
|
|
138
|
+
</div>
|
|
139
|
+
)
|
|
140
|
+
}
|
|
50
141
|
return (
|
|
51
142
|
<>
|
|
52
143
|
{groupLabel && <label className="field-label--caps">{groupLabel}</label>}
|
|
@@ -55,21 +146,14 @@ const FieldGroup = ({
|
|
|
55
146
|
<div className={`field ${error && "error"} ${fieldGroupClassName || ""} mb-0`}>
|
|
56
147
|
{fields?.map((item) => (
|
|
57
148
|
<div className={`field ${fieldClassName || ""} mb-1`} key={item.id}>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
ref={register(validation)}
|
|
67
|
-
{...item.inputProps}
|
|
68
|
-
/>
|
|
69
|
-
<label htmlFor={item.id} className={`font-semibold ${fieldLabelClassName}`}>
|
|
70
|
-
{item.label}
|
|
71
|
-
</label>
|
|
72
|
-
{item.note && <span className={"field-note font-normal"}>{item.note}</span>}
|
|
149
|
+
{getInputSet(item)}
|
|
150
|
+
{item.subFields && checkedInputs.indexOf(item.label) >= 0 && (
|
|
151
|
+
<div className={"ml-8"} key={`${item.value}-subfields`}>
|
|
152
|
+
{item.subFields?.map((subItem) => {
|
|
153
|
+
return getInputSet(subItem)
|
|
154
|
+
})}
|
|
155
|
+
</div>
|
|
156
|
+
)}
|
|
73
157
|
</div>
|
|
74
158
|
))}
|
|
75
159
|
</div>
|
|
@@ -20,10 +20,11 @@ const HouseholdMemberForm = (props: HouseholdMemberFormProps) => {
|
|
|
20
20
|
{props.memberFirstName} {props.memberLastName}
|
|
21
21
|
{editMode ? (
|
|
22
22
|
<button
|
|
23
|
-
id=
|
|
23
|
+
id={`edit-member-${props.memberFirstName}-${props.memberLastName}`}
|
|
24
24
|
className="edit-link"
|
|
25
25
|
onClick={() => props.editMember && props.editMember(props.memberId)}
|
|
26
26
|
type={"button"}
|
|
27
|
+
data-test-id={"app-household-member-edit-button"}
|
|
27
28
|
>
|
|
28
29
|
{t("t.edit")}
|
|
29
30
|
</button>
|
package/src/forms/PhoneField.tsx
CHANGED
|
@@ -19,6 +19,7 @@ export const PhoneField = (props: {
|
|
|
19
19
|
disabled?: boolean
|
|
20
20
|
required?: boolean
|
|
21
21
|
mask?: (args: any) => JSX.Element
|
|
22
|
+
dataTestId?: string
|
|
22
23
|
}) => {
|
|
23
24
|
const labelClasses = ["label"]
|
|
24
25
|
if (props.caps) labelClasses.push("field-label--caps")
|
|
@@ -55,7 +56,7 @@ export const PhoneField = (props: {
|
|
|
55
56
|
return (
|
|
56
57
|
<div className={"field " + (props.error ? "error" : "")}>
|
|
57
58
|
{props.label && <label className={labelClasses.join(" ")}>{props.label}</label>}
|
|
58
|
-
<div className={props.controlClassName}>
|
|
59
|
+
<div className={props.controlClassName} data-test-id={props.dataTestId}>
|
|
59
60
|
{props.mask ? (
|
|
60
61
|
<Controller {...controllerProps} render={props.mask} />
|
|
61
62
|
) : (
|
package/src/forms/Select.tsx
CHANGED
|
@@ -27,6 +27,7 @@ interface SelectProps {
|
|
|
27
27
|
keyPrefix?: string
|
|
28
28
|
describedBy?: string
|
|
29
29
|
inputProps?: Record<string, unknown>
|
|
30
|
+
dataTestId?: string
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
export const Select = ({
|
|
@@ -47,6 +48,7 @@ export const Select = ({
|
|
|
47
48
|
inputProps,
|
|
48
49
|
defaultValue,
|
|
49
50
|
subNote,
|
|
51
|
+
dataTestId,
|
|
50
52
|
}: SelectProps) => {
|
|
51
53
|
return (
|
|
52
54
|
<div className={`field ${error ? "error" : ""}`}>
|
|
@@ -58,8 +60,10 @@ export const Select = ({
|
|
|
58
60
|
className="input"
|
|
59
61
|
id={id || name}
|
|
60
62
|
name={name}
|
|
63
|
+
data-test-id={dataTestId}
|
|
61
64
|
aria-describedby={describedBy ? describedBy : `${id}-error`}
|
|
62
65
|
aria-invalid={!!error || false}
|
|
66
|
+
aria-label={label}
|
|
63
67
|
ref={register && register(validation)}
|
|
64
68
|
disabled={disabled}
|
|
65
69
|
defaultValue={defaultValue ?? ""}
|
package/src/forms/TimeField.tsx
CHANGED
|
@@ -28,6 +28,7 @@ export type TimeFieldProps = {
|
|
|
28
28
|
required?: boolean
|
|
29
29
|
watch: UseFormMethods["watch"]
|
|
30
30
|
seconds?: boolean
|
|
31
|
+
dataTestId?: string
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
export const formatDateToTimeField = (date: Date) => {
|
|
@@ -54,6 +55,7 @@ const TimeField = ({
|
|
|
54
55
|
seconds,
|
|
55
56
|
defaultValues,
|
|
56
57
|
disabled,
|
|
58
|
+
dataTestId,
|
|
57
59
|
}: TimeFieldProps) => {
|
|
58
60
|
const fieldName = (baseName: string) => {
|
|
59
61
|
return [name, baseName].filter((item) => item).join(".")
|
|
@@ -99,6 +101,7 @@ const TimeField = ({
|
|
|
99
101
|
register={register}
|
|
100
102
|
describedBy={`${id}-error`}
|
|
101
103
|
disabled={disabled}
|
|
104
|
+
dataTestId={dataTestId ? `${dataTestId}-hours` : undefined}
|
|
102
105
|
/>
|
|
103
106
|
|
|
104
107
|
<Field
|
|
@@ -122,6 +125,7 @@ const TimeField = ({
|
|
|
122
125
|
register={register}
|
|
123
126
|
describedBy={`${id}-error`}
|
|
124
127
|
disabled={disabled}
|
|
128
|
+
dataTestId={dataTestId ? `${dataTestId}-minutes` : undefined}
|
|
125
129
|
/>
|
|
126
130
|
|
|
127
131
|
{seconds && (
|
|
@@ -146,6 +150,7 @@ const TimeField = ({
|
|
|
146
150
|
register={register}
|
|
147
151
|
describedBy={`${id}-error`}
|
|
148
152
|
disabled={disabled}
|
|
153
|
+
dataTestId={dataTestId ? `${dataTestId}-seconds` : undefined}
|
|
149
154
|
/>
|
|
150
155
|
)}
|
|
151
156
|
|
|
@@ -161,6 +166,7 @@ const TimeField = ({
|
|
|
161
166
|
error={error}
|
|
162
167
|
describedBy={`${id}-error`}
|
|
163
168
|
disabled={disabled}
|
|
169
|
+
dataTestId={dataTestId ? `${dataTestId}-period` : undefined}
|
|
164
170
|
/>
|
|
165
171
|
</div>
|
|
166
172
|
|
package/src/global/forms.scss
CHANGED
package/src/headers/Hero.scss
CHANGED
package/src/headers/Hero.tsx
CHANGED
|
@@ -37,7 +37,7 @@ const Hero = (props: HeroProps) => {
|
|
|
37
37
|
classNames = "centered"
|
|
38
38
|
}
|
|
39
39
|
return (
|
|
40
|
-
<div className={`hero ${classNames}`} style={styles}>
|
|
40
|
+
<div className={`hero ${classNames}`} style={styles} data-test-id={"hero-component"}>
|
|
41
41
|
<h1 className={`hero__title ${props.extraLargeTitle ? "lg:text-6.5xl" : ""}`}>
|
|
42
42
|
{props.title}
|
|
43
43
|
</h1>
|
|
@@ -46,9 +46,9 @@ const Hero = (props: HeroProps) => {
|
|
|
46
46
|
{props.buttonTitle && props.buttonLink && (
|
|
47
47
|
<>
|
|
48
48
|
{props.secondaryButtonTitle && props.secondaryButtonLink ? (
|
|
49
|
-
<div className="
|
|
49
|
+
<div className="hero__buttons">
|
|
50
50
|
<HeroButton
|
|
51
|
-
className={"md:col-start-
|
|
51
|
+
className={"md:col-start-2 with_secondary"}
|
|
52
52
|
href={props.buttonLink}
|
|
53
53
|
title={props.buttonTitle}
|
|
54
54
|
/>
|
|
@@ -4,7 +4,7 @@ import "./PageHeader.scss"
|
|
|
4
4
|
export interface PageHeaderProps {
|
|
5
5
|
className?: string
|
|
6
6
|
inverse?: boolean
|
|
7
|
-
title
|
|
7
|
+
title?: React.ReactNode
|
|
8
8
|
subtitle?: string
|
|
9
9
|
children?: React.ReactNode
|
|
10
10
|
tabNav?: React.ReactNode
|
|
@@ -26,7 +26,7 @@ const PageHeader = (props: PageHeaderProps) => {
|
|
|
26
26
|
return (
|
|
27
27
|
<header className={classNames.join(" ")}>
|
|
28
28
|
<hgroup className="page-header__group">
|
|
29
|
-
<h1 className="page-header__title">{props.title}</h1>
|
|
29
|
+
{props.title && <h1 className="page-header__title">{props.title}</h1>}
|
|
30
30
|
{props.subtitle && <p className="page-header__lead"> {props.subtitle}</p>}
|
|
31
31
|
{props.children}
|
|
32
32
|
|
|
@@ -322,7 +322,10 @@
|
|
|
322
322
|
.navbar-notice {
|
|
323
323
|
@apply w-full;
|
|
324
324
|
@apply bg-primary;
|
|
325
|
-
@
|
|
325
|
+
@screen md {
|
|
326
|
+
@apply text-right;
|
|
327
|
+
}
|
|
328
|
+
@apply text-left;
|
|
326
329
|
@apply text-white;
|
|
327
330
|
@apply block;
|
|
328
331
|
}
|
|
@@ -338,11 +341,9 @@
|
|
|
338
341
|
.navbar-notice__text {
|
|
339
342
|
@apply max-w-5xl;
|
|
340
343
|
@apply text-sm;
|
|
341
|
-
@apply
|
|
342
|
-
@apply
|
|
343
|
-
@apply pr-3;
|
|
344
|
+
@apply py-2;
|
|
345
|
+
@apply px-3;
|
|
344
346
|
margin: auto;
|
|
345
|
-
height: 36px;
|
|
346
347
|
|
|
347
348
|
a,
|
|
348
349
|
a:hover {
|
package/src/icons/Icon.tsx
CHANGED
|
@@ -133,6 +133,7 @@ export interface IconProps {
|
|
|
133
133
|
symbol: IconTypes
|
|
134
134
|
className?: string
|
|
135
135
|
fill?: string
|
|
136
|
+
ariaHidden?: boolean
|
|
136
137
|
}
|
|
137
138
|
|
|
138
139
|
const Icon = (props: IconProps) => {
|
|
@@ -144,7 +145,7 @@ const Icon = (props: IconProps) => {
|
|
|
144
145
|
const SpecificIcon = IconMap[props.symbol]
|
|
145
146
|
|
|
146
147
|
return (
|
|
147
|
-
<span className={wrapperClasses.join(" ")}>
|
|
148
|
+
<span className={wrapperClasses.join(" ")} aria-hidden={props.ariaHidden}>
|
|
148
149
|
<SpecificIcon fill={props.fill ? props.fill : undefined} />
|
|
149
150
|
</span>
|
|
150
151
|
)
|
package/src/icons/Icons.tsx
CHANGED
|
@@ -474,9 +474,14 @@ export const MailThin = (props: IconProps) => {
|
|
|
474
474
|
fill={props.fill ?? "none"}
|
|
475
475
|
xmlns="http://www.w3.org/2000/svg"
|
|
476
476
|
>
|
|
477
|
-
<rect width="80" height="75" fill="
|
|
477
|
+
<rect width="80" height="75" fill={props.fill ?? "none"} />
|
|
478
478
|
<g clipPath="url(#clip0)">
|
|
479
|
-
<rect
|
|
479
|
+
<rect
|
|
480
|
+
width="1280"
|
|
481
|
+
height="1390"
|
|
482
|
+
transform="translate(-284 -530)"
|
|
483
|
+
fill={props.fill ?? "none"}
|
|
484
|
+
/>
|
|
480
485
|
<path
|
|
481
486
|
d="M61.3749 24.2402L43.2061 39.7424C41.8262 40.8341 39.7563 40.8341 38.3764 39.7424L19.9775 24.2402"
|
|
482
487
|
stroke="black"
|
package/src/locales/es.json
CHANGED
|
@@ -130,10 +130,12 @@
|
|
|
130
130
|
"assistanceUrl": "https://exygy.com/",
|
|
131
131
|
"dontQualifyHeader": "Desafortunadamente, parece que usted no reúne los requisitos de este listado.",
|
|
132
132
|
"dontQualifyInfo": "Por favor haga cambios si usted cree haber cometido algún error. Tenga presente que si usted falsifica cualquier tipo de información en su solicitud será descalificado(a). Si la información que usted ingresó es correcta, lo invitamos a visitarnos en el futuro a medida que otras propiedades están disponibles.",
|
|
133
|
+
"genericSubtitle": "Si se eligiera su solicitud, esté preparado para proporcionar documentación respaldatoria.",
|
|
133
134
|
"addMembers": {
|
|
134
135
|
"addHouseholdMember": "+ Añadir a un miembro del hogar",
|
|
135
136
|
"done": "Ya terminó de añadir personas",
|
|
136
|
-
"title": "Háblenos un poco acerca de su hogar."
|
|
137
|
+
"title": "Háblenos un poco acerca de su hogar.",
|
|
138
|
+
"doubleCheck": "Por favor revise la información de cada miembro del hogar."
|
|
137
139
|
},
|
|
138
140
|
"householdMember": "Miembro del hogar",
|
|
139
141
|
"householdMembers": "Miembros del hogar",
|
|
@@ -145,6 +147,7 @@
|
|
|
145
147
|
"preferredUnit": {
|
|
146
148
|
"preferredUnitType": "Tipo de vivienda preferida",
|
|
147
149
|
"title": "¿Cuáles son los tamaños de vivienda que le interesan?",
|
|
150
|
+
"subTitle": "Aunque los tamaños de las unidades en general se basen en la ocupación, indique el tamaño de unidad que desee para determinar su preferencia en esta oportunidad o establecer una lista de espera (solo por esta oportunidad).",
|
|
148
151
|
"optionsLabel": "Marque todas las opciones que correspondan:",
|
|
149
152
|
"options": {
|
|
150
153
|
"studio": "Estudio",
|
|
@@ -154,6 +157,14 @@
|
|
|
154
157
|
"fourBdrm": "+ de 3 dormitorios"
|
|
155
158
|
}
|
|
156
159
|
},
|
|
160
|
+
"expectingChanges": {
|
|
161
|
+
"title": "Espera cambios en su grupo familiar",
|
|
162
|
+
"question": "¿Espera que haya cambios en su grupo familiar en los próximos 12 meses?"
|
|
163
|
+
},
|
|
164
|
+
"householdStudent": {
|
|
165
|
+
"title": "El grupo familiar incluye un estudiante o miembro que está por cumplir 18 años",
|
|
166
|
+
"question": "¿Alguien de su grupo familiar es estudiante a tiempo completo o cumplirá 18 años en los próximos 60 días?"
|
|
167
|
+
},
|
|
157
168
|
"member": {
|
|
158
169
|
"cancelAddingThisPerson": "Cancelar añadir a esta persona",
|
|
159
170
|
"deleteThisPerson": "Borrar a esta persona",
|
|
@@ -277,7 +288,21 @@
|
|
|
277
288
|
"americanIndianAlaskanNativeAndWhite": "Indígena norteamericano o nativo de Alaska y blanco",
|
|
278
289
|
"asianAndWhite": "Asiático y blanco",
|
|
279
290
|
"blackAfricanAmericanAndWhite": "Negro o afroamericano y blanco",
|
|
280
|
-
"otherMutliracial": "Otro / Multirracial"
|
|
291
|
+
"otherMutliracial": "Otro / Multirracial",
|
|
292
|
+
"asian-otherAsian": "De otro país asiático",
|
|
293
|
+
"asian-chinese": "Chino",
|
|
294
|
+
"asian-asianIndian": "Indio asiático",
|
|
295
|
+
"declineToRespond": "No desea responder",
|
|
296
|
+
"asian-filipino": "Filipino",
|
|
297
|
+
"nativeHawaiianOtherPacificIslander-guamanianOrChamorro": "Guameño o chamorro",
|
|
298
|
+
"asian-japanese": "Japonés",
|
|
299
|
+
"asian-korean": "Coreano",
|
|
300
|
+
"nativeHawaiianOtherPacificIslander-nativeHawaiian": "Nativo hawaiano",
|
|
301
|
+
"otherMultiracial": "Otro/multirracial",
|
|
302
|
+
"nativeHawaiianOtherPacificIslander-otherPacificIslander": "Otro habitante de una isla del Pacífico",
|
|
303
|
+
"nativeHawaiianOtherPacificIslander-samoan": "Samoano",
|
|
304
|
+
"asian-vietnamese": "Vietnamita"
|
|
305
|
+
|
|
281
306
|
},
|
|
282
307
|
"genderOptions": {
|
|
283
308
|
"female": "Mujer",
|
|
@@ -295,7 +320,7 @@
|
|
|
295
320
|
"notListed": "No aparece en la lista"
|
|
296
321
|
},
|
|
297
322
|
"howDidYouHearOptions": {
|
|
298
|
-
"
|
|
323
|
+
"jurisdictionWebsite": "Sitio web del HCD del Condado de Alameda",
|
|
299
324
|
"developerWebsite": "Sitio web del constructor",
|
|
300
325
|
"flyer": "Folleto",
|
|
301
326
|
"emailAlert": "Aviso por email",
|
|
@@ -364,7 +389,22 @@
|
|
|
364
389
|
"signIn": {
|
|
365
390
|
"error": "Hubo un error cuando usted inició sesión",
|
|
366
391
|
"errorGenericMessage": "Por favor inténtelo de nuevo, o comuníquese con servicio al cliente para recibir asistencia.",
|
|
392
|
+
"forgotPassword": "Olvidé la contraseña",
|
|
367
393
|
"success": "¡Bienvenido de nuevo, %{name}!"
|
|
394
|
+
},
|
|
395
|
+
"createAccount": {
|
|
396
|
+
"accountConfirmed": "Su cuenta ha sido confirmada correctamente.",
|
|
397
|
+
"password": "Contraseña",
|
|
398
|
+
"noAccount": "No tienes una cuenta?",
|
|
399
|
+
"anEmailHasBeenSent": "Se ha enviado un email a %{email}",
|
|
400
|
+
"confirmationInstruction": "Por favor haga clic en el enlace del email que le hemos enviado para completar la creación de su cuenta.",
|
|
401
|
+
"confirmationNeeded": "Se necesita confirmación",
|
|
402
|
+
"resendTheEmail": "Volver a enviar el email",
|
|
403
|
+
"reEnterEmail": "Vuelva a introducir la dirección de correo electrónico",
|
|
404
|
+
"passwordInfo": "Debe tener al menos 8 caracteres e incluir al menos 1 letra y al menos un número",
|
|
405
|
+
"reEnterPassword": "Reingresa tu contraseña",
|
|
406
|
+
"mustBe8Chars": "debe tener 8 caracteres",
|
|
407
|
+
"yourName": "Su nombre"
|
|
368
408
|
}
|
|
369
409
|
},
|
|
370
410
|
"errors": {
|
|
@@ -402,7 +442,7 @@
|
|
|
402
442
|
"forGeneralQuestions": "Si requiere información general sobre el programa, nos puede llamar al 000-000-0000.",
|
|
403
443
|
"giveFeedback": "Proporcione sus comentarios",
|
|
404
444
|
"privacyPolicy": "Política de privacidad",
|
|
405
|
-
"copyright": "Demonstration
|
|
445
|
+
"copyright": "Demonstration Jurisdiction © 2021 • Todos los derechos reservados."
|
|
406
446
|
},
|
|
407
447
|
"housingCounselors": {
|
|
408
448
|
"subtitle": "Hable con un asesor de vivienda local en forma específica a sus necesidades.",
|
|
@@ -567,7 +607,8 @@
|
|
|
567
607
|
},
|
|
568
608
|
"nav": {
|
|
569
609
|
"accountSettings": "Configuraciones de la cuenta",
|
|
570
|
-
"browseProperties": "
|
|
610
|
+
"browseProperties": "Buscar Propiedades",
|
|
611
|
+
"getFeedback": "Nos encantaría recibir sus comentarios",
|
|
571
612
|
"getAssistance": "Obtener asistencia",
|
|
572
613
|
"listings": "Listados",
|
|
573
614
|
"properties": "Propiedades",
|
|
@@ -674,6 +715,7 @@
|
|
|
674
715
|
"edit": "Editar",
|
|
675
716
|
"email": "Email",
|
|
676
717
|
"emailAddressPlaceholder": "you@myemail.com",
|
|
718
|
+
"description": "Ingrese descripción",
|
|
677
719
|
"floor": "piso",
|
|
678
720
|
"floors": "pisos",
|
|
679
721
|
"getDirections": "Obtener instrucciones para llegar",
|
|
@@ -702,6 +744,7 @@
|
|
|
702
744
|
"phone": "Teléfono",
|
|
703
745
|
"phoneNumberPlaceholder": "(555) 555-5555",
|
|
704
746
|
"pleaseSelectOne": "Por favor seleccione una opción.",
|
|
747
|
+
"pleaseSelectYesNo": "Elija “sí” o “no”.",
|
|
705
748
|
"preferences": "Preferencias",
|
|
706
749
|
"propertyAmenities": "Servicios en la propiedad",
|
|
707
750
|
"range": "%{from} a %{to}",
|
|
@@ -737,7 +780,11 @@
|
|
|
737
780
|
"seeRentalListings": "Ver viviendas en alquiler",
|
|
738
781
|
"title": "Haga su solicitud de vivienda de precio accesible en",
|
|
739
782
|
"seeMoreOpportunities": "Ver más oportunidades de alquiler y propiedad de vivienda",
|
|
740
|
-
"viewAdditionalHousing": "Vea Oportunidades y recursos adicionales de vivienda"
|
|
783
|
+
"viewAdditionalHousing": "Vea Oportunidades y recursos adicionales de vivienda",
|
|
784
|
+
"seeMoreOpportunitiesTruncated": "Ver más oportunidades y recursos de vivienda",
|
|
785
|
+
"viewAdditionalHousingTruncated": "Ver oportunidades y recursos",
|
|
786
|
+
"signUp": "Reciba correos electrónicos cuando se publique un anuncio nuevo",
|
|
787
|
+
"signUpToday": "Regístrese hoy"
|
|
741
788
|
},
|
|
742
789
|
"whatToExpect": {
|
|
743
790
|
"label": "Lo que puede esperar",
|