-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Upgrade VZE to NextJS #1603
base: main
Are you sure you want to change the base?
Upgrade VZE to NextJS #1603
Changes from 117 commits
9e7ffa3
e731950
71464da
2272b7e
a09871d
f28ce2f
bc16472
94966f4
035d93a
454085b
242cda8
185c1fb
fc08cea
f023519
08212bf
42f92e0
03bc761
d3965d4
437068a
f666430
e229f56
2d1434d
ee0dab3
1cbe9ed
d156c03
c6f1f81
030fe41
910c3a1
29985c5
efffdc3
fd8bf16
c0f66ce
539495c
ce6a103
48f98a9
d07cc5d
e05addb
b479ad4
391bf93
a77c9b9
c9783d0
8d66933
63d1002
6381c73
4dc3b7a
5ee09ed
a388f32
0da3968
dc9a4f3
574f0ad
7dc9b42
125f43e
5bfef1e
7ddad28
204d5a7
61e31e4
5bc9963
c79539b
31ad3ed
0ab87a8
cbd2b7a
c23a872
1ebec6b
171495e
f14c8eb
1f6cb50
5d2147a
b74551d
bf5d208
e3fa945
f6df240
2fe9618
a655045
37ce3e6
7386d24
7e95be2
b5b4150
eb53433
6cf2a79
5f034cf
7b75854
2bffc04
36b9a3b
70d3cfa
6208281
787afa2
36ac568
26a9adc
7df4148
9c1e0d0
c948cb5
1a5bb41
27607c3
d12c826
92dc536
af42415
b01d5b3
2195d11
f1df966
518865d
c323530
c0dcd26
c494c2b
e5d4e2e
204b5ba
50bc377
ad5a72f
579102a
475503f
7c9bb3f
8c22853
f16ea66
08e0c01
e26566c
23b70bf
58fa664
cb77ffe
1ff86bb
b35be44
1a34085
78296f0
36b62b9
f5cd9b8
f27e25e
f23bdd5
dec6d2d
a24ab74
5333278
518a105
1760424
c4ddb9c
6499660
be3ee0b
18ec9e5
e2b41c1
3f0987a
ea32049
2b63a42
145f17a
ca6e6ca
1f8cd7b
fa0c815
3266471
322ef40
4ab657e
a57c6da
5635178
834ab9d
febf56d
e6bba53
f8d5152
5a95612
7ada08c
ed10690
e6aca7e
ed1774e
d2e4209
bf76fd5
61c1b7e
7623385
394fd20
0a0497f
bab9eff
c11b93d
4a3abde
f1193d8
fec2cfb
f8d7fca
104cc22
c2247d4
aae565b
7d91417
cb6677e
01e469d
cc05b0b
3eaf933
be440a9
764ecb0
a48ed2e
f24daed
2d02adf
130689d
695ee94
dcd9cbb
74c328c
7e970c5
f2527f8
3bb09a5
7be5b16
9f66bfa
7e598be
dd63ae9
c0f0bf9
c83b760
0182878
0af2d68
5561b07
0055aec
a229738
23d84ef
80c85a3
c8746a4
10bd43a
b95ecd8
6831d1e
0de6f83
184b9b8
79428de
852acdb
057bd97
bcd7a8f
ec4b1b8
353aa3e
53292a2
a194d16
24e3439
7fbb22b
2974dca
6ba0315
c41e404
2b784d9
5092a6b
b732c64
d6a6314
9b5aa2f
1434926
ab65525
aacee8d
88577f3
91b26c0
24ea67e
49a7017
f6952c3
fae9da1
83567ff
7ff577d
136e4e3
54c162e
97ed824
706e226
db29ede
9b736ec
2625576
daeec62
e5a78a2
e4c4c8c
f62c10f
d5727c0
9aaf89a
a72a20d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"extends": ["next/core-web-vitals", "next/typescript"] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
.yarn/install-state.gz | ||
|
||
# testing | ||
/coverage | ||
|
||
# next.js | ||
/.next/ | ||
/out/ | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# local env files | ||
.env*.local | ||
|
||
# vercel | ||
.vercel | ||
|
||
# typescript | ||
*.tsbuildinfo | ||
next-env.d.ts |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
20 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
**This** is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). | ||
|
||
## Quick start | ||
|
||
1. Start your database and graphql engine | ||
|
||
2. Use the `env_template` to configure the local environment variables. These can be copied from your existing VZE `.env` file, by replacing `REACT_APP_` with `NEXT_PUBLIC_` in the variable name: | ||
|
||
```shell | ||
# run this cmd and then edit .env.local as needed | ||
cp -n env_template .env.local | ||
``` | ||
|
||
3. Activate your `node` environment (`v20` is required): | ||
|
||
```shell | ||
nvm use | ||
``` | ||
|
||
4. Install node packages | ||
|
||
``` | ||
npm install | ||
``` | ||
|
||
5. Start the development server | ||
|
||
```shell | ||
npm run dev | ||
``` | ||
|
||
6. Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. | ||
|
||
## This app vs the old VZE | ||
|
||
- Create-React-App ➡️ NextJS | ||
- Javascript ➡️ Typescript | ||
- CoreUI + reactstrap ➡️ react-bootstrap | ||
- Apollo Client ➡️ SWR + graphql-request | ||
|
||
## Working features | ||
|
||
- Crashes list | ||
- filter by preset date range | ||
- filter by custom date range | ||
- filter using search input and selecting a field to search on | ||
- reset filters | ||
- filters are preserved (in local storage) when refreshing the page or navigating back to it | ||
- advanced search filter menu toggle shows a badge with how many fitlers are applied | ||
- expandable filter toggle menu with working filter switch groups | ||
- paginate through search results | ||
- loading spinner apperas in pagination controls when fetching data | ||
- sortable table columns with icon indicating sort direction | ||
- Crash details page | ||
- Crash map: crash map displays crash location with nearmap aerials | ||
- Crash map: ability to edit crash location | ||
- Crash diagram: diagrams render | ||
- Crash diagram: info alert shows when no diagram is available and is temp record | ||
- Crash diagram: danger alert shows when no diagram is available and is not temp record | ||
- Crash narrative: loads normally and is scrollable for long narratives | ||
- Crash data card: click field to edit | ||
- Crash data card: cannot save unless field is edited | ||
- Crash data card: use cancel button to exit edit mode and restore initial value | ||
- Crash data card: use `enter` key to save edits | ||
- Crash data card: edit a field with lookup values | ||
- Crash data card: edit a text input | ||
- Crash data card: edit a number input | ||
- Crash data card: nullify a value (e.g. street name) by clearing its input and saving it | ||
- Related records - units: click field to edit it | ||
- Related records - people: todo | ||
- Related records - chargs: todo | ||
- Change log: change log works normally with details modal. But it is not collapseable (yet). | ||
- Sidebar | ||
- is exapandable and open/closed state is preserved in localstorage | ||
|
||
|
||
## Todo | ||
|
||
- permissions-based features: | ||
- side nav | ||
- field editing | ||
- etc. see <Can/> component from VZE | ||
- crash details | ||
- crash injury widgets | ||
- swap addresses | ||
- people table | ||
- name edit component | ||
- charges table | ||
- notes | ||
- recommendations | ||
- misc column editing + placement | ||
- Crash map: show coordinates and enable editing by tying into input | ||
- crash diagram: zoom/tilt control | ||
- Change log: collapseable | ||
- table | ||
- advanced filters: test them and add "Other" unit type filter | ||
- export | ||
- record counts | ||
- Top nav component | ||
- app logo | ||
- navigration crash search | ||
- profile menu with signout | ||
- locations | ||
- location details | ||
- create crash record | ||
- upload non-cr3 | ||
- dashboard | ||
|
||
- users | ||
- user list | ||
- add/edit/delete uers | ||
- copy user emails | ||
- login page: make it look nice | ||
- versioned localstorage | ||
- error boundary (see Moped's for reference) | ||
- map geocoder (technically an enhancement vis a vis current state) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
"use client"; | ||
import { useCallback } from "react"; | ||
import Row from "react-bootstrap/Row"; | ||
import Col from "react-bootstrap/Col"; | ||
import Card from "react-bootstrap/Card"; | ||
import CrashMapCard from "@/components/CrashMapCard"; | ||
import { GET_CRASH, UPDATE_CRASH } from "@/queries/crash"; | ||
import { UPDATE_UNIT } from "@/queries/unit"; | ||
import { useQuery } from "@/utils/graphql"; | ||
import AppBreadCrumb from "@/components/AppBreadCrumb"; | ||
import CrashHeader from "@/components/CrashHeader"; | ||
import CrashDiagramCard from "@/components/CrashDiagramCard"; | ||
import DataCard from "@/components/DataCard"; | ||
import RelatedRecordTable from "@/components/RelatedRecordTable"; | ||
import ChangeLog from "@/components/ChangeLog"; | ||
import { crashDataCards } from "@/configs/crashDataCard"; | ||
import { unitRelatedRecordCols } from "@/configs/unitRelatedRecordTable"; | ||
import { Crash } from "@/types/types"; | ||
|
||
export default function CrashDetailsPage({ | ||
params, | ||
}: { | ||
params: { record_locator: string }; | ||
}) { | ||
const recordLocator = params.record_locator; | ||
|
||
const { data, refetch, isValidating } = useQuery<{ | ||
crashes: Crash[]; | ||
}>({ | ||
query: recordLocator ? GET_CRASH : null, | ||
variables: { recordLocator }, | ||
}); | ||
|
||
const onSaveCallback = useCallback(async () => { | ||
await refetch(); | ||
}, [refetch]); | ||
|
||
if (!data || !data?.crashes?.[0]) { | ||
// todo: 404 page | ||
// todo: loading spinner (would be nice to use a spinner inside cards) | ||
return; | ||
} | ||
|
||
const crash = data.crashes[0]; | ||
|
||
return ( | ||
<> | ||
<AppBreadCrumb /> | ||
<CrashHeader crash={crash} /> | ||
<Row> | ||
<Col sm={12} md={6} lg={4} className="mb-3"> | ||
<CrashMapCard | ||
savedLatitude={crash.latitude} | ||
savedLongitude={crash.longitude} | ||
crashId={crash.id} | ||
onSaveCallback={onSaveCallback} | ||
mutation={UPDATE_CRASH} | ||
/> | ||
</Col> | ||
<Col sm={12} md={6} lg={4} className="mb-3"> | ||
<CrashDiagramCard crash={crash} /> | ||
</Col> | ||
<Col sm={12} md={6} lg={4} className="mb-3"> | ||
<Card> | ||
<Card.Header>Narrative</Card.Header> | ||
<Card.Body className="crash-header-card-body"> | ||
<Card.Text>{crash.investigator_narrative || ""}</Card.Text> | ||
</Card.Body> | ||
</Card> | ||
</Col> | ||
</Row> | ||
<Row> | ||
<Col sm={12} md={6} lg={4} className="mb-3"> | ||
<DataCard<Crash> | ||
record={crash} | ||
isValidating={isValidating} | ||
title="Summary" | ||
columns={crashDataCards.summary} | ||
mutation={UPDATE_CRASH} | ||
onSaveCallback={onSaveCallback} | ||
/> | ||
</Col> | ||
<Col sm={12} md={6} lg={4} className="mb-3"> | ||
<DataCard<Crash> | ||
record={crash} | ||
isValidating={isValidating} | ||
title="Flags" | ||
columns={crashDataCards.flags} | ||
mutation={UPDATE_CRASH} | ||
onSaveCallback={onSaveCallback} | ||
/> | ||
</Col> | ||
<Col sm={12} md={6} lg={4} className="mb-3"> | ||
<DataCard<Crash> | ||
record={crash} | ||
isValidating={isValidating} | ||
title="Other" | ||
columns={crashDataCards.other} | ||
mutation={UPDATE_CRASH} | ||
onSaveCallback={onSaveCallback} | ||
/> | ||
</Col> | ||
</Row> | ||
<Row> | ||
<Col sm={12} md={6} lg={4} className="mb-3"> | ||
<DataCard<Crash> | ||
record={crash} | ||
isValidating={isValidating} | ||
title="Primary address" | ||
columns={crashDataCards.address} | ||
mutation={UPDATE_CRASH} | ||
onSaveCallback={onSaveCallback} | ||
/> | ||
</Col> | ||
<Col sm={12} md={6} lg={4} className="mb-3"> | ||
<DataCard<Crash> | ||
record={crash} | ||
isValidating={isValidating} | ||
title="Secondary address" | ||
columns={crashDataCards.address_secondary} | ||
mutation={UPDATE_CRASH} | ||
onSaveCallback={onSaveCallback} | ||
/> | ||
</Col> | ||
</Row> | ||
<Row> | ||
<Col sm={12} className="mb-3"> | ||
<RelatedRecordTable | ||
records={crash.units} | ||
isValidating={isValidating} | ||
title="Units" | ||
columns={unitRelatedRecordCols} | ||
mutation={UPDATE_UNIT} | ||
onSaveCallback={onSaveCallback} | ||
/> | ||
</Col> | ||
</Row> | ||
<Row className="mb-5"> | ||
<Col>{crash && <ChangeLog logs={crash.change_logs} />}</Col> | ||
</Row> | ||
</> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
"use client"; | ||
import Card from "react-bootstrap/Card"; | ||
import AppBreadCrumb from "@/components/AppBreadCrumb"; | ||
import { crashesListViewColumns } from "@/configs/crashesListViewColumns"; | ||
import { crashesListViewQueryConfig } from "@/configs/crashesListViewTable"; | ||
import TableWrapper from "@/components/TableWrapper"; | ||
const localStorageKey = "crashesListViewQueryConfig"; | ||
|
||
export default function Crashes() { | ||
return ( | ||
<> | ||
<AppBreadCrumb /> | ||
<Card className="mx-3 mb-3"> | ||
<Card.Header className="fs-5 fw-bold">Crashes</Card.Header> | ||
<Card.Body> | ||
<TableWrapper | ||
columns={crashesListViewColumns} | ||
initialQueryConfig={crashesListViewQueryConfig} | ||
localStorageKey={localStorageKey} | ||
/> | ||
</Card.Body> | ||
</Card> | ||
</> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export default function Dashboard() { | ||
return <h1>This is the dashboard page</h1>; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import "../styles/global.scss"; | ||
import AuthProvider from "@/contexts/Auth"; | ||
import SidebarLayout from "@/components/SidebarLayout"; | ||
|
||
/** | ||
* The root layout for the whole app | ||
* | ||
* todo: metadata | ||
*/ | ||
export default function RootLayout({ | ||
children, | ||
}: { | ||
children: React.ReactNode; | ||
}) { | ||
return ( | ||
// <Html lang="en" style={{fontSize: "14px"}} data-bs-theme="dark"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i left this here bc the dark theme is glorious to dev on. would be fun to spin off an issue to make a UI toggle for it 🌚 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. after switching back to light mode a while back, maybe it is time for me to find my way back to the dark side. 😈 |
||
<html lang="en" style={{ fontSize: "14px" }}> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. my chrome browser's font size is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fwiw this is what MUI does - https://mui.com/material-ui/customization/typography/#font-size which also seems to be the default of Bootstrap too - 1rem. Idk why the font looks so large with this override removed. But, i agree that it is something that needs more thought and can be adjusted globally later. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, thanks pointing to MUI's approach—interesting that they default to 14px. My understanding of the way it works is that |
||
<AuthProvider> | ||
<body> | ||
<SidebarLayout>{children}</SidebarLayout> | ||
</body> | ||
</AuthProvider> | ||
</html> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export default function Locations() { | ||
return <h1>This is the locations page</h1>; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
// this page redirects to /crashes | ||
// todo: what should go here | ||
export default function Page() { | ||
return <p> hello</p>; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i love seeing these absolute imports in this code - so fresh ✨