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

project init #1

Merged
merged 19 commits into from
Oct 28, 2024
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
20 changes: 20 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.now/*
*.css
.changeset
dist
esm/*
public/*
tests/*
scripts/*
*.config.js
.DS_Store
node_modules
coverage
.next
build
!.commitlintrc.cjs
!.lintstagedrc.cjs
!jest.config.js
!plopfile.js
!react-shim.js
!tsup.config.ts
51 changes: 51 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"airbnb",
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"sourceType": "module",
"ecmaVersion": "latest"
},
"plugins": ["react", "simple-import-sort", "prettier"],
"rules": {
"simple-import-sort/imports": "error",
"simple-import-sort/exports": "error",
"prettier/prettier": "error",
"react/react-in-jsx-scope": "off",
"jsx-a11y/anchor-is-valid": "off",
"react/require-default-props": "off",
"react/jsx-props-no-spreading": "off",
"import/prefer-default-export": "off",
"react/jsx-filename-extension": [1, { "extensions": [".tsx", ".jsx"] }],
"import/extensions": [
"error",
"ignorePackages",
{
"js": "never",
"jsx": "never",
"ts": "warn",
"tsx": "never"
}
]
},
"settings": {
"react": {
"version": "detect"
},
"import/resolver": {
"alias": {
"map": [["@", "./src/"]],
"extensions": [".ts", ".tsx", ""]
}
}
}
}
31 changes: 31 additions & 0 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Lint and Format Check

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
lint-and-format:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Install dependencies
run: yarn

- name: Run ESLint
run: yarn lint

- name: Run Prettier
run: yarn format
35 changes: 35 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# 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
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
yarn lint
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package-lock=false
3 changes: 3 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
.next
build
7 changes: 7 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"singleQuote": true,
"semi": true,
"trailingComma": "es5",
"printWidth": 120,
"tabWidth": 2
}
8 changes: 8 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"typescript.tsdk": "node_modules/typescript/lib",
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.tabSize": 2,
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"],
"files.eol": "\n"
}
60 changes: 59 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,59 @@
# wfp-hunger-map
# wfp-hunger-map

This is the repository for the World Food Program's HungerMap.

## Technologies Used

- [Next.js 14](https://nextjs.org/docs/getting-started)
- [NextUI v2](https://nextui.org/)
- [Tailwind CSS](https://tailwindcss.com/)
- [Tailwind Variants](https://tailwind-variants.org)
- [TypeScript](https://www.typescriptlang.org/)
- [Framer Motion](https://www.framer.com/motion/)
- [next-themes](https://github.com/pacocoursey/next-themes)
- [leaflet](https://leafletjs.com/), [react-leaflet](https://react-leaflet.js.org/)
- [Highcharts](https://www.highcharts.com/), [highcharts-react](https://github.com/highcharts/highcharts-react)

## How to Use

**Make sure to use yarn instead of npm!**

### Install dependencies

```bash
yarn install
```

### Run the development server

```bash
yarn dev
```

## Development guidelines

Besides the usual guidlines, we're following these as per the customer's request:

### Styling

Linting and styling is based on [Airbnb's React style guide](https://airbnb.io/javascript/react/). A pre-commit hook will make sure that only well-formatted code is commited to the repo, but a GitHub Actions workflow will also check this on each PR.

### Git and GitHub

Always work on a separate branch, never commit to main! When you're creating a branch, you should use the branchname provided by Linear. Click the branch icon in the upper right corner of issue's page on Linear to copy the branchname. It should have the following format: `feature/<issue no.>-<concise description of issue>`. Also use meaningful, but concise commit messages. After you're done with your task, create a Pull Request and share it with your teammates, ask your team lead and/or TPL for a review. Use squash merge when the PR is approved.

### Project Structure

Each component should have their own file, where the file name is the name of the component. The app directory is for pages and layouts, all other components should go to the components directory. Try to group components to sub-directories based on their function. Code that doesn't belong to a specific component should be placed in a different file, in directories like utils, config, types, etc.

### Domain Driven Design

DDD is a software design approach that is against the idea of having a single unified model; instead it divides a large system into bounded contexts, each of which have their own model.

What this means for a React application, is that instead of using one global state with, for example Redux, we will have a React context for each of our entities that will store all the data and offer all the methods related to that domain.

### Dependency Injection

The point of DI is that the dependencies of services should not be hardcoded, instead they should receive them as parameters, where the type of the parameter is an interface. This makes testing easier and the code more reusable, since the same service can be used with different implementations of the same interface (for example mock implementations for testing).

For a React application, the most common depeendency that needs mocking is the one that makes the HTTP call to the API. Thus contexts or hooks that call the backend should receive the HTTP library implementation as a prop or from a higher-order context.
4 changes: 4 additions & 0 deletions next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/** @type {import('next').NextConfig} */
const nextConfig = {}

