Skip to content

Commit

Permalink
Migrate from pages router to app router (#17)
Browse files Browse the repository at this point in the history
* Add TypeScript improvements

* Migrated to app router

* Add SEO

* Lint and format

* Add analytics

* Add static prefetching

* Reenable iterable fields comparison

* Add og image for school

* Force sitemap dynamic render

* Fix map page layout

* Add special pages

* Add Sentry reporting in app dir
  • Loading branch information
micorix authored May 22, 2023
1 parent a47dd8b commit ef402c9
Show file tree
Hide file tree
Showing 247 changed files with 2,461 additions and 2,170 deletions.
2 changes: 0 additions & 2 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ module.exports = {
project: './tsconfig.json',
},
rules: {
'react/react-in-jsx-scope': 'off', // next does that for us
'linebreak-style': 'off',
'prettier/prettier': [
'warn',
{
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified .yarn/install-state.gz
Binary file not shown.
16 changes: 8 additions & 8 deletions .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions .yarn/releases/yarn-berry.cjs

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

FROM node:16.13.2-alpine AS builder

ARG STATIC_PREFETCH_API_URL=""
ENV API_URL=$STATIC_PREFETCH_API_URL

# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat libtool automake autoconf nasm g++ make libpng-dev

Expand Down
16 changes: 3 additions & 13 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,6 @@ const withBundleAnalyzer = require('@next/bundle-analyzer')({
const customNextConfig = {
basePath: '/app',
assetPrefix: '/app/',
env: {
PUBLIC_URL: '',
},
publicRuntimeConfig: {
API_URL: process.env.API_URL,
APP_ENVIRONMENT: process.env.APP_ENVIRONMENT,
APP_FRONTEND_RELEASE: process.env.APP_FRONTEND_RELEASE,
PUBLIC_SENTRY_DSN: process.env.PUBLIC_SENTRY_DSN,
MAPBOX_ACCESS_TOKEN: process.env.MAPBOX_ACCESS_TOKEN,
POSTHOG_API_KEY: process.env.POSTHOG_API_KEY,
SHOW_LINKS_TO_APP: process.env.SHOW_LINKS_TO_APP,
SITE_URL: process.env.SITE_URL,
},
webpack(config) {
config.module.rules.push({
test: /\.svg$/i,
Expand Down Expand Up @@ -61,6 +48,9 @@ const customNextConfig = {
// your project has type errors.
ignoreBuildErrors: true,
},
experimental: {
esmExternals: 'loose',
},
};

module.exports = withBundleAnalyzer(withSentryConfig(customNextConfig));
16 changes: 9 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@
"@loaders.gl/mvt": "^3.3.3",
"@react-icons/all-files": "^4.1.0",
"@reduxjs/toolkit": "^1.9.1",
"@sentry/nextjs": "^6.15.0",
"@sentry/react": "^5.26.0",
"@sentry/tracing": "^6.16.1",
"@sentry/nextjs": "^7.52.1",
"@sentry/react": "^7.52.1",
"@sentry/tracing": "^7.52.1",
"@tailwindcss/typography": "^0.5.9",
"@tanstack/react-query": "^4.10.1",
"@testing-library/dom": "^9.2.0",
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^14.4.3",
"@vercel/og": "^0.5.4",
"@warsawlo/points-calculator": "^2.1.1",
"deck.gl": "^8.9.7",
"geojson": "^0.5.0",
Expand All @@ -35,17 +36,17 @@
"lodash": "^4.17.20",
"mapbox-gl": "^2.13.0",
"nanoid": "^4.0.0",
"next": "^13.3.1",
"next": "latest",
"next-i18next": "^11.0.0",
"next-seo": "^5.1.0",
"normalize.css": "^8.0.1",
"object-hash": "^3.0.0",
"posthog-js": "^1.20.2",
"query-string": "^7.1.1",
"react": "^18.2.0",
"react": "latest",
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
"react-dom": "^18.2.0",
"react-dom": "latest",
"react-hook-form": "^7.22.5",
"react-icons": "^4.3.1",
"react-leaflet": "^3.2.5",
Expand All @@ -70,6 +71,7 @@
"format:write": "prettier --parser typescript --write \"**/*.{js,jsx,ts,tsx}\"",
"lint:check": "eslint --ext .js,.jsx,.ts,.tsx --max-warnings=0 .",
"lint:fix": "eslint --fix --ext .js,.jsx,.ts,.tsx .",
"lint:next": "next lint",
"pr": "gh pr create -R po8klasie/web-frontend"
},
"browserslist": {
Expand Down Expand Up @@ -123,7 +125,7 @@
"responsive-loader": "^2.3.0",
"sharp": "^0.29.3",
"tailwindcss": "^3.2.7",
"typescript": "~4.3.5",
"typescript": "latest",
"webp-loader": "^0.6.0"
}
}
Binary file added public/assets/fonts/Jost-500-Medium.ttf
Binary file not shown.
6 changes: 6 additions & 0 deletions src/api/institutionDetails/institutionDetails.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { fetchJson } from '../serverFetch';
import { IInstitutionDetails } from '../../app/[projectID]/school/[rspo]/(sections)/types';

export const fetchInstitutionDetails = async (rspo: string) => {
return fetchJson<IInstitutionDetails>(`/school/${rspo}`);
};
6 changes: 6 additions & 0 deletions src/api/projectConfig/projectConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { fetchJson } from '../serverFetch';
import type { ProjectConfig } from './types';

export const fetchProjectConfig = async (projectID: string) => {
return fetchJson<ProjectConfig>(`/project/${projectID}`);
};
17 changes: 17 additions & 0 deletions src/api/projectConfig/projectConfigContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
'use client';

import { createContext, FC, useContext } from 'react';
import { ProjectConfig } from './types';

export const projectConfigContext = createContext<ProjectConfig>({});

export const useProjectConfig = () => useContext(projectConfigContext);

interface ProjectConfigProviderProps {
projectConfig: ProjectConfig;
}
const ProjectConfigProvider: FC<ProjectConfigProviderProps> = ({ projectConfig, children }) => (
<projectConfigContext.Provider value={projectConfig}>{children}</projectConfigContext.Provider>
);

export default ProjectConfigProvider;
6 changes: 3 additions & 3 deletions src/config/types.ts → src/api/projectConfig/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { SchoolInfoSectionId } from '../components/app/SchoolPage/schoolInfoSections/schoolInfoSections';
import { AnyParser } from '../utils/searchParser';
import { InstitutionDetailsSectionId } from '../../app/[projectID]/school/[rspo]/(sections)/institutionDetailsSections';
import { AnyParser } from '../../utils/searchParser';

export type FilterDefinition = {
name: string;
Expand All @@ -23,7 +23,7 @@ export type SearchViewConfig = {
};

export interface SchoolInfoSection {
sectionId: SchoolInfoSectionId;
sectionId: InstitutionDetailsSectionId;
options: Record<string, unknown>;
}

Expand Down
30 changes: 18 additions & 12 deletions src/api/queryClient.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
import { publicRuntimeConfig } from '../runtimeConfig';
import { QueryClientConfig, QueryKey } from '@tanstack/react-query';

interface FetcherArgs {
queryKey: QueryKey;
}

export const fetchData = (path: string) => fetch(`${publicRuntimeConfig.API_URL}${path}`);

export const fetcher = <T>({ queryKey }: FetcherArgs): Promise<T> =>
fetchData(queryKey[0]).then((res) => res.json());
import { QueryClient, QueryClientConfig, useQuery, UseQueryOptions } from '@tanstack/react-query';
import { useEnvironment } from '../environment/environmentContext';

export const queryClientOptions: QueryClientConfig = {
defaultOptions: {
queries: {
queryFn: fetcher,
refetchIntervalInBackground: false,
},
},
};

export const queryClient = new QueryClient(queryClientOptions);

export const useAPIQuery = <T = void>(
queryKey: [string],
options: Omit<UseQueryOptions, 'queryKey' | 'queryFn'>,
) => {
const {
publicEnvironment: { API_URL },
} = useEnvironment();
const path = queryKey[0];
const fullUrl = `${API_URL}${path}`;
const modifiedQueryKey: [string] = [fullUrl];

return useQuery<T>(modifiedQueryKey, () => fetch(fullUrl).then((res) => res.json()), options);
};
24 changes: 0 additions & 24 deletions src/api/schools.ts

This file was deleted.

6 changes: 6 additions & 0 deletions src/api/serverFetch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import environment from '../environment/server';

export const fetchData = (path: string) => fetch(`${environment.publicEnvironment.API_URL}${path}`);

export const fetchJson = <T = unknown>(path: string) =>
fetchData(path).then((res) => res.json() as T);
4 changes: 2 additions & 2 deletions src/api/singleSchool.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { ISchoolData } from '../types';
import { useQuery } from '@tanstack/react-query';
import { IInstitutionDetails } from '../app/[projectID]/school/[rspo]/(sections)/types';

export const createSingleSchoolDataQueryKey = (rspo: string) => [`/school/${rspo}`];

const useSingleSchoolData = (rspo: string) =>
useQuery<ISchoolData>(createSingleSchoolDataQueryKey(rspo));
useQuery<IInstitutionDetails>(createSingleSchoolDataQueryKey(rspo));

export default useSingleSchoolData;
34 changes: 34 additions & 0 deletions src/app/[projectID]/Providers.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
'use client';

import { store } from '../../store/store';
import { Provider as StoreProvider } from 'react-redux/es/exports';
import EnvironmentProvider from '../../environment/environmentContext';
import ProjectConfigProvider from '../../api/projectConfig/projectConfigContext';
import { IEnvironment } from '../../environment/types';
import { FC, PropsWithChildren } from 'react';
import { QueryClientProvider } from '@tanstack/react-query';
import { queryClient } from '../../api/queryClient';
import { ProjectConfig } from '../../api/projectConfig/types';

interface ProvidersProps {
environment: IEnvironment;
projectConfig: ProjectConfig;
}

const Providers: FC<PropsWithChildren<ProvidersProps>> = ({
children,
environment,
projectConfig,
}) => {
return (
<EnvironmentProvider environment={environment}>
<ProjectConfigProvider projectConfig={projectConfig}>
<QueryClientProvider client={queryClient}>
<StoreProvider store={store}>{children}</StoreProvider>
</QueryClientProvider>
</ProjectConfigProvider>
</EnvironmentProvider>
);
};

export default Providers;
10 changes: 10 additions & 0 deletions src/app/[projectID]/_components/Analytics.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'use client';

import usePosthogPageChangeTracker from '../../../hooks/usePosthogPageChangeTracker';

const Analytics = () => {
usePosthogPageChangeTracker();
return null;
};

export default Analytics;
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { FaFacebookF } from '@react-icons/all-files/fa/FaFacebookF';
import { FaLinkedinIn } from '@react-icons/all-files/fa/FaLinkedinIn';
import { FaTwitter } from '@react-icons/all-files/fa/FaTwitter';
import { IconType } from 'react-icons';
import Brand from '../Brand';
import { publicRuntimeConfig } from '../../runtimeConfig';
import Brand from '../../../components/Brand';
// import { publicRuntimeConfig } from '../../../../runtimeConfig';

const { APP_ENVIRONMENT, APP_FRONTEND_RELEASE } = publicRuntimeConfig;
// const { APP_ENVIRONMENT, APP_FRONTEND_RELEASE } = publicRuntimeConfig;

const socialLinks: [string, IconType][] = [
['https://fb.com/po8klasie', FaFacebookF],
Expand All @@ -25,8 +25,8 @@ const AppFooter: FC = () => (
<div className="lg:flex items-center">
<Brand className="font-bold text-xl" />
<span className="text-black lg:ml-10 flex items-center mt-5 lg:mt-0 text-sm lg:text-base">
wersja {APP_FRONTEND_RELEASE}
<span className="text-sm text-gray ml-2">{APP_ENVIRONMENT}</span>
{/* wersja {APP_FRONTEND_RELEASE} */}
<span className="text-sm text-gray ml-2">{process.env.APP_ENVIRONMENT}</span>
</span>
</div>
<div className="flex flex-col-reverse lg:flex-row lg:items-center items-end">
Expand Down
28 changes: 28 additions & 0 deletions src/app/[projectID]/_components/AppLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
'use client';

import type { FC, PropsWithChildren } from 'react';
import AppNavbar from './AppNavbar';
import AppFooter from './AppFooter';
import BetaBanner from './BetaBanner';
import { usePathname } from 'next/navigation';

interface AppLayoutProps {
className?: string;
}

const AppLayout: FC<PropsWithChildren<AppLayoutProps>> = ({ children, className }) => {
const pathname = usePathname();
const isMapSite = pathname.includes('map');
return (
<div className={['bg-appBg flex flex-col min-h-full', className ?? ''].join(' ')}>
<AppNavbar wide={isMapSite} />
<main className={`pt-navbarHeight ${isMapSite ? 'h-full' : ''}`} style={{ flex: '1 0 auto' }}>
{children}
</main>
<div className="shrink-0">{!isMapSite && <AppFooter />}</div>
<BetaBanner />
</div>
);
};

export default AppLayout;
Loading

0 comments on commit ef402c9

Please sign in to comment.