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: data portal landing page #729

Merged
merged 19 commits into from
Aug 19, 2023
Merged
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
24 changes: 7 additions & 17 deletions .github/workflows/chromatic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
DB_DIRECT_URL: ${{ secrets.DB_DIRECT_URL }}
NEXT_PUBLIC_GOOGLE_MAPS_API: ''
CI: true
OVERRIDE_CI: true
FORCE_COLOR: true
Expand All @@ -30,29 +31,18 @@ jobs:
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3
with:
fetch-depth: 0
- name: Install Node.js
uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3
with:
node-version: 18
- uses: pnpm/action-setup@d882d12c64e032187b2edb46d3a0d003b7a43598 # v2.4.0
name: Install pnpm
id: pnpm-install
with:
run_install: false
- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: 'echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT'
- uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3
name: Setup pnpm cache
- name: Install Node.js
uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
pnpm-store-
# - name: Install dependencies
# run: pnpm install
# 👇 Runs pnpm in ./packages/ui
node-version-file: .nvmrc
cache: pnpm
cache-dependency-path: pnpm-lock.yaml

- name: Install dependencies
run: pnpm install
working-directory: packages/ui
Expand Down
27 changes: 8 additions & 19 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,30 +30,19 @@ jobs:
git_config_global: true
git_commit_gpgsign: true

- name: Install Node.js
uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3
with:
node-version: 18

- uses: pnpm/action-setup@d882d12c64e032187b2edb46d3a0d003b7a43598 # v2.4.0
name: Install pnpm
id: pnpm-install
with:
run_install: false
# standalone: true

- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT

- uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3
name: Setup pnpm cache
- name: Install Node.js
uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
node-version-file: .nvmrc
cache: pnpm
cache-dependency-path: pnpm-lock.yaml