module.exports = nextConfig
68 changes: 68 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{
"name": "next-app-template",
"version": "0.0.1",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "eslint . --ext .ts,.tsx -c .eslintrc.json",
"lint:fix": "eslint . --ext .ts,.tsx -c .eslintrc.json --fix",
"format": "prettier --write .",
"format:fix": "prettier .",
"prepare": "husky"
},
"dependencies": {
"@nextui-org/button": "2.0.38",
"@nextui-org/code": "2.0.33",
"@nextui-org/input": "2.2.5",
"@nextui-org/kbd": "2.0.34",
"@nextui-org/link": "2.0.35",
"@nextui-org/listbox": "2.1.27",
"@nextui-org/navbar": "2.0.37",
"@nextui-org/skeleton": "^2.0.32",
"@nextui-org/snippet": "2.0.43",
"@nextui-org/switch": "2.0.34",
"@nextui-org/system": "2.2.6",
"@nextui-org/theme": "2.2.11",
"@react-aria/ssr": "3.9.4",
"@react-aria/visually-hidden": "3.8.12",
"clsx": "2.1.1",
"framer-motion": "~11.1.1",
"highcharts": "^11.4.8",
"highcharts-react-official": "^3.2.1",
"intl-messageformat": "^10.5.0",
"leaflet": "^1.9.4",
"leaflet-defaulticon-compatibility": "^0.1.2",
"leaflet-geosearch": "^4.0.0",
"next": "14.2.4",
"next-themes": "^0.2.1",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-leaflet": "^4.2.1",
"tailwind-variants": "0.1.20"
},
"devDependencies": {
"@types/leaflet": "^1.9.14",
"@types/node": "20.5.7",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@typescript-eslint/eslint-plugin": "^8.11.0",
"@typescript-eslint/parser": "^8.11.0",
"autoprefixer": "10.4.19",
"eslint": "^8.57.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-next": "15.0.1",
"eslint-config-prettier": "^8.2.0",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-react": "^7.23.2",
"eslint-plugin-simple-import-sort": "^12.1.1",
"husky": "^9.1.6",
"postcss": "8.4.38",
"prettier": "^3.3.3",
"tailwindcss": "3.4.3",
"typescript": "5.0.4"
}
}
6 changes: 6 additions & 0 deletions postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
Binary file added public/favicon.ico
Binary file not shown.
1 change: 1 addition & 0 deletions public/next.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/vercel.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions src/app/elements/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Chart } from '@/components/Charts/Chart';

/**
* You can use this page to try and show off your components.
* It's not accessible from the UI, but you can reach it by manually navigating to /elements
*/
export default function Elements() {
return <Chart />;
}
26 changes: 26 additions & 0 deletions src/app/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use client';

import { useEffect } from 'react';

export default function Error({ error, reset }: { error: Error; reset: () => void }) {
useEffect(() => {
// Log the error to an error reporting service
/* eslint-disable no-console */
console.error(error);
}, [error]);

return (
<div>
<h2>Something went wrong!</h2>
<button
type="button"
onClick={
// Attempt to recover by trying to re-render the segment
() => reset()
}
>
Try again
</button>
</div>
);
}
42 changes: 42 additions & 0 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import '@/styles/globals.css';

import clsx from 'clsx';
import { Metadata, Viewport } from 'next';

import { fontSans } from '@/config/fonts';
import { siteConfig } from '@/config/site';

import { Providers } from './providers';

export const metadata: Metadata = {
title: {
default: siteConfig.name,
template: `%s - ${siteConfig.name}`,
},
description: siteConfig.description,
icons: {
icon: '/favicon.ico',
},
};

export const viewport: Viewport = {
themeColor: [
{ media: '(prefers-color-scheme: light)', color: 'white' },
{ media: '(prefers-color-scheme: dark)', color: 'black' },
],
};

export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html suppressHydrationWarning lang="en">
<head />
<body className={clsx('min-h-screen bg-background font-sans antialiased', fontSans.variable)}>
<Providers themeProps={{ attribute: 'class', defaultTheme: 'dark' }}>
<div className="relative h-screen">
<main className="h-full w-full">{children}</main>
</div>
</Providers>
</body>
</html>
);
}
Loading