Skip to content
This repository has been archived by the owner on Nov 21, 2024. It is now read-only.

Commit

Permalink
fetching data from an api using a form and displaying the results
Browse files Browse the repository at this point in the history
  • Loading branch information
Courey committed Aug 14, 2023
1 parent b344e16 commit 12871ed
Show file tree
Hide file tree
Showing 3 changed files with 1,248 additions and 0 deletions.
186 changes: 186 additions & 0 deletions app/routes/data.new.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
import type { DataFunctionArgs } from '@remix-run/node'
import { useFetcher } from '@remix-run/react'
import {
Button,
ButtonGroup,
FormGroup,
Grid,
GridContainer,
Icon,
Label,
Select,
TextInput,
} from '@trussworks/react-uswds'
import { useState } from 'react'

import { getInstrumentData } from './data/data.server'
import { tableOptions } from './data/data.table-options'

function validateResultCountInput(input: string) {
const numericalInput = parseFloat(input)
return numericalInput.toString() === input && numericalInput <= 100
}

export async function action({ request }: DataFunctionArgs) {
const data = await request.formData()
const format = data.get('format')?.toString()
const resultCount = data.get('resultCount')?.toString()
const instrument = data.get('instrument')?.toString()
const ra = data.get('ra')?.toString()
const dec = data.get('dec')?.toString()
const radius = data.get('radius')?.toString()

if (!instrument || !format || !resultCount || !ra || !dec || !radius)
return null
const res = await getInstrumentData(
instrument,
format,
parseInt(resultCount),
parseFloat(ra),
parseFloat(dec),
parseInt(radius)
)
return res
}

export default function () {
const [instrument, setInstrument] = useState('')
const [format, setFormat] = useState('')
const [ra, setRa] = useState('')
const [dec, setDec] = useState('')
const [radius, setRadius] = useState('')
const [resultCount, setResultCount] = useState('')
const isValid = validateResultCountInput(resultCount)

const fetcher = useFetcher()
const results = fetcher.data
const resultArray = results?.request || ['no results']

const shouldDisableForm =
!instrument || !format || !resultCount || !isValid || !ra || !dec || !radius

return (
<div>
<h1 className="text-center">Instrument Data Form</h1>
<GridContainer>
<Grid row>
<Grid tablet={{ col: true }} className="bg-base-lightest">
<h2 className="text-center">Get data by instrument</h2>
<fetcher.Form method="POST" className="margin-2">
<input hidden name="intent" defaultValue="get-data" />
<Label htmlFor="instruments">Choose Instrument</Label>
<Select
id="instrument"
name="instrument"
value={instrument}
onChange={(e) => {
setInstrument(e.target.value)
}}
>
<option value="">Select instrument</option>
{tableOptions.map((x) => (
<option key={x} value={x}>
{x}
</option>
))}
</Select>
<ButtonGroup className="margin-top-2">
<Label htmlFor="ra">RA:</Label>
<TextInput
type="text"
id="ra"
name="ra"
placeholder="0"
className="width-10 margin-right-5"
onChange={(e) => {
setRa(e.target.value)
}}
></TextInput>
<Label htmlFor="dec">DEC:</Label>
<TextInput
type="text"
id="dec"
name="dec"
placeholder="0"
className="width-10"
onChange={(e) => {
setDec(e.target.value)
}}
></TextInput>
</ButtonGroup>
<Label htmlFor="radius">Radius (arcmin)</Label>
<TextInput
type="text"
id="radius"
name="radius"
placeholder="0"
className="width-10"
onChange={(e) => {
setRadius(e.target.value)
}}
></TextInput>
<Label htmlFor="format">Choose result format</Label>
<Select
id="format"
name="format"
value={format}
onChange={(e) => {
setFormat(e.target.value)
}}
>
<option value="">Select format</option>
<option value="json">json</option>
<option value="txt">txt</option>
</Select>
<Label htmlFor="resultCount">Result Count</Label>
<TextInput
type="text"
id="resultCount"
name="resultCount"
placeholder="0-100"
className="width-10"
onChange={(e) => {
setResultCount(e.target.value)
}}
></TextInput>
<FormGroup>
<Button type="submit" disabled={shouldDisableForm}>
Submit
</Button>

{fetcher.state !== 'idle' && (
<>
<Icon.Autorenew className="text-middle" /> Loading...
</>
)}
{fetcher.state === 'idle' &&
fetcher.data === null &&
!shouldDisableForm && (
<>
<Icon.Check className="text-middle" color="green" /> Saved
</>
)}
</FormGroup>
</fetcher.Form>
</Grid>
</Grid>
<hr></hr>
<Grid row>
<Grid
tablet={{ col: true }}
className="bg-primary-lighter margin-bottom-5"
>
<h2 className="margin-left-2">Results</h2>
{resultArray.map((x: object, index: number) => {
return (
<GridContainer key={index} className="margin-bottom-2">
{JSON.stringify(x, null, 2)}
</GridContainer>
)
})}
</Grid>
</Grid>
</GridContainer>
</div>
)
}
53 changes: 53 additions & 0 deletions app/routes/data/data.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
async function fetchData(
instrument: string,
format: string,
resultCount: number,
ra: number,
dec: number,
radius: number
) {
const heasarc_api_url = 'https://heasarc.gsfc.nasa.gov/xamin/QueryServlet'
const formData = new FormData()

formData.append('table', instrument)
formData.append('format', format)
formData.append('resultmax', resultCount.toString())
formData.append('radius', radius.toString())
formData.append('position[]', ra.toString())
formData.append('position[]', dec.toString())

try {
const response = await fetch(heasarc_api_url, {
method: 'POST',
body: formData,
})
const data =
format === 'json' ? await response.json() : await response.text()
return data
} catch (error) {
console.log(error)
}
}

export async function getInstrumentData(
instrument: string,
format: string,
resultCount: number,
ra: number,
dec: number,
radius: number
) {
try {
const response = await fetchData(
instrument,
format,
resultCount,
ra,
dec,
radius
)
return response
} catch (error) {
console.log(error)
}
}
Loading

0 comments on commit 12871ed

Please sign in to comment.