- name: Install dependencies
run: pnpm install
Expand Down Expand Up @@ -89,7 +78,7 @@ jobs:
with:
message: 'chore: lint & format'
commit: --signoff --no-verify
committer_name: InReach Bot
committer_name: InReach [bot]
committer_email: [email protected]
author_name: InReach Bot
author_name: InReach [bot]
author_email: [email protected]
4 changes: 2 additions & 2 deletions InReach.code-workspace
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@
"eslint.options": {
"cache": true
},
"eslint.ignoreUntitled": true,
"eslint.nodeEnv": "development",
"eslint.rules.customizations": [
{
"rule": "import/order",
Expand All @@ -160,9 +162,7 @@
},
{ "rule": "sort-imports", "severity": "off" }
],
"eslint.runtime": "node",
"eslint.useESLintClass": true,
"eslint.workingDirectories": [{ "pattern": "./packages/*/" }, { "pattern": "./apps/*/" }],
"explorer.decorations.badges": true,
"explorer.expandSingleFolderWorkspaces": false,
"explorer.fileNesting.enabled": true,
Expand Down
1 change: 1 addition & 0 deletions apps/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
"just-compact": "3.2.0",
"just-compare": "2.3.0",
"luxon": "3.4.0",
"mantine-react-table": "1.1.2",
"next": "13.4.18",
"next-auth": "4.23.1",
"next-i18next": "14.0.0",
Expand Down
4 changes: 4 additions & 0 deletions apps/app/public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@
"enter-password-placeholder": "Enter password...",
"enter-review": "Enter your review...",
"errors": {
"401-title": "You must be logged in to do that.",
"403-body": "You do not have permission to access this page. If you feel that you have reached this page in error, please contact your supervisor.",
"403-title": "403: Forbidden",
"404-body": "We're sorry, the page you're looking for doesn't exist or has been moved. Start a search below to find safe, verified resources for the diverse LGBTQ+ community in your area.",
"404-title": "404: Page not found.",
"500-body": "We're sorry, something went wrong with our server. Please try again later, or start a search below to find safe, verified LGBTQ+ resources in your area.",
Expand Down Expand Up @@ -368,6 +371,7 @@
"visit": "Visit",
"website_one": "Website",
"website_other": "Websites",
"welcome-name": "Welcome, {{name}}!",
"words": {
"accept": "Accept",
"account": "Account",
Expand Down
52 changes: 52 additions & 0 deletions apps/app/src/pages/401.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { Container, rem, Stack, Title } from '@mantine/core'
import { type GetStaticProps } from 'next'
import { useRouter } from 'next/router'
import { useTranslation } from 'next-i18next'
import { type Route } from 'nextjs-routes'
import { z } from 'zod'

import { getServerSideTranslations } from '~app/utils/i18n'
import { LoginBody } from '~ui/modals/Login'

const RouteSchema = z.object({
pathname: z.string(),
query: z.record(z.string()).optional(),
locale: z.string().optional(),
})

const Unauthorized = () => {
const { t } = useTranslation('common')
const router = useRouter()
const callback =
typeof router.query.callbackUrl === 'string'
? RouteSchema.safeParse(JSON.parse(Buffer.from(router.query.callbackUrl, 'base64').toString('utf-8')))
: undefined

return (
<Container>
<Stack
m={{ base: `${rem(48)} ${rem(0)}`, xs: `${rem(80)} ${rem(0)}`, sm: `${rem(100)} ${rem(0)}` }}
align='center'
spacing={32}
>
<Stack spacing={0} align='center'>
{/* eslint-disable-next-line i18next/no-literal-string */}
<Title order={1}>🔐</Title>
<Title order={1}>{t('errors.401-title')}</Title>
</Stack>
<LoginBody hideTitle callbackUrl={callback?.success ? (callback.data as Route) : undefined} />
</Stack>
</Container>
)
}

export const getStaticProps: GetStaticProps = async ({ locale }) => {
return {
props: {
...(await getServerSideTranslations(locale, ['common'])),
},
revalidate: 60 * 60 * 24 * 7,
}
}

export default Unauthorized
37 changes: 37 additions & 0 deletions apps/app/src/pages/403.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Container, rem, Stack, Text, Title } from '@mantine/core'
import { type GetStaticProps } from 'next'
import { useTranslation } from 'next-i18next'

import { getServerSideTranslations } from '~app/utils/i18n'

const Forbidden = () => {
const { t } = useTranslation('common')

return (
<Container>
<Stack
m={{ base: `${rem(48)} ${rem(0)}`, xs: `${rem(80)} ${rem(0)}`, sm: `${rem(100)} ${rem(0)}` }}
align='center'
spacing={32}
>
<Stack spacing={0} align='center'>
{/* eslint-disable-next-line i18next/no-literal-string */}
<Title order={1}>⛔️</Title>
<Title order={1}>{t('errors.403-title')}</Title>
</Stack>
<Text ta='center'>{t('errors.403-body')}</Text>
</Stack>
</Container>
)
}

export const getStaticProps: GetStaticProps = async ({ locale }) => {
return {
props: {
...(await getServerSideTranslations(locale, ['common'])),
},
revalidate: 60 * 60 * 24 * 7,
}
}

export default Forbidden
62 changes: 62 additions & 0 deletions apps/app/src/pages/admin/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { Container, Stack, Title } from '@mantine/core'
import { type GetServerSideProps, type NextPage } from 'next'
import Head from 'next/head'
import { useSession } from 'next-auth/react'
import { useTranslation } from 'next-i18next'
import { type Route, route } from 'nextjs-routes'

import { checkPermissions, getServerSession } from '@weareinreach/auth'
import { OrganizationTable } from '@weareinreach/ui/components/data-portal/OrganizationTable'
import { getServerSideTranslations } from '~app/utils/i18n'

const AdminIndex: NextPage = () => {
const { t } = useTranslation(['common'])
const { data: session, status } = useSession()
return (
<>
<Head>
<title>{t('page-title.base', { title: 'Data Admin' })}</title>
</Head>
{/* <Container fluid> */}
<Stack spacing={40} miw='80vw'>
<Title order={2}>{t('welcome-name', { name: session?.user?.name })}</Title>
<OrganizationTable />
</Stack>
{/* </Container> */}
</>
)
}
export default AdminIndex

export const getServerSideProps: GetServerSideProps = async (ctx) => {
const session = await getServerSession(ctx)
if (!session) {
const callbackRoute: Route = {
pathname: '/admin',
}
const callbackUrl = Buffer.from(JSON.stringify(callbackRoute)).toString('base64url')
return {
redirect: {
destination: route({ pathname: '/401', query: { callbackUrl } }),
permanent: false,
},
}
}
const hasPermissions = checkPermissions({ session, permissions: 'root', has: 'some' })

if (!hasPermissions) {
return {
redirect: {
destination: '/403',
permanent: false,
},
}
}

return {
props: {
session,
...(await getServerSideTranslations(ctx.locale, ['common'])),
},
}
}
3 changes: 3 additions & 0 deletions apps/app/src/types/nextjs-routes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@ declare module "nextjs-routes" {
} from "next";

export type Route =
| StaticRoute<"/401">
| StaticRoute<"/403">
| StaticRoute<"/404">
| StaticRoute<"/500">
| StaticRoute<"/account">
| StaticRoute<"/account/reviews">
| StaticRoute<"/account/saved">
| StaticRoute<"/admin">
| StaticRoute<"/admin/quicklink/email">
| StaticRoute<"/admin/quicklink">
| StaticRoute<"/admin/quicklink/phone">
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
"chokidar": ">=3.0.0",
"csstype": "^3.1.2",
"eslint-plugin-import": "npm:eslint-plugin-i@latest",
"eslint-plugin-node": "npm:eslint-plugin-n@latest",
"glob-parent@<5.1.2": "^5.1.2",
"http-cache-semantics@<=4.1.0": "^4.1.1",
"listr2@<5": "^5.0.5",
Expand All @@ -91,7 +92,6 @@
},
"patchedDependencies": {
"@crowdin/[email protected]": "patches/@[email protected]",
"[email protected]": "patches/[email protected]",
"[email protected]": "patches/[email protected]",
"[email protected]": "patches/[email protected]"
},
Expand Down
7 changes: 5 additions & 2 deletions packages/api/router/location/query.forGoogleMaps.handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,12 @@ export const forGoogleMaps = async ({ input }: TRPCHandlerParams<TForGoogleMapsS
if (latitude && longitude) coordsForBounds.push({ latitude, longitude })
}
const bounds = result.length > 1 ? getBoundary(coordsForBounds) : null
const singleLat = result.at(0)?.latitude
const singleLon = result.at(0)?.longitude

const center =
result.length === 1 && result.at(0)?.latitude && result.at(0)?.longitude
? ({ lat: result.at(0)!.latitude, lng: result.at(0)!.longitude } as { lat: number; lng: number })
result.length === 1 && singleLat && singleLon
? ({ lat: singleLat, lng: singleLon } satisfies google.maps.LatLngLiteral)
: getCenter(coordsForBounds)
const zoom = result.length === 1 ? 17 : null

Expand Down
2 changes: 1 addition & 1 deletion packages/config/tsconfig/base.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"resolveJsonModule": true,
"skipLibCheck": true,
"strict": true,
"target": "es2017"
"target": "es2020"
},
"display": "Default",
"include": ["../../@types/**/*.ts"],
Expand Down
Loading
Loading