diff --git a/app.arc b/app.arc index 22e3266..949f7c7 100644 --- a/app.arc +++ b/app.arc @@ -18,3 +18,9 @@ plugin-remix runtime nodejs18.x region us-east-1 architecture arm64 + +@tables +notes + userId *String + noteId **String + PointInTimeRecovery true \ No newline at end of file diff --git a/app/lib/utils.ts b/app/lib/utils.ts new file mode 100644 index 0000000..711ac64 --- /dev/null +++ b/app/lib/utils.ts @@ -0,0 +1,6 @@ +// This is just for example. Typically you would get a user from the session. +// By making it reusable, you would only have to get the userId from the session +// in one place. This makes it portable. +export function getUserId() { + return 'test' +} diff --git a/app/root.tsx b/app/root.tsx index c6e1aa3..22f5685 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -4,11 +4,12 @@ import { Links, LiveReload, Meta, + NavLink, Outlet, Scripts, ScrollRestoration, } from '@remix-run/react' -import { GovBanner, GridContainer } from '@trussworks/react-uswds' +import { GovBanner, GridContainer, PrimaryNav } from '@trussworks/react-uswds' import theme from './theme.css' import favicon_16 from '~/../node_modules/@uswds/uswds/dist/img/favicons/favicon-16.png' @@ -51,6 +52,17 @@ export default function App() { + + Data + , + + Home + , + ]} + > Skip to main content diff --git a/app/routes/data._index.tsx b/app/routes/data._index.tsx new file mode 100644 index 0000000..64064d6 --- /dev/null +++ b/app/routes/data._index.tsx @@ -0,0 +1,14 @@ +import { Link } from '@remix-run/react' + +export default function () { + return ( +
+

Instrument Data

+
+ + New Data Gathering Session + +
+
+ ) +} diff --git a/app/routes/data.new.tsx b/app/routes/data.new.tsx new file mode 100644 index 0000000..6f14bb6 --- /dev/null +++ b/app/routes/data.new.tsx @@ -0,0 +1,270 @@ +import type { DataFunctionArgs } from '@remix-run/node' +import { Link, useFetcher, useLoaderData } from '@remix-run/react' +import { + Button, + ButtonGroup, + FormGroup, + Grid, + GridContainer, + Icon, + Label, + Select, + TextInput, + Textarea, +} from '@trussworks/react-uswds' +import { getUserId } from 'app/lib/utils' +import { useEffect, useRef, useState } from 'react' + +import { createNewNote, getInstrumentData, getNotes } 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 loader({ request }: DataFunctionArgs) { + const userID = getUserId() + return await getNotes(userID) +} + +export async function action({ request }: DataFunctionArgs) { + const userID = getUserId() + const data = await request.formData() + const intent = data.get('intent')?.toString() + + if (intent === 'get-data') { + 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 + } else if (intent === 'new-note') { + const noteTitle = data.get('title')?.toString() + const noteBody = data.get('notes')?.toString() + if (!noteBody || !noteTitle) { + return null + } + await createNewNote(noteTitle, noteBody, userID) + + return null + } else { + return null + } +} + +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 [noteTitle, setNoteTitle] = useState('') + const [noteBody, setNoteBody] = useState('') + + const noteRef = useRef(null) + + const fetcher = useFetcher() + const results = fetcher.data + const fetchNotes = useFetcher() + const notes = useLoaderData() + const resultArray = results?.request || ['no results'] + + const shouldDisableForm = + !instrument || !format || !resultCount || !isValid || !ra || !dec || !radius + const shouldDisableNotes = !noteTitle || !noteBody + + useEffect(() => { + if ( + fetchNotes.state === 'idle' && + fetchNotes.data === null && + noteRef.current + ) { + noteRef.current.reset() + } + }, [fetchNotes.state, fetchNotes.data]) + + return ( +
+

Instrument Data Form

+ + + +

Get data by instrument

+ + + + + + + { + setRa(e.target.value) + }} + > + + { + setDec(e.target.value) + }} + > + + + { + setRadius(e.target.value) + }} + > + + + + { + setResultCount(e.target.value) + }} + > + + + + {fetcher.state !== 'idle' && ( + <> + Loading... + + )} + {fetcher.state === 'idle' && + fetcher.data === null && + !shouldDisableForm && ( + <> + Saved + + )} + + +
+ +

Take Notes:

+ + + + { + setNoteTitle(e.target.value) + }} + /> + +