Skip to content
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
b9e2d24
feat: init refactor and documents page
cliu02 Apr 8, 2026
a9a089a
feat: cleanup
cliu02 Apr 8, 2026
04cc54e
feat: update routing
cliu02 Apr 8, 2026
d6584a7
chore: old token
cliu02 Apr 9, 2026
de09189
test: tests
cliu02 Apr 9, 2026
e96ce0a
chore: more refactors
cliu02 Apr 9, 2026
f114d1a
chore: cleanup
cliu02 Apr 9, 2026
38a1938
chore: cleanup and placeholder
cliu02 Apr 9, 2026
778c99a
chore: cleanup
cliu02 Apr 9, 2026
91c94b7
chore: cleanup
cliu02 Apr 9, 2026
e8d2d29
chore: renaming
cliu02 Apr 9, 2026
6527593
chore: main merge conflict
cliu02 Apr 9, 2026
2637ab7
fix: backwards compatible
cliu02 Apr 9, 2026
a076d5e
feat: update record response
cliu02 Apr 9, 2026
69e6f79
chore: cleanup
cliu02 Apr 9, 2026
7b3c7f4
chore: refactor
cliu02 Apr 9, 2026
4731ffb
fix: old email param
cliu02 Apr 9, 2026
59c91a7
test: update tests
cliu02 Apr 9, 2026
03ecf9f
test: update tests
cliu02 Apr 9, 2026
2100d8a
Merge branch 'main' into DAH-4006-i2i-next-steps
cliu02 Apr 13, 2026
0dce7be
feat: next steps page
cliu02 Apr 15, 2026
32b16be
chore: refactor
cliu02 Apr 15, 2026
bfe2f69
Merge branch 'main' into DAH-4006-i2i-next-steps
cliu02 Apr 15, 2026
27bac01
feat: use scheduling url
cliu02 Apr 15, 2026
7446e9c
chore: refactor and fallbacks
cliu02 Apr 15, 2026
10629cc
Merge branch 'main' into DAH-4006-i2i-next-steps
cliu02 Apr 15, 2026
789a7c0
fix: merge conflict
cliu02 Apr 15, 2026
fb7aa2c
test: add test
cliu02 Apr 15, 2026
0b2cff3
feat: response pages
cliu02 Apr 16, 2026
78a446a
Merge branch 'main' into DAH-4037-i2i-response
cliu02 Apr 20, 2026
2f2fa3f
chore: cleanup
cliu02 Apr 20, 2026
9876c34
chore: cleanup
cliu02 Apr 20, 2026
55c2047
fix: merge conflict
cliu02 Apr 20, 2026
23ace8b
fix: merge conflict
cliu02 Apr 20, 2026
63111e1
chore: updated token
cliu02 Apr 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/assets/json/translations/react/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -903,7 +903,7 @@
"inviteToInterviewPage.leasingAgent.p2": "We sent you an email confirming your answer. Follow the link in your email if you need to change it.",
"inviteToInterviewPage.leasingAgent.p3": "Or, contact the leasing agent:",
"inviteToInterviewPage.submitYourInfo.deadline": "%{day} at 11:59 pm Pacific Time",
"inviteToInterviewPage.submitYourInfo.deadlineInfo": "<strong>The deadline to schedule your appointment has passed:</strong> %{day} at 11:59 pm Pacific Time. If you are still interested in an apartment at %{listingName}, contact the leasing agent.",
"inviteToInterviewPage.submitYourInfo.deadlineInfo": "<strong>The deadline to schedule your appointment has passed:</strong> %{day} at 11:59 pm Pacific Time.\n\nIf you are still interested in an apartment at %{listingName}, contact the leasing agent.",
"inviteToInterviewPage.submitYourInfo.deadlinePassed": "The deadline to schedule your appointment has passed: ",
"inviteToInterviewPage.submitYourInfo.prepare.p1": "If you already work with a housing counselor, contact them for help with your application.",
"inviteToInterviewPage.submitYourInfo.prepare.p2": "Otherwise, <a target='_blank' href='https://www.homesanfrancisco.org'>HomeSF</a> can connect you with someone who can help.",
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/api/v1/invite_to_response_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def record_response
"action=#{action}",
)
else
DahliaBackend::MessageService.send_invite_to_response(
DahliaBackend::MessageService.send_invite_to_apply_response(
deadline,
application_id,
application_number,
Expand Down
33 changes: 17 additions & 16 deletions app/controllers/invite_to_controller.rb
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
# Invite to X controller
class InviteToController < ApplicationController
def index
decoded_params = decode_token(params[:t])
if decoded_params.is_a?(String)
redirect_to decoded_params
return
end
# TODO: uncomment when backend token updated
# decoded_params = decode_token(params[:t])
# if decoded_params.is_a?(String)
# redirect_to decoded_params
# return
# end
decoded_params ||= params
Comment thread
cliu02 marked this conversation as resolved.
Outdated
@invite_to_props = props(decoded_params)
# Get file upload URL for application
if decoded_params['appId'].present?
application = Force::ShortFormService.get(decoded_params['appId'])
@invite_to_props = @invite_to_props.merge(
fileUploadUrl: application['uploadURL'],
url: application['uploadURL'],
)
end
if decoded_params['applicationNumber'].present?
application = Force::ShortFormService.get(decoded_params['applicationNumber'])
@invite_to_props = @invite_to_props.merge(
fileUploadUrl: application['uploadURL'],
url: application['uploadURL'],
)
end
record_response(decoded_params)
Expand All @@ -37,31 +38,31 @@ def props(decoded_params = params)
url_params = {
type: decoded_params['type'],
deadline: decoded_params['deadline'],
action: decoded_params['action'] || decoded_params['response'],
inviteAction: decoded_params['inviteAction'] || decoded_params['response'],
appId: decoded_params['appId'] || decoded_params['applicationNumber'],
}

{
assetPaths: static_asset_paths,
urlParams: url_params,
submitPreviewLinkTokenParam: encode_token(url_params.except(:action, :response)),
submitPreviewLinkTokenParam: encode_token(url_params.except(:inviteAction, :response)),
}.compact
end

def record_response(decoded_params)
deadline = decoded_params['deadline']
response = decoded_params['response']
application_number = decoded_params['applicationNumber']
action = decoded_params['action']
invite_action = decoded_params['inviteAction']
app_id = decoded_params['appId']

if (action.blank? && response.blank?) || (deadline && deadline_has_passed?(deadline)) || language_change?
if (invite_action.blank? && response.blank?) || (deadline && deadline_has_passed?(deadline)) || language_change?
Rails.logger.info(
'InviteToController#record_response: *NOT* recording ' \
"deadline=#{deadline}, " \
"app_id=#{app_id}, " \
"application_number=#{application_number}, " \
"action=#{action.inspect}, " \
"inviteAction=#{invite_action.inspect}, " \
"response=#{response.inspect}",
)
return
Expand All @@ -72,16 +73,16 @@ def record_response(decoded_params)
"deadline=#{deadline}, " \
"app_id=#{app_id}, " \
"application_number=#{application_number}, " \
"action=#{action}, " \
"inviteAction=#{invite_action}, " \
"response=#{response}",
)

DahliaBackend::MessageService.send_invite_to_response(
DahliaBackend::MessageService.send_invite_to_apply_response(
deadline,
app_id,
application_number,
response,
action,
invite_action,
params['id'], # listing_id
)
end
Expand All @@ -99,7 +100,7 @@ def decode_token(token)
# "data" => {
# "type" => "I2I",
# "deadline" => "1999-12-31",
# "action" => "yes",
# "inviteAction" => "yes",
# "appId" => "12345678"
# },
# "iat" => 946512000
Expand Down
7 changes: 4 additions & 3 deletions app/javascript/__tests__/api/inviteToApplyApiService.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { post } from "../../api/apiService"
import { recordResponse } from "../../api/inviteToApplyApiService"
import { recordResponse } from "../../api/inviteToApiService"
import { INVITE_TO_X } from "../../modules/constants"

jest.mock("../../api/apiService", () => ({
post: jest.fn(),
}))

describe("inviteToApplyApiService", () => {
describe("inviteToApiService", () => {
describe("recordResponse", () => {
Comment thread
cliu02 marked this conversation as resolved.
it("calls apiService post", async () => {
post as jest.Mock
Expand All @@ -16,7 +17,7 @@ describe("inviteToApplyApiService", () => {
deadline: "2099-01-01",
action: "submit",
response: "submit",
type: "I2A",
type: INVITE_TO_X.APPLY,
}
await recordResponse(record)
expect(post).toHaveBeenCalled()
Expand Down
43 changes: 22 additions & 21 deletions app/javascript/__tests__/pages/invite-to-apply.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ import InviteToPage from "../../pages/inviteTo/invite-to"
import { renderAndLoadAsync } from "../__util__/renderUtils"
import { localizedFormat } from "../../util/languageUtil"
import { getListing } from "../../api/listingApiService"
import { recordResponse } from "../../api/inviteToApplyApiService"
import { recordResponse } from "../../api/inviteToApiService"
import { ConfigContext } from "../../lib/ConfigContext"
import { INVITE_TO_X } from "../../modules/constants"

jest.mock("../../api/listingApiService")
jest.mock("../../api/inviteToApplyApiService", () => ({
jest.mock("../../api/inviteToApiService", () => ({
recordResponse: jest.fn(),
}))
jest.mock("../../hooks/useFeatureFlag", () => ({
Expand Down Expand Up @@ -98,8 +99,8 @@ describe("Invite to Apply", () => {
<InviteToPage
assetPaths={"/"}
urlParams={{
type: "I2A",
action: "contact",
type: INVITE_TO_X.APPLY,
inviteAction: "contact",
deadline: mockPastDeadline,
}}
/>
Expand All @@ -117,14 +118,14 @@ describe("Invite to Apply", () => {
<InviteToPage
assetPaths={"/"}
urlParams={{
type: "I2A",
type: INVITE_TO_X.APPLY,
deadline: mockFutureDeadline,
action: "no",
inviteAction: "no",
appId: "0000",
}}
/>
)
const submitPreviewLink = `/en/listings/${mockListing.Id}/next-steps?appId=0000&deadline=${mockFutureDeadline}`
const submitPreviewLink = `/en/listings/${mockListing.Id}/next-steps?appId=0000&deadline=${mockFutureDeadline}&type=I2A`

expect(screen.getByText(t("inviteToApplyPage.withdrawn.title"))).toBeInTheDocument()
expect(screen.getByText(mockListing.Building_Name_for_Process)).toBeInTheDocument()
Expand All @@ -145,15 +146,15 @@ describe("Invite to Apply", () => {
<InviteToPage
assetPaths={"/"}
urlParams={{
type: "I2A",
type: INVITE_TO_X.APPLY,
deadline: mockFutureDeadline,
action: "contact",
inviteAction: "contact",
appId: "0000",
}}
/>
)

const submitPreviewLink = `/en/listings/${mockListing.Id}/next-steps?appId=0000&deadline=${mockFutureDeadline}`
const submitPreviewLink = `/en/listings/${mockListing.Id}/next-steps?appId=0000&deadline=${mockFutureDeadline}&type=I2A`

expect(
screen.getByText(
Expand Down Expand Up @@ -182,9 +183,9 @@ describe("Invite to Apply", () => {
<InviteToPage
assetPaths={"/"}
urlParams={{
type: "I2A",
type: INVITE_TO_X.APPLY,
deadline: mockPastDeadline,
action: "yes",
inviteAction: "yes",
appId: "0000",
}}
/>
Expand All @@ -197,9 +198,9 @@ describe("Invite to Apply", () => {
<InviteToPage
assetPaths={"/"}
urlParams={{
type: "I2A",
type: INVITE_TO_X.APPLY,
deadline: mockFutureDeadline,
action: "yes",
inviteAction: "yes",
}}
/>
)
Expand All @@ -217,9 +218,9 @@ describe("Invite to Apply", () => {
<InviteToPage
assetPaths={"/"}
urlParams={{
type: "I2A",
type: INVITE_TO_X.APPLY,
deadline: mockFutureDeadline,
action: "yes",
inviteAction: "yes",
appId: "a0o123",
}}
/>
Expand All @@ -242,9 +243,9 @@ describe("Invite to Apply", () => {
<InviteToPage
assetPaths={"/"}
urlParams={{
type: "I2A",
type: INVITE_TO_X.APPLY,
deadline: mockFutureDeadline,
action: "yes",
inviteAction: "yes",
appId: "a0o123",
}}
/>
Expand All @@ -264,9 +265,9 @@ describe("Invite to Apply", () => {
<InviteToPage
assetPaths={"/"}
urlParams={{
type: "I2A",
type: INVITE_TO_X.APPLY,
deadline: mockFutureDeadline,
action: "yes",
inviteAction: "yes",
}}
/>
)
Expand All @@ -285,7 +286,7 @@ describe("Invite to Apply", () => {
assetPaths={"/"}
documentsPath={true}
urlParams={{
type: "I2A",
type: INVITE_TO_X.APPLY,
}}
/>
)
Expand Down
Loading
Loading