Skip to content

Commit

Permalink
feat: export lottery modal (#4176)
Browse files Browse the repository at this point in the history
  • Loading branch information
emilyjablonski authored Jul 3, 2024
1 parent 12f3808 commit 97b1c85
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 12 deletions.
116 changes: 106 additions & 10 deletions sites/partners/__tests__/pages/listings/lottery.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { setupServer } from "msw/node"
import { listing } from "@bloom-housing/shared-helpers/__tests__/testHelpers"
import Lottery from "../../../src/pages/listings/[id]/lottery"
import { mockNextRouter, render } from "../../testUtils"
import { ListingMultiselectQuestion } from "@bloom-housing/shared-helpers/src/types/backend-swagger"

const server = setupServer()

Expand Down Expand Up @@ -207,9 +208,7 @@ describe("lottery", () => {
expect(header).toBeInTheDocument()

expect(getByText("Export lottery data")).toBeInTheDocument()
expect(
getByText("File includes randomized general pool and preference data.")
).toBeInTheDocument()
expect(getByText("File includes randomized general pool data.")).toBeInTheDocument()
expect(getByText("Re-run lottery")).toBeInTheDocument()
expect(getByText("Release lottery")).toBeInTheDocument()
})
Expand All @@ -234,7 +233,7 @@ describe("lottery", () => {
})
)

