Skip to content
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

feat: framework upgrade Next.js 12 -> 14 #126

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions .env.example

This file was deleted.

2 changes: 1 addition & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"extends": "next/core-web-vitals",
"rules": {
"react/display-name": "off"
"react/jsx-key": "off"
}
}
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz

# testing
/coverage
Expand All @@ -23,7 +24,6 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# local env files
.env*.local
Expand Down
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
public-hoist-pattern[]=*
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@ First, run the development server:
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.

[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.

The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.

## Learn More

Expand Down
54 changes: 54 additions & 0 deletions app/(with-map)/entry/[slug]/EntryDetails.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import {
getFormattedTenureTypes,
getFormattedEntryDates,
} from "@/app/utils/sanity/entry"
import { Entry } from "@/app/utils/sanity/types"
import { Tag } from "@carbon/icons-react"
import EntryItem from "./EntryItem"
import EntryReferences from "./EntryReferences"
import EntryPortableText from "./EntryPortableText"

const EntryDetails = (entry?: Entry) => (
<div className="bg-white text-black grid grid-cols-4 grid-rows-auto gap-x-4 gap-y-1 sm:gap-y-6 p-8">
<EntryItem
className="col-span-4 sm:col-span-2"
heading={getFormattedTenureTypes(entry?.tenureType)}
/>
<EntryItem
className="col-span-2 sm:col-span-1"
heading={entry?.location?.region || "Unknown location"}
/>
<EntryItem
className="col-span-2 sm:col-span-1 text-right sm:text-left"
heading={getFormattedEntryDates(entry?.dates)}
/>
<EntryItem heading="" className="col-span-4">
<EntryPortableText value={entry?.content ?? []} />
</EntryItem>
{entry?.references?.length && (
<EntryItem heading="More information" className="col-span-2">
<EntryReferences {...entry} />
</EntryItem>
)}
<EntryItem heading="Rating" className="col-span-2">
<>
<p className="text-sm">
This entry is{" "}
<span className="text-gray-400 text-sm lowercase">
{entry?.entryRating?.grade || "a draft"}
</span>
</p>
<div className="">
{entry?.tags &&
entry.tags.map((entryTag) => (
<Tag key={entryTag.value} className={"bg-gray-200 mt-2"}>
{entryTag.label}
</Tag>
))}
</div>
</>
</EntryItem>
</div>
)

export default EntryDetails
61 changes: 61 additions & 0 deletions app/(with-map)/entry/[slug]/EntryHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Tag } from "@/app/ui/Tag"
import { Entry } from "@/app/utils/sanity/types"
import { ArrowLeft, ArrowUpRight, Close } from "@carbon/icons-react"
import Link from "next/link"

const EntryHeader = (entry?: Entry) => (
<div
// TODO: The sanity image pipeline could get us an optimized image here
// https://www.sanity.io/docs/presenting-images
style={{ backgroundImage: `url(${entry?.mainImage?.file?.asset?.url})` }}
className="h-80 p-8 pt-2 flex flex-col justify-between bg-center bg-cover"
>
<nav className="flex justify-between">
<Link href="/" className="inline-flex items-center space-x-1">
<ArrowLeft />
<span>Back to map</span>
</Link>
<Link href="/">
<Close size={32} className="cursor-pointer" />
</Link>
</nav>
<div className="flex flex-row justify-between items-center">
<h1 className="text-3xl sm:text-5xl w-2/3 sm:w-1/2">{entry?.name}</h1>
<div className="flex flex-col items-end opacity-90 text-sm">
<Tag className="bg-white">{entry?.type}</Tag>
{entry?.mainImage?.source ? (
entry.mainImage.credit ? (
<div className="mt-3">
<span className="font-bold mr-2">Image</span>
<a
href={entry.mainImage.source}
target="_blank"
rel="noreferrer"
className="inline-flex items-center space-x-1 underline"
>
<span>{entry.mainImage.credit}</span>

<ArrowUpRight />
</a>
</div>
) : (
<div className="mt-3">
<a
href={entry.mainImage.source}
target="_blank"
rel="noreferrer"
className="inline-flex items-center space-x-1 underline"
>
<span>{"Image source"}</span>

<ArrowUpRight />
</a>
</div>
)
) : null}
</div>
</div>
</div>
)

