generated from StanfordBDHG/NextJSTemplate
-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
# Add Export Health Summary ## ♻️ Current situation & Problem As a clinician, I want to be able to export Health Summary report. ### Code of Conduct & Contributing Guidelines By submitting creating this pull request, you agree to follow our [Code of Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md): - [x] I agree to follow the [Code of Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md).
- Loading branch information
1 parent
465a113
commit aba5cca
Showing
8 changed files
with
167 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// | ||
// This source file is part of the Stanford Biodesign Digital Health ENGAGE-HF open-source project | ||
// | ||
// SPDX-FileCopyrightText: 2023 Stanford University and the project authors (see CONTRIBUTORS.md) | ||
// | ||
// SPDX-License-Identifier: MIT | ||
// | ||
'use client' | ||
import { kebabCase } from 'es-toolkit' | ||
import { Download } from 'lucide-react' | ||
import { useState } from 'react' | ||
import { callables } from '@/modules/firebase/clientApp' | ||
import { type ResourceType } from '@/modules/firebase/utils' | ||
import { Button } from '@/packages/design-system/src/components/Button' | ||
import { toast } from '@/packages/design-system/src/components/Toaster' | ||
import { Tooltip } from '@/packages/design-system/src/components/Tooltip' | ||
import { | ||
base64ToBlob, | ||
downloadFile, | ||
} from '@/packages/design-system/src/utils/file' | ||
|
||
interface GenerateHealthSummaryProps { | ||
userId: string | ||
userName: string | ||
resourceType: ResourceType | ||
} | ||
|
||
export const GenerateHealthSummary = ({ | ||
userId, | ||
resourceType, | ||
userName, | ||
}: GenerateHealthSummaryProps) => { | ||
const [isPending, setIsPending] = useState(false) | ||
|
||
const downloadHealthSummary = async () => { | ||
setIsPending(true) | ||
try { | ||
const exportHealthPromise = callables.exportHealthSummary({ userId }) | ||
toast.promise(exportHealthPromise, { | ||
loading: `Generating health summary for ${userName}...`, | ||
success: `Health summary for ${userName} has been downloaded.`, | ||
error: `Generating health summary for ${userName} failed. Please try later.`, | ||
}) | ||
const response = await exportHealthPromise | ||
const blob = base64ToBlob(response.data.content, 'application/pdf') | ||
downloadFile(blob, `health-summary-${kebabCase(userName)}.pdf`) | ||
} finally { | ||
setIsPending(false) | ||
} | ||
} | ||
|
||
return ( | ||
<Tooltip | ||
open={resourceType === 'invitation' ? undefined : false} | ||
tooltip="This user has not logged in to the application yet" | ||
> | ||
<Button | ||
type="submit" | ||
disabled={resourceType === 'invitation'} | ||
onClick={downloadHealthSummary} | ||
className="disabled:pointer-events-auto" | ||
isPending={isPending} | ||
> | ||
<Download /> | ||
Export Health Summary | ||
</Button> | ||
</Tooltip> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// | ||
// This source file is part of the Stanford Biodesign Digital Health ENGAGE-HF open-source project | ||
// | ||
// SPDX-FileCopyrightText: 2023 Stanford University and the project authors (see CONTRIBUTORS.md) | ||
// | ||
// SPDX-License-Identifier: MIT | ||
// | ||
|
||
export const downloadFile = ( | ||
src: File | Blob | MediaSource, | ||
fileName: string, | ||
) => { | ||
const url = URL.createObjectURL(src) | ||
|
||
const link = document.createElement('a') | ||
link.href = url | ||
link.download = fileName | ||
link.click() | ||
|
||
URL.revokeObjectURL(url) | ||
} | ||
|
||
export const base64ToBlob = ( | ||
base64Data: string, | ||
contentType = '', | ||
sliceSize = 512, | ||
) => { | ||
const byteCharacters = atob(base64Data) | ||
const byteArrays = [] | ||
|
||
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) { | ||
const slice = byteCharacters.slice(offset, offset + sliceSize) | ||
|
||
const byteNumbers = new Array(slice.length) | ||
for (let i = 0; i < slice.length; i++) { | ||
byteNumbers[i] = slice.charCodeAt(i) | ||
} | ||
|
||
const byteArray = new Uint8Array(byteNumbers) | ||
byteArrays.push(byteArray) | ||
} | ||
|
||
return new Blob(byteArrays, { type: contentType }) | ||
} |