const { getByText, findByText, findAllByText } = render(
const { getByText, findByText, getAllByText } = render(
<Lottery listing={{ ...listing, lotteryLastRunAt: new Date() }} />
)

Expand All @@ -243,7 +242,7 @@ describe("lottery", () => {

fireEvent.click(getByText("Re-run lottery"))
expect(await findByText("Are you sure?")).toBeInTheDocument()
expect(await findAllByText("Re-run lottery")).toHaveLength(2)
expect(getAllByText("Re-run lottery")).toHaveLength(2)
})

it("should show release modal if user clicks on release", async () => {
Expand Down Expand Up @@ -276,7 +275,7 @@ describe("lottery", () => {
fireEvent.click(getByText("Release lottery"))
expect(await findByText("Are you sure?")).toBeInTheDocument()
expect(
await findByText(
getByText(
"Releasing the lottery will give Partner users access to the lottery data, including the ability to publish results to applicants."
)
).toBeInTheDocument()
Expand Down Expand Up @@ -310,7 +309,7 @@ describe("lottery", () => {
fireEvent.click(getByText("Run lottery"))
expect(await findByText("Confirmation needed")).toBeInTheDocument()
expect(
await findByText("Make sure to add all paper applications before running the lottery.")
getByText("Make sure to add all paper applications before running the lottery.")
).toBeInTheDocument()
})

Expand All @@ -334,14 +333,111 @@ describe("lottery", () => {
})
)

const { getByText, findByText, findAllByText } = render(<Lottery listing={listing} />)
const { getByText, findByText, getAllByText } = render(<Lottery listing={listing} />)

const header = await findByText("Partners Portal")
expect(header).toBeInTheDocument()

fireEvent.click(getByText("Run lottery"))
expect(await findByText("Confirmation needed")).toBeInTheDocument()
expect(await findByText("5 unresolved duplicate sets.")).toBeInTheDocument()
expect(await findAllByText("Run lottery")).toHaveLength(2)
expect(getByText("5 unresolved duplicate sets.")).toBeInTheDocument()
expect(getAllByText("Run lottery")).toHaveLength(2)
})

it("should show export modal if lottery has been run with no preference text", async () => {
mockNextRouter({ id: "Uvbk5qurpB2WI9V6WnNdH" })
document.cookie = "access-token-available=True"
server.use(
rest.get("http://localhost/api/adapter/user", (_req, res, ctx) => {
return res(
ctx.json({
id: "user1",
userRoles: { isAdmin: true },
})
)
}),
rest.post("http://localhost:3100/auth/token", (_req, res, ctx) => {
return res(ctx.json(""))
}),
rest.get("http://localhost/api/adapter/applicationFlaggedSets/meta", (_req, res, ctx) => {
return res(ctx.json({ totalCount: 5, totalPendingCount: 5 }))
})
)

const updatedListing = { ...listing, lotteryLastRunAt: new Date("September 6, 2025 8:15:00") }
const { getByText, findByText, findAllByText, getAllByText } = render(
<Lottery listing={updatedListing} />
)

const header = await findByText("Partners Portal")
expect(header).toBeInTheDocument()

expect(getByText("File includes randomized general pool data.")).toBeInTheDocument()

fireEvent.click(getByText("Export"))
expect(await findAllByText("Export lottery data")).toHaveLength(2)

expect(
getByText("This file includes the lottery raw rank for all applications.", { exact: false })
).toBeInTheDocument()
expect(
getByText("This data was generated from the lottery that was run on 09/06/2025 at 8:15 am.", {
exact: false,
})
).toBeInTheDocument()
expect(getAllByText("Export")).toHaveLength(2)
})

it("should show export modal if lottery has been run with preference text", async () => {
mockNextRouter({ id: "Uvbk5qurpB2WI9V6WnNdH" })
document.cookie = "access-token-available=True"
server.use(
rest.get("http://localhost/api/adapter/user", (_req, res, ctx) => {
return res(
ctx.json({
id: "user1",
userRoles: { isAdmin: true },
})
)
}),
rest.post("http://localhost:3100/auth/token", (_req, res, ctx) => {
return res(ctx.json(""))
}),
rest.get("http://localhost/api/adapter/applicationFlaggedSets/meta", (_req, res, ctx) => {
return res(ctx.json({ totalCount: 5, totalPendingCount: 5 }))
})
)

const updatedListing = {
...listing,
lotteryLastRunAt: new Date("September 6, 2025 8:15:00"),
listingMultiselectQuestions: [{ multiselectQuestions: {} } as ListingMultiselectQuestion],
}
const { getByText, findByText, findAllByText, getAllByText } = render(
<Lottery listing={updatedListing} />
)

const header = await findByText("Partners Portal")
expect(header).toBeInTheDocument()

expect(
getByText("File includes randomized general pool and preference data.")
).toBeInTheDocument()

fireEvent.click(getByText("Export"))
expect(await findAllByText("Export lottery data")).toHaveLength(2)

expect(
getByText(
"This file includes the lottery raw rank and preferences data for all applications.",
{ exact: false }
)
).toBeInTheDocument()
expect(
getByText("This data was generated from the lottery that was run on 09/06/2025 at 8:15 am.", {
exact: false,
})
).toBeInTheDocument()
expect(getAllByText("Export")).toHaveLength(2)
})
})
4 changes: 4 additions & 0 deletions sites/partners/page_content/locale_overrides/general.json
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,11 @@
"listings.lottery.duplicateStringPlural": "%{sets} unresolved duplicate sets.",
"listings.lottery.duplicatesConfirm": "You should resolve any duplicates before running the lottery.",
"listings.lottery.export": "Export lottery data",
"listings.lottery.exportContent": "This file includes the lottery raw rank and preferences data for all applications.",
"listings.lottery.exportContentNoPreferences": "This file includes the lottery raw rank for all applications.",
"listings.lottery.exportContentTimestamp": "This data was generated from the lottery that was run on %{date} at %{time}.",
"listings.lottery.exportFile": "File includes randomized general pool and preference data.",
"listings.lottery.exportFileNoPreferences": "File includes randomized general pool data.",
"listings.lottery.history": "History",
"listings.lottery.noData": "No lottery data",
"listings.lottery.noDataDescription": "It looks like you haven't run a lottery for this listing yet.",
Expand Down
52 changes: 50 additions & 2 deletions sites/partners/src/pages/listings/[id]/lottery.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useState, useContext } from "react"
import Head from "next/head"
import axios from "axios"
import dayjs from "dayjs"
import Ticket from "@heroicons/react/24/solid/TicketIcon"
import Download from "@heroicons/react/24/solid/ArrowDownTrayIcon"
import { t, Breadcrumbs, BreadcrumbLink } from "@bloom-housing/ui-components"
Expand Down Expand Up @@ -32,6 +33,7 @@ const Lottery = (props: { listing: Listing }) => {
const [runModal, setRunModal] = useState(false)
const [reRunModal, setReRunModal] = useState(false)
const [releaseModal, setReleaseModal] = useState(false)
const [exportModal, setExportModal] = useState(false)
const [loading, setLoading] = useState(false)

const { listingsService } = useContext(AuthContext)
Expand Down Expand Up @@ -60,9 +62,13 @@ const Lottery = (props: { listing: Listing }) => {
<Heading priority={2} size={"2xl"}>
{t("listings.lottery.export")}
</Heading>
<div className={styles["card-description"]}>{t("listings.lottery.exportFile")}</div>
<div className={styles["card-description"]}>
{listing.listingMultiselectQuestions.length
? t("listings.lottery.exportFile")
: t("listings.lottery.exportFileNoPreferences")}
</div>
<div>
<Button>{t("t.export")}</Button>
<Button onClick={() => setExportModal(true)}>{t("t.export")}</Button>
</div>
</CardSection>
)
Expand Down Expand Up @@ -330,6 +336,48 @@ const Lottery = (props: { listing: Listing }) => {
</Button>
</Dialog.Footer>
</Dialog>
<Dialog
isOpen={!!exportModal}
ariaLabelledBy="export-lottery-modal-header"
ariaDescribedBy="export-lottery-modal-content"
onClose={() => setExportModal(false)}
>
<Dialog.Header id="export-lottery-modal-header">
{t("listings.lottery.export")}
</Dialog.Header>
<Dialog.Content id="export-lottery-modal-content">
<p>
{listing.listingMultiselectQuestions.length
? t("listings.lottery.exportContent")
: t("listings.lottery.exportContentNoPreferences")}{" "}
{t("listings.lottery.exportContentTimestamp", {
date: dayjs(listing.lotteryLastRunAt).format("MM/DD/YYYY"),
time: dayjs(listing.lotteryLastRunAt).format("h:mm a"),
})}
</p>
</Dialog.Content>
<Dialog.Footer>
<Button
variant="primary"
onClick={() => {
// export lottery
setExportModal(false)
}}
size="sm"
>
{t("t.export")}
</Button>
<Button
variant="primary-outlined"
onClick={() => {
setExportModal(false)
}}
size="sm"
>
{t("t.cancel")}
</Button>
</Dialog.Footer>
</Dialog>
</>
</ListingGuard>
</ListingContext.Provider>
Expand Down

0 comments on commit 97b1c85

Please sign in to comment.