export default EntryHeader
19 changes: 19 additions & 0 deletions app/(with-map)/entry/[slug]/EntryItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { HTMLProps, PropsWithChildren } from "react"

type Props = HTMLProps<HTMLDivElement> & {
heading: string
}

const EntryItem = ({ heading, children, ...rest }: Props) => (
<section {...rest}>
<div
role="doc-subtitle"
className={`mb-1 ${children ? "text-sm" : "text-base sm:text-2xl"}`}
>
{heading}
</div>
{children}
</section>
)

export default EntryItem
113 changes: 113 additions & 0 deletions app/(with-map)/entry/[slug]/EntryPageChart.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { A } from "@/app/utils/fp"
import {
getPatternClasses,
getPatterns,
getRelatedEntriesByPattern,
getRelatedEntriesByTenureQuery,
} from "@/app/utils/sanity/queries"
import { Entry, Term } from "@/app/utils/sanity/types"
import { pipe } from "fp-ts/lib/function"
import _ from "lodash"
import EntryPageChartImpl from "./EntryPageChartImpl"

type Props = {
entry: Entry
}

const EntryPageChart = async (props: Props) => {
const { entry } = props

const terms: Term[] = entry.terms ?? []

const patterns = await getPatterns()
const patternClasses = await getPatternClasses()

const relatedEntriesByTenure = await getRelatedEntriesByTenureQuery(
entry.tenureType,
entry._id
)

const augmentedTerms = await Promise.all(
pipe(
terms,
A.map(async (term) => {
const patternId = term.pattern._ref
const entryId = entry._id

const relatedEntriesByPattern = await getRelatedEntriesByPattern(
patternId,
entryId
)

const pattern = _.find(patterns, ["_id", term.pattern?._ref])

const patternName = _.find(patterns, ["_id", term.pattern?._ref])?.name

const type = _.capitalize(
_.find(patterns, ["_id", term.pattern?._ref])?.type
)

// strength: term.strength, // 1-5
// description: term.description,
const legalMechanisms = term.termLegalMechanisms?.map(
(mechanism: Record<string, any>): string => mechanism.name
)

return {
meta: pattern,
name: patternName,
patternClassName: _.find(patternClasses, [
"_id",
pattern?.class?._ref,
])?.name,
patternClassOrder: _.find(patternClasses, [
"_id",
pattern?.class?._ref,
])?.order,
patternIconUrl: pattern?.iconUrl,
type: type === "Limitation" ? "Obligation" : type,
strength: term.strength,
description: term.description,
legalMechanisms,
relatedEntriesByPattern,
}
})
)
)

// Format the list of individual terms that apply to this entry
// let formattedTerms = _(entry.terms)
// .map((term: any) => ({
// pattern: _.find(patterns, ["_id", term.pattern?._ref]),
// patternName: _.find(patterns, ["_id", term.pattern?._ref])?.name,
// type: _.capitalize(_.find(patterns, ["_id", term.pattern?._ref])?.type),
// strength: term.strength, // 1-5
// description: term.description,
// legalMechanisms: term.termLegalMechanisms?.map(
// (mechanism: Record<string, any>) => mechanism.name
// ),
// }))
// .map((term: any) => ({
// meta: term.pattern,
// name: term.patternName,
// patternClassName: _.find(patternClasses, [
// "_id",
// term.pattern?.class?._ref,
// ])?.name,
// patternClassOrder: _.find(patternClasses, [
// "_id",
// term.pattern?.class?._ref,
// ])?.order,
// patternIconUrl: term.pattern?.iconUrl,
// type: term.type === "Limitation" ? "Obligation" : term.type,
// strength: term.strength,
// description: term.description,
// legalMechanisms: term.legalMechanisms,
// }))
// .sortBy("patternClassOrder", "name")
// .value()

return <EntryPageChartImpl augmentedTerms={augmentedTerms} />
}

export default EntryPageChart
Loading