├── .env.example
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .husky
├── .gitignore
└── pre-commit
├── .prettierignore
├── .prettierrc
├── .storybook
├── main.js
└── preview.js
├── .vscode
├── extensions.json
└── settings.json
├── LICENSE
├── README.md
├── code-stages
├── chapter-02
│ └── src
│ │ ├── components
│ │ └── .gitkeep
│ │ ├── config
│ │ ├── constants.ts
│ │ └── theme.ts
│ │ ├── features
│ │ ├── auth
│ │ │ ├── api
│ │ │ │ └── .gitkeep
│ │ │ ├── components
│ │ │ │ └── .gitkeep
│ │ │ ├── index.ts
│ │ │ ├── pages
│ │ │ │ └── .gitkeep
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ ├── jobs
│ │ │ ├── api
│ │ │ │ └── .gitkeep
│ │ │ ├── components
│ │ │ │ └── .gitkeep
│ │ │ ├── index.ts
│ │ │ ├── pages
│ │ │ │ └── .gitkeep
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ └── organizations
│ │ │ ├── api
│ │ │ └── .gitkeep
│ │ │ ├── index.ts
│ │ │ ├── pages
│ │ │ └── .gitkeep
│ │ │ └── types
│ │ │ └── index.ts
│ │ ├── layouts
│ │ └── .gitkeep
│ │ ├── lib
│ │ └── .gitkeep
│ │ ├── pages
│ │ ├── _app.tsx
│ │ └── index.tsx
│ │ ├── providers
│ │ └── app.tsx
│ │ ├── stores
│ │ └── .gitkeep
│ │ ├── testing
│ │ └── .gitkeep
│ │ ├── types
│ │ └── index.ts
│ │ └── utils
│ │ ├── format.ts
│ │ └── uid.ts
├── chapter-03-start
│ └── src
│ │ ├── components
│ │ ├── button
│ │ │ ├── button.tsx
│ │ │ └── index.ts
│ │ ├── form
│ │ │ ├── index.ts
│ │ │ └── input-field.tsx
│ │ └── link
│ │ │ ├── index.ts
│ │ │ └── link.tsx
│ │ ├── config
│ │ ├── constants.ts
│ │ └── theme.ts
│ │ ├── features
│ │ ├── auth
│ │ │ ├── api
│ │ │ │ └── .gitkeep
│ │ │ ├── components
│ │ │ │ └── .gitkeep
│ │ │ ├── index.ts
│ │ │ ├── pages
│ │ │ │ └── .gitkeep
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ ├── jobs
│ │ │ ├── api
│ │ │ │ └── .gitkeep
│ │ │ ├── components
│ │ │ │ └── .gitkeep
│ │ │ ├── index.ts
│ │ │ ├── pages
│ │ │ │ └── .gitkeep
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ └── organizations
│ │ │ ├── api
│ │ │ └── .gitkeep
│ │ │ ├── index.ts
│ │ │ ├── pages
│ │ │ └── .gitkeep
│ │ │ └── types
│ │ │ └── index.ts
│ │ ├── layouts
│ │ └── .gitkeep
│ │ ├── lib
│ │ └── .gitkeep
│ │ ├── pages
│ │ ├── _app.tsx
│ │ └── index.tsx
│ │ ├── providers
│ │ └── app.tsx
│ │ ├── stores
│ │ └── .gitkeep
│ │ ├── testing
│ │ └── .gitkeep
│ │ ├── types
│ │ └── index.ts
│ │ └── utils
│ │ ├── format.ts
│ │ └── uid.ts
├── chapter-03
│ └── src
│ │ ├── components
│ │ ├── button
│ │ │ ├── button.stories.tsx
│ │ │ ├── button.tsx
│ │ │ └── index.ts
│ │ ├── form
│ │ │ ├── index.ts
│ │ │ ├── input-field.stories.tsx
│ │ │ └── input-field.tsx
│ │ └── link
│ │ │ ├── index.ts
│ │ │ ├── link.stories.tsx
│ │ │ └── link.tsx
│ │ ├── config
│ │ ├── constants.ts
│ │ └── theme.ts
│ │ ├── features
│ │ ├── auth
│ │ │ ├── api
│ │ │ │ └── .gitkeep
│ │ │ ├── components
│ │ │ │ └── .gitkeep
│ │ │ ├── index.ts
│ │ │ ├── pages
│ │ │ │ └── .gitkeep
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ ├── jobs
│ │ │ ├── api
│ │ │ │ └── .gitkeep
│ │ │ ├── components
│ │ │ │ └── .gitkeep
│ │ │ ├── index.ts
│ │ │ ├── pages
│ │ │ │ └── .gitkeep
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ └── organizations
│ │ │ ├── api
│ │ │ └── .gitkeep
│ │ │ ├── index.ts
│ │ │ ├── pages
│ │ │ └── .gitkeep
│ │ │ └── types
│ │ │ └── index.ts
│ │ ├── layouts
│ │ └── .gitkeep
│ │ ├── lib
│ │ └── .gitkeep
│ │ ├── pages
│ │ ├── _app.tsx
│ │ └── index.tsx
│ │ ├── providers
│ │ └── app.tsx
│ │ ├── stores
│ │ └── .gitkeep
│ │ ├── testing
│ │ └── .gitkeep
│ │ ├── types
│ │ └── index.ts
│ │ └── utils
│ │ ├── format.ts
│ │ └── uid.ts
├── chapter-04-start
│ └── src
│ │ ├── components
│ │ ├── button
│ │ │ ├── button.stories.tsx
│ │ │ ├── button.tsx
│ │ │ └── index.ts
│ │ ├── content
│ │ │ ├── content.stories.tsx
│ │ │ ├── content.tsx
│ │ │ └── index.ts
│ │ ├── data-table
│ │ │ ├── data-table.stories.tsx
│ │ │ ├── data-table.tsx
│ │ │ └── index.ts
│ │ ├── form
│ │ │ ├── index.ts
│ │ │ ├── input-field.stories.tsx
│ │ │ └── input-field.tsx
│ │ ├── info-card
│ │ │ ├── index.ts
│ │ │ ├── info-card.stories.tsx
│ │ │ └── info-card.tsx
│ │ ├── link
│ │ │ ├── index.ts
│ │ │ ├── link.stories.tsx
│ │ │ └── link.tsx
│ │ ├── loading
│ │ │ ├── index.ts
│ │ │ ├── loading.stories.tsx
│ │ │ └── loading.tsx
│ │ ├── not-found
│ │ │ ├── index.ts
│ │ │ ├── not-found.stories.tsx
│ │ │ └── not-found.tsx
│ │ └── seo
│ │ │ ├── index.ts
│ │ │ └── seo.tsx
│ │ ├── config
│ │ ├── constants.ts
│ │ └── theme.ts
│ │ ├── features
│ │ ├── auth
│ │ │ ├── api
│ │ │ │ └── .gitkeep
│ │ │ ├── components
│ │ │ │ └── .gitkeep
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ ├── jobs
│ │ │ ├── api
│ │ │ │ └── .gitkeep
│ │ │ ├── components
│ │ │ │ ├── create-job-form
│ │ │ │ │ ├── create-job-form.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── dashboard-job-info
│ │ │ │ │ ├── dashboard-job-info.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── jobs-list
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── jobs-list.tsx
│ │ │ │ └── public-job-info
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── public-job-info.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ └── organizations
│ │ │ ├── api
│ │ │ └── .gitkeep
│ │ │ ├── components
│ │ │ └── organization-info
│ │ │ │ ├── index.ts
│ │ │ │ └── organization-info.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ └── index.ts
│ │ ├── layouts
│ │ ├── dashboard-layout.tsx
│ │ └── public-layout.tsx
│ │ ├── lib
│ │ └── .gitkeep
│ │ ├── pages
│ │ ├── _app.tsx
│ │ └── index.tsx
│ │ ├── providers
│ │ └── app.tsx
│ │ ├── stores
│ │ └── .gitkeep
│ │ ├── testing
│ │ └── test-data.ts
│ │ ├── types
│ │ └── index.ts
│ │ └── utils
│ │ ├── format.ts
│ │ └── uid.ts
├── chapter-04
│ └── src
│ │ ├── components
│ │ ├── button
│ │ │ ├── button.stories.tsx
│ │ │ ├── button.tsx
│ │ │ └── index.ts
│ │ ├── content
│ │ │ ├── content.stories.tsx
│ │ │ ├── content.tsx
│ │ │ └── index.ts
│ │ ├── data-table
│ │ │ ├── data-table.stories.tsx
│ │ │ ├── data-table.tsx
│ │ │ └── index.ts
│ │ ├── form
│ │ │ ├── index.ts
│ │ │ ├── input-field.stories.tsx
│ │ │ └── input-field.tsx
│ │ ├── info-card
│ │ │ ├── index.ts
│ │ │ ├── info-card.stories.tsx
│ │ │ └── info-card.tsx
│ │ ├── link
│ │ │ ├── index.ts
│ │ │ ├── link.stories.tsx
│ │ │ └── link.tsx
│ │ ├── loading
│ │ │ ├── index.ts
│ │ │ ├── loading.stories.tsx
│ │ │ └── loading.tsx
│ │ ├── not-found
│ │ │ ├── index.ts
│ │ │ ├── not-found.stories.tsx
│ │ │ └── not-found.tsx
│ │ └── seo
│ │ │ ├── index.ts
│ │ │ └── seo.tsx
│ │ ├── config
│ │ ├── constants.ts
│ │ └── theme.ts
│ │ ├── features
│ │ ├── auth
│ │ │ ├── api
│ │ │ │ └── .gitkeep
│ │ │ ├── components
│ │ │ │ └── .gitkeep
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ ├── jobs
│ │ │ ├── api
│ │ │ │ └── .gitkeep
│ │ │ ├── components
│ │ │ │ ├── create-job-form
│ │ │ │ │ ├── create-job-form.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── dashboard-job-info
│ │ │ │ │ ├── dashboard-job-info.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── jobs-list
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── jobs-list.tsx
│ │ │ │ └── public-job-info
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── public-job-info.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ └── organizations
│ │ │ ├── api
│ │ │ └── .gitkeep
│ │ │ ├── components
│ │ │ └── organization-info
│ │ │ │ ├── index.ts
│ │ │ │ └── organization-info.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ └── index.ts
│ │ ├── layouts
│ │ ├── dashboard-layout.tsx
│ │ └── public-layout.tsx
│ │ ├── lib
│ │ └── .gitkeep
│ │ ├── pages
│ │ ├── 404.tsx
│ │ ├── _app.tsx
│ │ ├── dashboard
│ │ │ └── jobs
│ │ │ │ ├── [jobId].tsx
│ │ │ │ ├── create.tsx
│ │ │ │ └── index.tsx
│ │ ├── index.tsx
│ │ └── organizations
│ │ │ └── [organizationId]
│ │ │ ├── index.tsx
│ │ │ └── jobs
│ │ │ └── [jobId].tsx
│ │ ├── providers
│ │ └── app.tsx
│ │ ├── stores
│ │ └── .gitkeep
│ │ ├── testing
│ │ └── test-data.ts
│ │ ├── types
│ │ └── index.ts
│ │ └── utils
│ │ ├── format.ts
│ │ └── uid.ts
├── chapter-05-start
│ └── src
│ │ ├── components
│ │ ├── button
│ │ │ ├── button.stories.tsx
│ │ │ ├── button.tsx
│ │ │ └── index.ts
│ │ ├── content
│ │ │ ├── content.stories.tsx
│ │ │ ├── content.tsx
│ │ │ └── index.ts
│ │ ├── data-table
│ │ │ ├── data-table.stories.tsx
│ │ │ ├── data-table.tsx
│ │ │ └── index.ts
│ │ ├── form
│ │ │ ├── index.ts
│ │ │ ├── input-field.stories.tsx
│ │ │ └── input-field.tsx
│ │ ├── info-card
│ │ │ ├── index.ts
│ │ │ ├── info-card.stories.tsx
│ │ │ └── info-card.tsx
│ │ ├── link
│ │ │ ├── index.ts
│ │ │ ├── link.stories.tsx
│ │ │ └── link.tsx
│ │ ├── loading
│ │ │ ├── index.ts
│ │ │ ├── loading.stories.tsx
│ │ │ └── loading.tsx
│ │ ├── not-found
│ │ │ ├── index.ts
│ │ │ ├── not-found.stories.tsx
│ │ │ └── not-found.tsx
│ │ └── seo
│ │ │ ├── index.ts
│ │ │ └── seo.tsx
│ │ ├── config
│ │ ├── constants.ts
│ │ └── theme.ts
│ │ ├── features
│ │ ├── auth
│ │ │ ├── api
│ │ │ │ └── .gitkeep
│ │ │ ├── components
│ │ │ │ └── .gitkeep
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ ├── jobs
│ │ │ ├── api
│ │ │ │ └── .gitkeep
│ │ │ ├── components
│ │ │ │ ├── create-job-form
│ │ │ │ │ ├── create-job-form.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── dashboard-job-info
│ │ │ │ │ ├── dashboard-job-info.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── jobs-list
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── jobs-list.tsx
│ │ │ │ └── public-job-info
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── public-job-info.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ └── organizations
│ │ │ ├── api
│ │ │ └── .gitkeep
│ │ │ ├── components
│ │ │ └── organization-info
│ │ │ │ ├── index.ts
│ │ │ │ └── organization-info.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ └── index.ts
│ │ ├── layouts
│ │ ├── dashboard-layout.tsx
│ │ └── public-layout.tsx
│ │ ├── pages
│ │ ├── 404.tsx
│ │ ├── _app.tsx
│ │ ├── dashboard
│ │ │ └── jobs
│ │ │ │ ├── [jobId].tsx
│ │ │ │ ├── create.tsx
│ │ │ │ └── index.tsx
│ │ ├── index.tsx
│ │ └── organizations
│ │ │ └── [organizationId]
│ │ │ ├── index.tsx
│ │ │ └── jobs
│ │ │ └── [jobId].tsx
│ │ ├── providers
│ │ └── app.tsx
│ │ ├── stores
│ │ └── .gitkeep
│ │ ├── testing
│ │ ├── mocks
│ │ │ ├── browser.ts
│ │ │ ├── db.ts
│ │ │ ├── handlers
│ │ │ │ ├── auth.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── jobs.ts
│ │ │ │ └── organizations.ts
│ │ │ ├── index.ts
│ │ │ ├── initialize.ts
│ │ │ ├── seed-db.ts
│ │ │ ├── server.ts
│ │ │ └── utils.ts
│ │ └── test-data.ts
│ │ ├── types
│ │ └── index.ts
│ │ └── utils
│ │ ├── format.ts
│ │ └── uid.ts
├── chapter-05
│ └── src
│ │ ├── components
│ │ ├── button
│ │ │ ├── button.stories.tsx
│ │ │ ├── button.tsx
│ │ │ └── index.ts
│ │ ├── content
│ │ │ ├── content.stories.tsx
│ │ │ ├── content.tsx
│ │ │ └── index.ts
│ │ ├── data-table
│ │ │ ├── data-table.stories.tsx
│ │ │ ├── data-table.tsx
│ │ │ └── index.ts
│ │ ├── form
│ │ │ ├── index.ts
│ │ │ ├── input-field.stories.tsx
│ │ │ └── input-field.tsx
│ │ ├── info-card
│ │ │ ├── index.ts
│ │ │ ├── info-card.stories.tsx
│ │ │ └── info-card.tsx
│ │ ├── link
│ │ │ ├── index.ts
│ │ │ ├── link.stories.tsx
│ │ │ └── link.tsx
│ │ ├── loading
│ │ │ ├── index.ts
│ │ │ ├── loading.stories.tsx
│ │ │ └── loading.tsx
│ │ ├── not-found
│ │ │ ├── index.ts
│ │ │ ├── not-found.stories.tsx
│ │ │ └── not-found.tsx
│ │ └── seo
│ │ │ ├── index.ts
│ │ │ └── seo.tsx
│ │ ├── config
│ │ ├── constants.ts
│ │ └── theme.ts
│ │ ├── features
│ │ ├── auth
│ │ │ ├── api
│ │ │ │ └── .gitkeep
│ │ │ ├── components
│ │ │ │ └── .gitkeep
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ ├── jobs
│ │ │ ├── api
│ │ │ │ └── .gitkeep
│ │ │ ├── components
│ │ │ │ ├── create-job-form
│ │ │ │ │ ├── create-job-form.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── dashboard-job-info
│ │ │ │ │ ├── dashboard-job-info.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── jobs-list
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── jobs-list.tsx
│ │ │ │ └── public-job-info
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── public-job-info.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ └── organizations
│ │ │ ├── api
│ │ │ └── .gitkeep
│ │ │ ├── components
│ │ │ └── organization-info
│ │ │ │ ├── index.ts
│ │ │ │ └── organization-info.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ └── index.ts
│ │ ├── layouts
│ │ ├── dashboard-layout.tsx
│ │ └── public-layout.tsx
│ │ ├── lib
│ │ └── msw.tsx
│ │ ├── pages
│ │ ├── 404.tsx
│ │ ├── _app.tsx
│ │ ├── dashboard
│ │ │ └── jobs
│ │ │ │ ├── [jobId].tsx
│ │ │ │ ├── create.tsx
│ │ │ │ └── index.tsx
│ │ ├── index.tsx
│ │ └── organizations
│ │ │ └── [organizationId]
│ │ │ ├── index.tsx
│ │ │ └── jobs
│ │ │ └── [jobId].tsx
│ │ ├── providers
│ │ └── app.tsx
│ │ ├── stores
│ │ └── .gitkeep
│ │ ├── testing
│ │ ├── mocks
│ │ │ ├── browser.ts
│ │ │ ├── db.ts
│ │ │ ├── handlers
│ │ │ │ ├── auth.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── jobs.ts
│ │ │ │ └── organizations.ts
│ │ │ ├── index.ts
│ │ │ ├── initialize.ts
│ │ │ ├── seed-db.ts
│ │ │ ├── server.ts
│ │ │ └── utils.ts
│ │ └── test-data.ts
│ │ ├── types
│ │ └── index.ts
│ │ └── utils
│ │ ├── format.ts
│ │ └── uid.ts
├── chapter-06-start
│ └── src
│ │ ├── components
│ │ ├── button
│ │ │ ├── button.stories.tsx
│ │ │ ├── button.tsx
│ │ │ └── index.ts
│ │ ├── content
│ │ │ ├── content.stories.tsx
│ │ │ ├── content.tsx
│ │ │ └── index.ts
│ │ ├── data-table
│ │ │ ├── data-table.stories.tsx
│ │ │ ├── data-table.tsx
│ │ │ └── index.ts
│ │ ├── form
│ │ │ ├── index.ts
│ │ │ ├── input-field.stories.tsx
│ │ │ └── input-field.tsx
│ │ ├── info-card
│ │ │ ├── index.ts
│ │ │ ├── info-card.stories.tsx
│ │ │ └── info-card.tsx
│ │ ├── link
│ │ │ ├── index.ts
│ │ │ ├── link.stories.tsx
│ │ │ └── link.tsx
│ │ ├── loading
│ │ │ ├── index.ts
│ │ │ ├── loading.stories.tsx
│ │ │ └── loading.tsx
│ │ ├── not-found
│ │ │ ├── index.ts
│ │ │ ├── not-found.stories.tsx
│ │ │ └── not-found.tsx
│ │ └── seo
│ │ │ ├── index.ts
│ │ │ └── seo.tsx
│ │ ├── config
│ │ ├── constants.ts
│ │ └── theme.ts
│ │ ├── features
│ │ ├── auth
│ │ │ ├── api
│ │ │ │ └── .gitkeep
│ │ │ ├── components
│ │ │ │ └── .gitkeep
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ ├── jobs
│ │ │ ├── api
│ │ │ │ └── .gitkeep
│ │ │ ├── components
│ │ │ │ ├── create-job-form
│ │ │ │ │ ├── create-job-form.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── dashboard-job-info
│ │ │ │ │ ├── dashboard-job-info.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── jobs-list
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── jobs-list.tsx
│ │ │ │ └── public-job-info
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── public-job-info.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ └── organizations
│ │ │ ├── api
│ │ │ └── .gitkeep
│ │ │ ├── components
│ │ │ └── organization-info
│ │ │ │ ├── index.ts
│ │ │ │ └── organization-info.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ └── index.ts
│ │ ├── layouts
│ │ ├── dashboard-layout.tsx
│ │ └── public-layout.tsx
│ │ ├── lib
│ │ └── msw.tsx
│ │ ├── pages
│ │ ├── 404.tsx
│ │ ├── _app.tsx
│ │ ├── dashboard
│ │ │ └── jobs
│ │ │ │ ├── [jobId].tsx
│ │ │ │ ├── create.tsx
│ │ │ │ └── index.tsx
│ │ ├── index.tsx
│ │ └── organizations
│ │ │ └── [organizationId]
│ │ │ ├── index.tsx
│ │ │ └── jobs
│ │ │ └── [jobId].tsx
│ │ ├── providers
│ │ └── app.tsx
│ │ ├── stores
│ │ └── .gitkeep
│ │ ├── testing
│ │ ├── mocks
│ │ │ ├── browser.ts
│ │ │ ├── db.ts
│ │ │ ├── handlers
│ │ │ │ ├── auth.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── jobs.ts
│ │ │ │ └── organizations.ts
│ │ │ ├── index.ts
│ │ │ ├── initialize.ts
│ │ │ ├── seed-db.ts
│ │ │ ├── server.ts
│ │ │ └── utils.ts
│ │ └── test-data.ts
│ │ ├── types
│ │ └── index.ts
│ │ └── utils
│ │ ├── format.ts
│ │ └── uid.ts
├── chapter-06
│ └── src
│ │ ├── components
│ │ ├── button
│ │ │ ├── button.stories.tsx
│ │ │ ├── button.tsx
│ │ │ └── index.ts
│ │ ├── content
│ │ │ ├── content.stories.tsx
│ │ │ ├── content.tsx
│ │ │ └── index.ts
│ │ ├── data-table
│ │ │ ├── data-table.stories.tsx
│ │ │ ├── data-table.tsx
│ │ │ └── index.ts
│ │ ├── form
│ │ │ ├── index.ts
│ │ │ ├── input-field.stories.tsx
│ │ │ └── input-field.tsx
│ │ ├── info-card
│ │ │ ├── index.ts
│ │ │ ├── info-card.stories.tsx
│ │ │ └── info-card.tsx
│ │ ├── link
│ │ │ ├── index.ts
│ │ │ ├── link.stories.tsx
│ │ │ └── link.tsx
│ │ ├── loading
│ │ │ ├── index.ts
│ │ │ ├── loading.stories.tsx
│ │ │ └── loading.tsx
│ │ ├── not-found
│ │ │ ├── index.ts
│ │ │ ├── not-found.stories.tsx
│ │ │ └── not-found.tsx
│ │ └── seo
│ │ │ ├── index.ts
│ │ │ └── seo.tsx
│ │ ├── config
│ │ ├── constants.ts
│ │ └── theme.ts
│ │ ├── features
│ │ ├── auth
│ │ │ ├── api
│ │ │ │ └── .gitkeep
│ │ │ ├── components
│ │ │ │ └── .gitkeep
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ ├── jobs
│ │ │ ├── api
│ │ │ │ ├── create-job.ts
│ │ │ │ ├── get-job.ts
│ │ │ │ └── get-jobs.ts
│ │ │ ├── components
│ │ │ │ ├── create-job-form
│ │ │ │ │ ├── create-job-form.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── dashboard-job-info
│ │ │ │ │ ├── dashboard-job-info.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── jobs-list
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── jobs-list.tsx
│ │ │ │ └── public-job-info
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── public-job-info.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ └── organizations
│ │ │ ├── api
│ │ │ └── get-organization.ts
│ │ │ ├── components
│ │ │ └── organization-info
│ │ │ │ ├── index.ts
│ │ │ │ └── organization-info.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ └── index.ts
│ │ ├── layouts
│ │ ├── dashboard-layout.tsx
│ │ └── public-layout.tsx
│ │ ├── lib
│ │ ├── api-client.ts
│ │ ├── msw.tsx
│ │ └── react-query.ts
│ │ ├── pages
│ │ ├── 404.tsx
│ │ ├── _app.tsx
│ │ ├── dashboard
│ │ │ └── jobs
│ │ │ │ ├── [jobId].tsx
│ │ │ │ ├── create.tsx
│ │ │ │ └── index.tsx
│ │ ├── index.tsx
│ │ └── organizations
│ │ │ └── [organizationId]
│ │ │ ├── index.tsx
│ │ │ └── jobs
│ │ │ └── [jobId].tsx
│ │ ├── providers
│ │ └── app.tsx
│ │ ├── stores
│ │ └── .gitkeep
│ │ ├── testing
│ │ ├── mocks
│ │ │ ├── browser.ts
│ │ │ ├── db.ts
│ │ │ ├── handlers
│ │ │ │ ├── auth.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── jobs.ts
│ │ │ │ └── organizations.ts
│ │ │ ├── index.ts
│ │ │ ├── initialize.ts
│ │ │ ├── seed-db.ts
│ │ │ ├── server.ts
│ │ │ └── utils.ts
│ │ └── test-data.ts
│ │ ├── types
│ │ └── index.ts
│ │ └── utils
│ │ ├── format.ts
│ │ └── uid.ts
├── chapter-07-start
│ └── src
│ │ ├── components
│ │ ├── button
│ │ │ ├── button.stories.tsx
│ │ │ ├── button.tsx
│ │ │ └── index.ts
│ │ ├── content
│ │ │ ├── content.stories.tsx
│ │ │ ├── content.tsx
│ │ │ └── index.ts
│ │ ├── data-table
│ │ │ ├── data-table.stories.tsx
│ │ │ ├── data-table.tsx
│ │ │ └── index.ts
│ │ ├── form
│ │ │ ├── index.ts
│ │ │ ├── input-field.stories.tsx
│ │ │ └── input-field.tsx
│ │ ├── info-card
│ │ │ ├── index.ts
│ │ │ ├── info-card.stories.tsx
│ │ │ └── info-card.tsx
│ │ ├── link
│ │ │ ├── index.ts
│ │ │ ├── link.stories.tsx
│ │ │ └── link.tsx
│ │ ├── loading
│ │ │ ├── index.ts
│ │ │ ├── loading.stories.tsx
│ │ │ └── loading.tsx
│ │ ├── not-found
│ │ │ ├── index.ts
│ │ │ ├── not-found.stories.tsx
│ │ │ └── not-found.tsx
│ │ ├── notifications
│ │ │ ├── index.ts
│ │ │ └── notifications.tsx
│ │ └── seo
│ │ │ ├── index.ts
│ │ │ └── seo.tsx
│ │ ├── config
│ │ ├── constants.ts
│ │ └── theme.ts
│ │ ├── features
│ │ ├── auth
│ │ │ ├── api
│ │ │ │ └── .gitkeep
│ │ │ ├── components
│ │ │ │ ├── login-form
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── login-form.tsx
│ │ │ │ └── protected
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── protected.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ ├── jobs
│ │ │ ├── api
│ │ │ │ ├── create-job.ts
│ │ │ │ ├── get-job.ts
│ │ │ │ └── get-jobs.ts
│ │ │ ├── components
│ │ │ │ ├── create-job-form
│ │ │ │ │ ├── create-job-form.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── dashboard-job-info
│ │ │ │ │ ├── dashboard-job-info.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── jobs-list
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── jobs-list.tsx
│ │ │ │ └── public-job-info
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── public-job-info.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ └── organizations
│ │ │ ├── api
│ │ │ └── get-organization.ts
│ │ │ ├── components
│ │ │ └── organization-info
│ │ │ │ ├── index.ts
│ │ │ │ └── organization-info.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ └── index.ts
│ │ ├── layouts
│ │ ├── auth-layout.tsx
│ │ ├── dashboard-layout.tsx
│ │ └── public-layout.tsx
│ │ ├── lib
│ │ ├── api-client.ts
│ │ ├── msw.tsx
│ │ └── react-query.ts
│ │ ├── pages
│ │ ├── 404.tsx
│ │ ├── _app.tsx
│ │ ├── auth
│ │ │ └── login.tsx
│ │ ├── dashboard
│ │ │ └── jobs
│ │ │ │ ├── [jobId].tsx
│ │ │ │ ├── create.tsx
│ │ │ │ └── index.tsx
│ │ ├── index.tsx
│ │ └── organizations
│ │ │ └── [organizationId]
│ │ │ ├── index.tsx
│ │ │ └── jobs
│ │ │ └── [jobId].tsx
│ │ ├── providers
│ │ └── app.tsx
│ │ ├── stores
│ │ └── notifications
│ │ │ ├── index.ts
│ │ │ └── notifications.ts
│ │ ├── testing
│ │ ├── mocks
│ │ │ ├── browser.ts
│ │ │ ├── db.ts
│ │ │ ├── handlers
│ │ │ │ ├── auth.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── jobs.ts
│ │ │ │ └── organizations.ts
│ │ │ ├── index.ts
│ │ │ ├── initialize.ts
│ │ │ ├── seed-db.ts
│ │ │ ├── server.ts
│ │ │ └── utils.ts
│ │ └── test-data.ts
│ │ ├── types
│ │ └── index.ts
│ │ └── utils
│ │ ├── format.ts
│ │ └── uid.ts
├── chapter-07
│ └── src
│ │ ├── components
│ │ ├── button
│ │ │ ├── button.stories.tsx
│ │ │ ├── button.tsx
│ │ │ └── index.ts
│ │ ├── content
│ │ │ ├── content.stories.tsx
│ │ │ ├── content.tsx
│ │ │ └── index.ts
│ │ ├── data-table
│ │ │ ├── data-table.stories.tsx
│ │ │ ├── data-table.tsx
│ │ │ └── index.ts
│ │ ├── form
│ │ │ ├── index.ts
│ │ │ ├── input-field.stories.tsx
│ │ │ └── input-field.tsx
│ │ ├── info-card
│ │ │ ├── index.ts
│ │ │ ├── info-card.stories.tsx
│ │ │ └── info-card.tsx
│ │ ├── link
│ │ │ ├── index.ts
│ │ │ ├── link.stories.tsx
│ │ │ └── link.tsx
│ │ ├── loading
│ │ │ ├── index.ts
│ │ │ ├── loading.stories.tsx
│ │ │ └── loading.tsx
│ │ ├── not-found
│ │ │ ├── index.ts
│ │ │ ├── not-found.stories.tsx
│ │ │ └── not-found.tsx
│ │ ├── notifications
│ │ │ ├── index.ts
│ │ │ └── notifications.tsx
│ │ └── seo
│ │ │ ├── index.ts
│ │ │ └── seo.tsx
│ │ ├── config
│ │ ├── constants.ts
│ │ └── theme.ts
│ │ ├── features
│ │ ├── auth
│ │ │ ├── api
│ │ │ │ ├── get-auth-user.ts
│ │ │ │ ├── login.ts
│ │ │ │ └── logout.ts
│ │ │ ├── components
│ │ │ │ ├── login-form
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── login-form.tsx
│ │ │ │ └── protected
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── protected.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ ├── jobs
│ │ │ ├── api
│ │ │ │ ├── create-job.ts
│ │ │ │ ├── get-job.ts
│ │ │ │ └── get-jobs.ts
│ │ │ ├── components
│ │ │ │ ├── create-job-form
│ │ │ │ │ ├── create-job-form.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── dashboard-job-info
│ │ │ │ │ ├── dashboard-job-info.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── jobs-list
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── jobs-list.tsx
│ │ │ │ └── public-job-info
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── public-job-info.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ └── organizations
│ │ │ ├── api
│ │ │ └── get-organization.ts
│ │ │ ├── components
│ │ │ └── organization-info
│ │ │ │ ├── index.ts
│ │ │ │ └── organization-info.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ └── index.ts
│ │ ├── layouts
│ │ ├── auth-layout.tsx
│ │ ├── dashboard-layout.tsx
│ │ └── public-layout.tsx
│ │ ├── lib
│ │ ├── api-client.ts
│ │ ├── msw.tsx
│ │ └── react-query.ts
│ │ ├── pages
│ │ ├── 404.tsx
│ │ ├── _app.tsx
│ │ ├── auth
│ │ │ └── login.tsx
│ │ ├── dashboard
│ │ │ └── jobs
│ │ │ │ ├── [jobId].tsx
│ │ │ │ ├── create.tsx
│ │ │ │ └── index.tsx
│ │ ├── index.tsx
│ │ └── organizations
│ │ │ └── [organizationId]
│ │ │ ├── index.tsx
│ │ │ └── jobs
│ │ │ └── [jobId].tsx
│ │ ├── providers
│ │ └── app.tsx
│ │ ├── stores
│ │ └── notifications
│ │ │ ├── index.ts
│ │ │ └── notifications.ts
│ │ ├── testing
│ │ ├── mocks
│ │ │ ├── browser.ts
│ │ │ ├── db.ts
│ │ │ ├── handlers
│ │ │ │ ├── auth.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── jobs.ts
│ │ │ │ └── organizations.ts
│ │ │ ├── index.ts
│ │ │ ├── initialize.ts
│ │ │ ├── seed-db.ts
│ │ │ ├── server.ts
│ │ │ └── utils.ts
│ │ └── test-data.ts
│ │ ├── types
│ │ └── index.ts
│ │ └── utils
│ │ ├── format.ts
│ │ └── uid.ts
├── chapter-08-start
│ ├── cypress.config.ts
│ ├── cypress
│ │ ├── e2e
│ │ │ ├── dashboard.cy.ts
│ │ │ └── public.cy.ts
│ │ ├── fixtures
│ │ │ └── example.json
│ │ ├── plugins
│ │ │ └── index.ts
│ │ ├── support
│ │ │ ├── commands.ts
│ │ │ └── e2e.ts
│ │ └── tsconfig.json
│ ├── jest.config.js
│ └── src
│ │ ├── __tests__
│ │ ├── dashboard-create-job-page.test.tsx
│ │ ├── dashboard-job-page.test.tsx
│ │ ├── dashboard-jobs-page.test.tsx
│ │ ├── login-page.test.tsx
│ │ ├── public-job-page.test.tsx
│ │ └── public-organization-page.test.tsx
│ │ ├── components
│ │ ├── button
│ │ │ ├── button.stories.tsx
│ │ │ ├── button.tsx
│ │ │ └── index.ts
│ │ ├── content
│ │ │ ├── content.stories.tsx
│ │ │ ├── content.tsx
│ │ │ └── index.ts
│ │ ├── data-table
│ │ │ ├── data-table.stories.tsx
│ │ │ ├── data-table.tsx
│ │ │ └── index.ts
│ │ ├── form
│ │ │ ├── index.ts
│ │ │ ├── input-field.stories.tsx
│ │ │ └── input-field.tsx
│ │ ├── info-card
│ │ │ ├── index.ts
│ │ │ ├── info-card.stories.tsx
│ │ │ └── info-card.tsx
│ │ ├── link
│ │ │ ├── index.ts
│ │ │ ├── link.stories.tsx
│ │ │ └── link.tsx
│ │ ├── loading
│ │ │ ├── index.ts
│ │ │ ├── loading.stories.tsx
│ │ │ └── loading.tsx
│ │ ├── not-found
│ │ │ ├── index.ts
│ │ │ ├── not-found.stories.tsx
│ │ │ └── not-found.tsx
│ │ ├── notifications
│ │ │ ├── index.ts
│ │ │ ├── notifications.stories.tsx
│ │ │ └── notifications.tsx
│ │ └── seo
│ │ │ ├── index.ts
│ │ │ └── seo.tsx
│ │ ├── config
│ │ ├── constants.ts
│ │ └── theme.ts
│ │ ├── features
│ │ ├── auth
│ │ │ ├── api
│ │ │ │ ├── get-auth-user.ts
│ │ │ │ ├── login.ts
│ │ │ │ └── logout.ts
│ │ │ ├── components
│ │ │ │ ├── login-form
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── login-form.tsx
│ │ │ │ └── protected
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── protected.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ ├── jobs
│ │ │ ├── api
│ │ │ │ ├── create-job.ts
│ │ │ │ ├── get-job.ts
│ │ │ │ └── get-jobs.ts
│ │ │ ├── components
│ │ │ │ ├── create-job-form
│ │ │ │ │ ├── create-job-form.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── dashboard-job-info
│ │ │ │ │ ├── dashboard-job-info.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── jobs-list
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── jobs-list.tsx
│ │ │ │ └── public-job-info
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── public-job-info.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ └── organizations
│ │ │ ├── api
│ │ │ └── get-organization.ts
│ │ │ ├── components
│ │ │ └── organization-info
│ │ │ │ ├── index.ts
│ │ │ │ └── organization-info.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ └── index.ts
│ │ ├── layouts
│ │ ├── auth-layout.tsx
│ │ ├── dashboard-layout.tsx
│ │ └── public-layout.tsx
│ │ ├── lib
│ │ ├── api-client.ts
│ │ ├── msw.tsx
│ │ └── react-query.ts
│ │ ├── pages
│ │ ├── 404.tsx
│ │ ├── _app.tsx
│ │ ├── auth
│ │ │ └── login.tsx
│ │ ├── dashboard
│ │ │ └── jobs
│ │ │ │ ├── [jobId].tsx
│ │ │ │ ├── create.tsx
│ │ │ │ └── index.tsx
│ │ ├── index.tsx
│ │ └── organizations
│ │ │ └── [organizationId]
│ │ │ ├── index.tsx
│ │ │ └── jobs
│ │ │ └── [jobId].tsx
│ │ ├── providers
│ │ └── app.tsx
│ │ ├── stores
│ │ └── notifications
│ │ │ ├── __tests__
│ │ │ └── notifications.test.ts
│ │ │ ├── index.ts
│ │ │ └── notifications.ts
│ │ ├── testing
│ │ ├── mocks
│ │ │ ├── browser.ts
│ │ │ ├── db.ts
│ │ │ ├── handlers
│ │ │ │ ├── auth.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── jobs.ts
│ │ │ │ └── organizations.ts
│ │ │ ├── index.ts
│ │ │ ├── initialize.ts
│ │ │ ├── seed-db.ts
│ │ │ ├── server.ts
│ │ │ └── utils.ts
│ │ ├── setup-tests.ts
│ │ ├── test-data.ts
│ │ └── test-utils.ts
│ │ ├── types
│ │ └── index.ts
│ │ └── utils
│ │ ├── format.ts
│ │ └── uid.ts
├── chapter-08
│ ├── cypress.config.ts
│ ├── cypress
│ │ ├── e2e
│ │ │ ├── dashboard.cy.ts
│ │ │ └── public.cy.ts
│ │ ├── fixtures
│ │ │ └── example.json
│ │ ├── plugins
│ │ │ └── index.ts
│ │ ├── support
│ │ │ ├── commands.ts
│ │ │ └── e2e.ts
│ │ └── tsconfig.json
│ ├── jest.config.js
│ └── src
│ │ ├── __tests__
│ │ ├── dashboard-create-job-page.test.tsx
│ │ ├── dashboard-job-page.test.tsx
│ │ ├── dashboard-jobs-page.test.tsx
│ │ ├── login-page.test.tsx
│ │ ├── public-job-page.test.tsx
│ │ └── public-organization-page.test.tsx
│ │ ├── components
│ │ ├── button
│ │ │ ├── button.stories.tsx
│ │ │ ├── button.tsx
│ │ │ └── index.ts
│ │ ├── content
│ │ │ ├── content.stories.tsx
│ │ │ ├── content.tsx
│ │ │ └── index.ts
│ │ ├── data-table
│ │ │ ├── data-table.stories.tsx
│ │ │ ├── data-table.tsx
│ │ │ └── index.ts
│ │ ├── form
│ │ │ ├── index.ts
│ │ │ ├── input-field.stories.tsx
│ │ │ └── input-field.tsx
│ │ ├── info-card
│ │ │ ├── index.ts
│ │ │ ├── info-card.stories.tsx
│ │ │ └── info-card.tsx
│ │ ├── link
│ │ │ ├── index.ts
│ │ │ ├── link.stories.tsx
│ │ │ └── link.tsx
│ │ ├── loading
│ │ │ ├── index.ts
│ │ │ ├── loading.stories.tsx
│ │ │ └── loading.tsx
│ │ ├── not-found
│ │ │ ├── index.ts
│ │ │ ├── not-found.stories.tsx
│ │ │ └── not-found.tsx
│ │ ├── notifications
│ │ │ ├── index.ts
│ │ │ ├── notifications.stories.tsx
│ │ │ └── notifications.tsx
│ │ └── seo
│ │ │ ├── index.ts
│ │ │ └── seo.tsx
│ │ ├── config
│ │ ├── constants.ts
│ │ └── theme.ts
│ │ ├── features
│ │ ├── auth
│ │ │ ├── api
│ │ │ │ ├── get-auth-user.ts
│ │ │ │ ├── login.ts
│ │ │ │ └── logout.ts
│ │ │ ├── components
│ │ │ │ ├── login-form
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── login-form.tsx
│ │ │ │ └── protected
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── protected.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ ├── jobs
│ │ │ ├── api
│ │ │ │ ├── create-job.ts
│ │ │ │ ├── get-job.ts
│ │ │ │ └── get-jobs.ts
│ │ │ ├── components
│ │ │ │ ├── create-job-form
│ │ │ │ │ ├── create-job-form.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── dashboard-job-info
│ │ │ │ │ ├── dashboard-job-info.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── jobs-list
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── jobs-list.tsx
│ │ │ │ └── public-job-info
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── public-job-info.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ └── organizations
│ │ │ ├── api
│ │ │ └── get-organization.ts
│ │ │ ├── components
│ │ │ └── organization-info
│ │ │ │ ├── index.ts
│ │ │ │ └── organization-info.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ └── index.ts
│ │ ├── layouts
│ │ ├── auth-layout.tsx
│ │ ├── dashboard-layout.tsx
│ │ └── public-layout.tsx
│ │ ├── lib
│ │ ├── api-client.ts
│ │ ├── msw.tsx
│ │ └── react-query.ts
│ │ ├── pages
│ │ ├── 404.tsx
│ │ ├── _app.tsx
│ │ ├── auth
│ │ │ └── login.tsx
│ │ ├── dashboard
│ │ │ └── jobs
│ │ │ │ ├── [jobId].tsx
│ │ │ │ ├── create.tsx
│ │ │ │ └── index.tsx
│ │ ├── index.tsx
│ │ └── organizations
│ │ │ └── [organizationId]
│ │ │ ├── index.tsx
│ │ │ └── jobs
│ │ │ └── [jobId].tsx
│ │ ├── providers
│ │ └── app.tsx
│ │ ├── stores
│ │ └── notifications
│ │ │ ├── __tests__
│ │ │ └── notifications.test.ts
│ │ │ ├── index.ts
│ │ │ └── notifications.ts
│ │ ├── testing
│ │ ├── mocks
│ │ │ ├── browser.ts
│ │ │ ├── db.ts
│ │ │ ├── handlers
│ │ │ │ ├── auth.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── jobs.ts
│ │ │ │ └── organizations.ts
│ │ │ ├── index.ts
│ │ │ ├── initialize.ts
│ │ │ ├── seed-db.ts
│ │ │ ├── server.ts
│ │ │ └── utils.ts
│ │ ├── setup-tests.ts
│ │ ├── test-data.ts
│ │ └── test-utils.ts
│ │ ├── types
│ │ └── index.ts
│ │ └── utils
│ │ ├── format.ts
│ │ └── uid.ts
├── chapter-09-start
│ ├── cypress.config.ts
│ ├── cypress
│ │ ├── e2e
│ │ │ ├── dashboard.cy.ts
│ │ │ └── public.cy.ts
│ │ ├── fixtures
│ │ │ └── example.json
│ │ ├── plugins
│ │ │ └── index.ts
│ │ ├── support
│ │ │ ├── commands.ts
│ │ │ └── e2e.ts
│ │ └── tsconfig.json
│ ├── jest.config.js
│ └── src
│ │ ├── __tests__
│ │ ├── dashboard-create-job-page.test.tsx
│ │ ├── dashboard-job-page.test.tsx
│ │ ├── dashboard-jobs-page.test.tsx
│ │ ├── login-page.test.tsx
│ │ ├── public-job-page.test.tsx
│ │ └── public-organization-page.test.tsx
│ │ ├── components
│ │ ├── button
│ │ │ ├── button.stories.tsx
│ │ │ ├── button.tsx
│ │ │ └── index.ts
│ │ ├── content
│ │ │ ├── content.stories.tsx
│ │ │ ├── content.tsx
│ │ │ └── index.ts
│ │ ├── data-table
│ │ │ ├── data-table.stories.tsx
│ │ │ ├── data-table.tsx
│ │ │ └── index.ts
│ │ ├── form
│ │ │ ├── index.ts
│ │ │ ├── input-field.stories.tsx
│ │ │ └── input-field.tsx
│ │ ├── info-card
│ │ │ ├── index.ts
│ │ │ ├── info-card.stories.tsx
│ │ │ └── info-card.tsx
│ │ ├── link
│ │ │ ├── index.ts
│ │ │ ├── link.stories.tsx
│ │ │ └── link.tsx
│ │ ├── loading
│ │ │ ├── index.ts
│ │ │ ├── loading.stories.tsx
│ │ │ └── loading.tsx
│ │ ├── not-found
│ │ │ ├── index.ts
│ │ │ ├── not-found.stories.tsx
│ │ │ └── not-found.tsx
│ │ ├── notifications
│ │ │ ├── index.ts
│ │ │ ├── notifications.stories.tsx
│ │ │ └── notifications.tsx
│ │ └── seo
│ │ │ ├── index.ts
│ │ │ └── seo.tsx
│ │ ├── config
│ │ ├── constants.ts
│ │ └── theme.ts
│ │ ├── features
│ │ ├── auth
│ │ │ ├── api
│ │ │ │ ├── get-auth-user.ts
│ │ │ │ ├── login.ts
│ │ │ │ └── logout.ts
│ │ │ ├── components
│ │ │ │ ├── login-form
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── login-form.tsx
│ │ │ │ └── protected
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── protected.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ ├── jobs
│ │ │ ├── api
│ │ │ │ ├── create-job.ts
│ │ │ │ ├── get-job.ts
│ │ │ │ └── get-jobs.ts
│ │ │ ├── components
│ │ │ │ ├── create-job-form
│ │ │ │ │ ├── create-job-form.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── dashboard-job-info
│ │ │ │ │ ├── dashboard-job-info.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── jobs-list
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── jobs-list.tsx
│ │ │ │ └── public-job-info
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── public-job-info.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ └── organizations
│ │ │ ├── api
│ │ │ └── get-organization.ts
│ │ │ ├── components
│ │ │ └── organization-info
│ │ │ │ ├── index.ts
│ │ │ │ └── organization-info.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ └── index.ts
│ │ ├── layouts
│ │ ├── auth-layout.tsx
│ │ ├── dashboard-layout.tsx
│ │ └── public-layout.tsx
│ │ ├── lib
│ │ ├── api-client.ts
│ │ ├── msw.tsx
│ │ └── react-query.ts
│ │ ├── pages
│ │ ├── 404.tsx
│ │ ├── _app.tsx
│ │ ├── auth
│ │ │ └── login.tsx
│ │ ├── dashboard
│ │ │ └── jobs
│ │ │ │ ├── [jobId].tsx
│ │ │ │ ├── create.tsx
│ │ │ │ └── index.tsx
│ │ ├── index.tsx
│ │ └── organizations
│ │ │ └── [organizationId]
│ │ │ ├── index.tsx
│ │ │ └── jobs
│ │ │ └── [jobId].tsx
│ │ ├── providers
│ │ └── app.tsx
│ │ ├── stores
│ │ └── notifications
│ │ │ ├── __tests__
│ │ │ └── notifications.test.ts
│ │ │ ├── index.ts
│ │ │ └── notifications.ts
│ │ ├── testing
│ │ ├── mocks
│ │ │ ├── browser.ts
│ │ │ ├── db.ts
│ │ │ ├── handlers
│ │ │ │ ├── auth.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── jobs.ts
│ │ │ │ └── organizations.ts
│ │ │ ├── index.ts
│ │ │ ├── initialize.ts
│ │ │ ├── seed-db.ts
│ │ │ ├── server.ts
│ │ │ └── utils.ts
│ │ ├── setup-tests.ts
│ │ ├── test-data.ts
│ │ └── test-utils.ts
│ │ ├── types
│ │ └── index.ts
│ │ └── utils
│ │ ├── format.ts
│ │ └── uid.ts
└── chapter-09
│ ├── .github
│ └── workflows
│ │ └── main.yml
│ ├── cypress.config.ts
│ ├── cypress
│ ├── e2e
│ │ ├── dashboard.cy.ts
│ │ └── public.cy.ts
│ ├── fixtures
│ │ └── example.json
│ ├── plugins
│ │ └── index.ts
│ ├── support
│ │ ├── commands.ts
│ │ └── e2e.ts
│ └── tsconfig.json
│ ├── jest.config.js
│ ├── src
│ ├── __tests__
│ │ ├── dashboard-create-job-page.test.tsx
│ │ ├── dashboard-job-page.test.tsx
│ │ ├── dashboard-jobs-page.test.tsx
│ │ ├── login-page.test.tsx
│ │ ├── public-job-page.test.tsx
│ │ └── public-organization-page.test.tsx
│ ├── components
│ │ ├── button
│ │ │ ├── button.stories.tsx
│ │ │ ├── button.tsx
│ │ │ └── index.ts
│ │ ├── content
│ │ │ ├── content.stories.tsx
│ │ │ ├── content.tsx
│ │ │ └── index.ts
│ │ ├── data-table
│ │ │ ├── data-table.stories.tsx
│ │ │ ├── data-table.tsx
│ │ │ └── index.ts
│ │ ├── form
│ │ │ ├── index.ts
│ │ │ ├── input-field.stories.tsx
│ │ │ └── input-field.tsx
│ │ ├── info-card
│ │ │ ├── index.ts
│ │ │ ├── info-card.stories.tsx
│ │ │ └── info-card.tsx
│ │ ├── link
│ │ │ ├── index.ts
│ │ │ ├── link.stories.tsx
│ │ │ └── link.tsx
│ │ ├── loading
│ │ │ ├── index.ts
│ │ │ ├── loading.stories.tsx
│ │ │ └── loading.tsx
│ │ ├── not-found
│ │ │ ├── index.ts
│ │ │ ├── not-found.stories.tsx
│ │ │ └── not-found.tsx
│ │ ├── notifications
│ │ │ ├── index.ts
│ │ │ ├── notifications.stories.tsx
│ │ │ └── notifications.tsx
│ │ └── seo
│ │ │ ├── index.ts
│ │ │ └── seo.tsx
│ ├── config
│ │ ├── constants.ts
│ │ └── theme.ts
│ ├── features
│ │ ├── auth
│ │ │ ├── api
│ │ │ │ ├── get-auth-user.ts
│ │ │ │ ├── login.ts
│ │ │ │ └── logout.ts
│ │ │ ├── components
│ │ │ │ ├── login-form
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── login-form.tsx
│ │ │ │ └── protected
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── protected.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ ├── jobs
│ │ │ ├── api
│ │ │ │ ├── create-job.ts
│ │ │ │ ├── get-job.ts
│ │ │ │ └── get-jobs.ts
│ │ │ ├── components
│ │ │ │ ├── create-job-form
│ │ │ │ │ ├── create-job-form.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── dashboard-job-info
│ │ │ │ │ ├── dashboard-job-info.tsx
│ │ │ │ │ └── index.ts
│ │ │ │ ├── jobs-list
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── jobs-list.tsx
│ │ │ │ └── public-job-info
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── public-job-info.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ │ └── index.ts
│ │ └── organizations
│ │ │ ├── api
│ │ │ └── get-organization.ts
│ │ │ ├── components
│ │ │ └── organization-info
│ │ │ │ ├── index.ts
│ │ │ │ └── organization-info.tsx
│ │ │ ├── index.ts
│ │ │ └── types
│ │ │ └── index.ts
│ ├── layouts
│ │ ├── auth-layout.tsx
│ │ ├── dashboard-layout.tsx
│ │ └── public-layout.tsx
│ ├── lib
│ │ ├── api-client.ts
│ │ ├── msw.tsx
│ │ └── react-query.ts
│ ├── pages
│ │ ├── 404.tsx
│ │ ├── _app.tsx
│ │ ├── auth
│ │ │ └── login.tsx
│ │ ├── dashboard
│ │ │ └── jobs
│ │ │ │ ├── [jobId].tsx
│ │ │ │ ├── create.tsx
│ │ │ │ └── index.tsx
│ │ ├── index.tsx
│ │ └── organizations
│ │ │ └── [organizationId]
│ │ │ ├── index.tsx
│ │ │ └── jobs
│ │ │ └── [jobId].tsx
│ ├── providers
│ │ └── app.tsx
│ ├── stores
│ │ └── notifications
│ │ │ ├── __tests__
│ │ │ └── notifications.test.ts
│ │ │ ├── index.ts
│ │ │ └── notifications.ts
│ ├── testing
│ │ ├── mocks
│ │ │ ├── browser.ts
│ │ │ ├── db.ts
│ │ │ ├── handlers
│ │ │ │ ├── auth.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── jobs.ts
│ │ │ │ └── organizations.ts
│ │ │ ├── index.ts
│ │ │ ├── initialize.ts
│ │ │ ├── seed-db.ts
│ │ │ ├── server.ts
│ │ │ └── utils.ts
│ │ ├── setup-tests.ts
│ │ ├── test-data.ts
│ │ └── test-utils.ts
│ ├── types
│ │ └── index.ts
│ └── utils
│ │ ├── format.ts
│ │ └── uid.ts
│ └── vercel.json
├── lint-staged.config.js
├── next-env.d.ts
├── next.config.js
├── package-lock.json
├── package.json
├── public
├── favicon.ico
├── mockServiceWorker.js
└── vercel.svg
├── scripts
├── clear-stage.js
├── save-stage.js
├── switch-stage.js
└── utils.js
└── tsconfig.json
/.env.example:
--------------------------------------------------------------------------------
1 | NEXT_PUBLIC_API_URL=https://api.jobs-app.com
2 | NEXT_PUBLIC_API_MOCKING=true
3 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 |
2 | # dependencies
3 | /node_modules
4 |
5 | # testing
6 | /coverage
7 |
8 | # next.js
9 | /.next/
10 | /out/
11 |
12 | # production
13 | /build
14 |
15 |
16 | # others
17 | /code-stages
18 | /scripts
--------------------------------------------------------------------------------
/.husky/.gitignore:
--------------------------------------------------------------------------------
1 | _
2 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | npx lint-staged
5 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 |
2 | # dependencies
3 | /node_modules
4 |
5 | # testing
6 | /coverage
7 |
8 | # next.js
9 | /.next/
10 | /out/
11 |
12 | # production
13 | /build
14 |
15 |
16 | # others
17 | # /code-stages
18 | /scripts
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "endOfLine": "auto",
3 | "singleQuote": true,
4 | "printWidth": 58,
5 | "tabWidth": 2,
6 | "trailingComma": "es5"
7 | }
8 |
--------------------------------------------------------------------------------
/.storybook/preview.js:
--------------------------------------------------------------------------------
1 | import { theme } from '../src/config/theme';
2 |
3 | export const parameters = {
4 | actions: { argTypesRegex: '^on[A-Z].*' },
5 | controls: {
6 | matchers: {
7 | color: /(background|color)$/i,
8 | date: /Date$/,
9 | },
10 | },
11 | controls: { expanded: true },
12 | chakra: {
13 | theme,
14 | },
15 | };
16 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "dbaeumer.vscode-eslint",
4 | "esbenp.prettier-vscode",
5 | "dsznajder.es7-react-js-snippets"
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.formatOnSave": true,
3 | "editor.codeActionsOnSave": {
4 | "source.fixAll.eslint": true
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-02/src/components/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/config/theme.ts:
--------------------------------------------------------------------------------
1 | export const theme = {};
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/features/auth/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-02/src/features/auth/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/features/auth/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-02/src/features/auth/components/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/features/auth/index.ts:
--------------------------------------------------------------------------------
1 | // types:
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/features/auth/pages/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-02/src/features/auth/pages/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/features/auth/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type AuthUser = Entity & {
4 | email: string;
5 | organizationId: string;
6 | };
7 |
8 | export type LoginData = {
9 | email: string;
10 | password: string;
11 | };
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/features/jobs/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-02/src/features/jobs/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/features/jobs/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-02/src/features/jobs/components/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/features/jobs/index.ts:
--------------------------------------------------------------------------------
1 | // types:
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/features/jobs/pages/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-02/src/features/jobs/pages/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/features/jobs/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Job = Entity & {
4 | organizationId: string;
5 | position: string;
6 | info: string;
7 | location: string;
8 | department: string;
9 | };
10 |
11 | export type CreateJobData = Pick<
12 | Job,
13 | 'position' | 'department' | 'location' | 'info'
14 | >;
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/features/organizations/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-02/src/features/organizations/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/features/organizations/index.ts:
--------------------------------------------------------------------------------
1 | // types:
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/features/organizations/pages/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-02/src/features/organizations/pages/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/features/organizations/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Organization = Entity & {
4 | adminId: string;
5 | name: string;
6 | email: string;
7 | phone: string;
8 | info: string;
9 | };
10 |
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/layouts/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-02/src/layouts/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/lib/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-02/src/lib/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/pages/_app.tsx:
--------------------------------------------------------------------------------
1 | import type { AppProps } from 'next/app';
2 |
3 | import { AppProvider } from '@/providers/app';
4 |
5 | const App = ({ Component, pageProps }: AppProps) => {
6 | return (
7 |
8 |
9 |
10 | );
11 | };
12 |
13 | export default App;
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/pages/index.tsx:
--------------------------------------------------------------------------------
1 | const LandingPage = () => {
2 | return <>Landing Page>;
3 | };
4 |
5 | export default LandingPage;
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/providers/app.tsx:
--------------------------------------------------------------------------------
1 | import { ReactNode } from 'react';
2 |
3 | type AppProviderProps = {
4 | children: ReactNode;
5 | };
6 |
7 | export const AppProvider = ({
8 | children,
9 | }: AppProviderProps) => {
10 | return <>{children}>;
11 | };
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/stores/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-02/src/stores/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/testing/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-02/src/testing/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export type Entity = {
2 | id: string;
3 | createdAt: number;
4 | };
5 |
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/utils/format.ts:
--------------------------------------------------------------------------------
1 | export const formatDate = (date: number | string) => {
2 | return new Date(date).toLocaleDateString('en-US', {
3 | month: 'long',
4 | year: 'numeric',
5 | day: 'numeric',
6 | });
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-02/src/utils/uid.ts:
--------------------------------------------------------------------------------
1 | // https://gist.github.com/gordonbrander/2230317?permalink_comment_id=3443509#gistcomment-3443509
2 | export const uid = () => {
3 | return (
4 | performance.now().toString(36) +
5 | Math.random().toString(36)
6 | ).replace(/\./g, '');
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/components/button/button.tsx:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line @typescript-eslint/ban-types
2 | export type ButtonProps = {};
3 |
4 | export const Button = () => {
5 | return <>Button>;
6 | };
7 |
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/components/button/index.ts:
--------------------------------------------------------------------------------
1 | export * from './button';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/components/form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './input-field';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/components/form/input-field.tsx:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line @typescript-eslint/ban-types
2 | export type InputFieldProps = {};
3 |
4 | export const InputField = () => {
5 | return <>InputField>;
6 | };
7 |
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/components/link/index.ts:
--------------------------------------------------------------------------------
1 | export * from './link';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/components/link/link.tsx:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line @typescript-eslint/ban-types
2 | export type LinkProps = {};
3 |
4 | export const Link = () => {
5 | return <>Link>;
6 | };
7 |
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/config/theme.ts:
--------------------------------------------------------------------------------
1 | export const theme = {};
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/features/auth/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-03-start/src/features/auth/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/features/auth/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-03-start/src/features/auth/components/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/features/auth/index.ts:
--------------------------------------------------------------------------------
1 | // types:
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/features/auth/pages/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-03-start/src/features/auth/pages/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/features/auth/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type AuthUser = Entity & {
4 | email: string;
5 | organizationId: string;
6 | };
7 |
8 | export type LoginData = {
9 | email: string;
10 | password: string;
11 | };
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/features/jobs/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-03-start/src/features/jobs/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/features/jobs/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-03-start/src/features/jobs/components/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/features/jobs/index.ts:
--------------------------------------------------------------------------------
1 | // types:
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/features/jobs/pages/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-03-start/src/features/jobs/pages/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/features/jobs/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Job = Entity & {
4 | organizationId: string;
5 | position: string;
6 | info: string;
7 | location: string;
8 | department: string;
9 | };
10 |
11 | export type CreateJobData = Pick<
12 | Job,
13 | 'position' | 'department' | 'location' | 'info'
14 | >;
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/features/organizations/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-03-start/src/features/organizations/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/features/organizations/index.ts:
--------------------------------------------------------------------------------
1 | // types:
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/features/organizations/pages/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-03-start/src/features/organizations/pages/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/features/organizations/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Organization = Entity & {
4 | adminId: string;
5 | name: string;
6 | email: string;
7 | phone: string;
8 | info: string;
9 | };
10 |
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/layouts/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-03-start/src/layouts/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/lib/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-03-start/src/lib/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/pages/_app.tsx:
--------------------------------------------------------------------------------
1 | import type { AppProps } from 'next/app';
2 |
3 | import { AppProvider } from '@/providers/app';
4 |
5 | const App = ({ Component, pageProps }: AppProps) => {
6 | return (
7 |
8 |
9 |
10 | );
11 | };
12 |
13 | export default App;
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/pages/index.tsx:
--------------------------------------------------------------------------------
1 | const LandingPage = () => {
2 | return <>Landing Page>;
3 | };
4 |
5 | export default LandingPage;
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/providers/app.tsx:
--------------------------------------------------------------------------------
1 | import { ReactNode } from 'react';
2 |
3 | type AppProviderProps = {
4 | children: ReactNode;
5 | };
6 |
7 | export const AppProvider = ({
8 | children,
9 | }: AppProviderProps) => {
10 | return <>{children}>;
11 | };
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/stores/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-03-start/src/stores/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/testing/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-03-start/src/testing/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export type Entity = {
2 | id: string;
3 | createdAt: number;
4 | };
5 |
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/utils/format.ts:
--------------------------------------------------------------------------------
1 | export const formatDate = (date: number | string) => {
2 | return new Date(date).toLocaleDateString('en-US', {
3 | month: 'long',
4 | year: 'numeric',
5 | day: 'numeric',
6 | });
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-03-start/src/utils/uid.ts:
--------------------------------------------------------------------------------
1 | // https://gist.github.com/gordonbrander/2230317?permalink_comment_id=3443509#gistcomment-3443509
2 | export const uid = () => {
3 | return (
4 | performance.now().toString(36) +
5 | Math.random().toString(36)
6 | ).replace(/\./g, '');
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/components/button/index.ts:
--------------------------------------------------------------------------------
1 | export * from './button';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/components/form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './input-field';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/components/link/index.ts:
--------------------------------------------------------------------------------
1 | export * from './link';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/components/link/link.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { Link, LinkProps } from './link';
4 |
5 | const meta: Meta = {
6 | title: 'Components/Link',
7 | component: Link,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => (
13 |
14 | );
15 |
16 | export const Default = Template.bind({});
17 |
18 | Default.args = {
19 | href: '/',
20 | children: 'Click Me',
21 | };
22 |
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/config/theme.ts:
--------------------------------------------------------------------------------
1 | import { extendTheme } from '@chakra-ui/react';
2 |
3 | const colors = {
4 | primary: '#1a365d',
5 | primaryAccent: '#ffffff',
6 | };
7 |
8 | const styles = {
9 | global: {
10 | 'html, body': {
11 | height: '100%',
12 | bg: 'gray.50',
13 | },
14 |
15 | '#__next': {
16 | height: '100%',
17 | bg: 'gray.50',
18 | },
19 | },
20 | };
21 |
22 | export const theme = extendTheme({ colors, styles });
23 |
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/features/auth/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-03/src/features/auth/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/features/auth/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-03/src/features/auth/components/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/features/auth/index.ts:
--------------------------------------------------------------------------------
1 | // types:
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/features/auth/pages/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-03/src/features/auth/pages/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/features/auth/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type AuthUser = Entity & {
4 | email: string;
5 | organizationId: string;
6 | };
7 |
8 | export type LoginData = {
9 | email: string;
10 | password: string;
11 | };
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/features/jobs/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-03/src/features/jobs/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/features/jobs/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-03/src/features/jobs/components/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/features/jobs/index.ts:
--------------------------------------------------------------------------------
1 | // types:
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/features/jobs/pages/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-03/src/features/jobs/pages/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/features/jobs/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Job = Entity & {
4 | organizationId: string;
5 | position: string;
6 | info: string;
7 | location: string;
8 | department: string;
9 | };
10 |
11 | export type CreateJobData = Pick<
12 | Job,
13 | 'position' | 'department' | 'location' | 'info'
14 | >;
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/features/organizations/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-03/src/features/organizations/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/features/organizations/index.ts:
--------------------------------------------------------------------------------
1 | // types:
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/features/organizations/pages/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-03/src/features/organizations/pages/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/features/organizations/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Organization = Entity & {
4 | adminId: string;
5 | name: string;
6 | email: string;
7 | phone: string;
8 | info: string;
9 | };
10 |
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/layouts/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-03/src/layouts/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/lib/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-03/src/lib/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/pages/_app.tsx:
--------------------------------------------------------------------------------
1 | import type { AppProps } from 'next/app';
2 |
3 | import { AppProvider } from '@/providers/app';
4 |
5 | const App = ({ Component, pageProps }: AppProps) => {
6 | return (
7 |
8 |
9 |
10 | );
11 | };
12 |
13 | export default App;
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/stores/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-03/src/stores/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/testing/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-03/src/testing/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export type Entity = {
2 | id: string;
3 | createdAt: number;
4 | };
5 |
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/utils/format.ts:
--------------------------------------------------------------------------------
1 | export const formatDate = (date: number | string) => {
2 | return new Date(date).toLocaleDateString('en-US', {
3 | month: 'long',
4 | year: 'numeric',
5 | day: 'numeric',
6 | });
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-03/src/utils/uid.ts:
--------------------------------------------------------------------------------
1 | // https://gist.github.com/gordonbrander/2230317?permalink_comment_id=3443509#gistcomment-3443509
2 | export const uid = () => {
3 | return (
4 | performance.now().toString(36) +
5 | Math.random().toString(36)
6 | ).replace(/\./g, '');
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/components/button/index.ts:
--------------------------------------------------------------------------------
1 | export * from './button';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/components/content/content.tsx:
--------------------------------------------------------------------------------
1 | import { Box } from '@chakra-ui/react';
2 |
3 | export type ContentProps = {
4 | children: string;
5 | };
6 |
7 | export const Content = ({ children }: ContentProps) => {
8 | return (
9 |
10 | {children}
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/components/content/index.ts:
--------------------------------------------------------------------------------
1 | export * from './content';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/components/data-table/index.ts:
--------------------------------------------------------------------------------
1 | export * from './data-table';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/components/form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './input-field';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/components/info-card/index.ts:
--------------------------------------------------------------------------------
1 | export * from './info-card';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/components/link/index.ts:
--------------------------------------------------------------------------------
1 | export * from './link';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/components/loading/index.ts:
--------------------------------------------------------------------------------
1 | export * from './loading';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/components/loading/loading.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { Loading } from './loading';
4 |
5 | const meta: Meta = {
6 | title: 'Components/Loading',
7 | component: Loading,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => ;
13 |
14 | export const Default = Template.bind({});
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/components/loading/loading.tsx:
--------------------------------------------------------------------------------
1 | import { Center, Spinner } from '@chakra-ui/react';
2 |
3 | export const Loading = () => {
4 | return (
5 |
6 |
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/components/not-found/index.ts:
--------------------------------------------------------------------------------
1 | export * from './not-found';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/components/not-found/not-found.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { NotFound } from './not-found';
4 |
5 | const meta: Meta = {
6 | title: 'Components/NotFound',
7 | component: NotFound,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => (
13 |
14 | );
15 |
16 | export const Default = Template.bind({});
17 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/components/not-found/not-found.tsx:
--------------------------------------------------------------------------------
1 | import { NotAllowedIcon } from '@chakra-ui/icons';
2 | import {
3 | Center,
4 | Heading,
5 | VStack,
6 | } from '@chakra-ui/react';
7 |
8 | export const NotFound = () => {
9 | return (
10 |
11 |
12 |
13 | Not Found
14 |
15 |
16 | );
17 | };
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/components/seo/index.ts:
--------------------------------------------------------------------------------
1 | export * from './seo';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/components/seo/seo.tsx:
--------------------------------------------------------------------------------
1 | export const Seo = () => {
2 | return <>Seo>;
3 | };
4 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/config/theme.ts:
--------------------------------------------------------------------------------
1 | import { extendTheme } from '@chakra-ui/react';
2 |
3 | const colors = {
4 | primary: '#1a365d',
5 | primaryAccent: 'white',
6 | };
7 |
8 | const styles = {
9 | global: {
10 | 'html, body': {
11 | height: '100%',
12 | bg: 'gray.50',
13 | },
14 |
15 | '#__next': {
16 | height: '100%',
17 | bg: 'gray.50',
18 | },
19 | },
20 | };
21 |
22 | export const theme = extendTheme({ colors, styles });
23 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/features/auth/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-04-start/src/features/auth/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/features/auth/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-04-start/src/features/auth/components/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/features/auth/index.ts:
--------------------------------------------------------------------------------
1 | // types:
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/features/auth/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type AuthUser = Entity & {
4 | email: string;
5 | organizationId: string;
6 | };
7 |
8 | export type LoginData = {
9 | email: string;
10 | password: string;
11 | };
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/features/jobs/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-04-start/src/features/jobs/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/features/jobs/components/create-job-form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './create-job-form';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/features/jobs/components/dashboard-job-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dashboard-job-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/features/jobs/components/jobs-list/index.ts:
--------------------------------------------------------------------------------
1 | export * from './jobs-list';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/features/jobs/components/public-job-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './public-job-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/features/jobs/index.ts:
--------------------------------------------------------------------------------
1 | // components:
2 | export * from './components/create-job-form';
3 | export * from './components/dashboard-job-info';
4 | export * from './components/jobs-list';
5 | export * from './components/public-job-info';
6 |
7 | // types:
8 | export * from './types';
9 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/features/jobs/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Job = Entity & {
4 | organizationId: string;
5 | position: string;
6 | info: string;
7 | location: string;
8 | department: string;
9 | };
10 |
11 | export type CreateJobData = Pick<
12 | Job,
13 | 'position' | 'department' | 'location' | 'info'
14 | >;
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/features/organizations/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-04-start/src/features/organizations/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/features/organizations/components/organization-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './organization-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/features/organizations/index.ts:
--------------------------------------------------------------------------------
1 | // components:
2 | export * from './components/organization-info';
3 |
4 | // types:
5 | export * from './types';
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/features/organizations/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Organization = Entity & {
4 | adminId: string;
5 | name: string;
6 | email: string;
7 | phone: string;
8 | info: string;
9 | };
10 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/lib/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-04-start/src/lib/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/pages/_app.tsx:
--------------------------------------------------------------------------------
1 | import type { AppProps } from 'next/app';
2 |
3 | import { AppProvider } from '@/providers/app';
4 |
5 | const App = ({ Component, pageProps }: AppProps) => {
6 | return (
7 |
8 |
9 |
10 | );
11 | };
12 |
13 | export default App;
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/stores/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-04-start/src/stores/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export type Entity = {
2 | id: string;
3 | createdAt: number;
4 | };
5 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/utils/format.ts:
--------------------------------------------------------------------------------
1 | export const formatDate = (date: number | string) => {
2 | return new Date(date).toLocaleDateString('en-US', {
3 | month: 'long',
4 | year: 'numeric',
5 | day: 'numeric',
6 | });
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-04-start/src/utils/uid.ts:
--------------------------------------------------------------------------------
1 | // https://gist.github.com/gordonbrander/2230317?permalink_comment_id=3443509#gistcomment-3443509
2 | export const uid = () => {
3 | return (
4 | performance.now().toString(36) +
5 | Math.random().toString(36)
6 | ).replace(/\./g, '');
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/components/button/index.ts:
--------------------------------------------------------------------------------
1 | export * from './button';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/components/content/content.tsx:
--------------------------------------------------------------------------------
1 | import { Box } from '@chakra-ui/react';
2 |
3 | export type ContentProps = {
4 | children: string;
5 | };
6 |
7 | export const Content = ({ children }: ContentProps) => {
8 | return (
9 |
10 | {children}
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/components/content/index.ts:
--------------------------------------------------------------------------------
1 | export * from './content';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/components/data-table/index.ts:
--------------------------------------------------------------------------------
1 | export * from './data-table';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/components/form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './input-field';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/components/info-card/index.ts:
--------------------------------------------------------------------------------
1 | export * from './info-card';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/components/link/index.ts:
--------------------------------------------------------------------------------
1 | export * from './link';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/components/link/link.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { Link, LinkProps } from './link';
4 |
5 | const meta: Meta = {
6 | title: 'Components/Link',
7 | component: Link,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => (
13 |
14 | );
15 |
16 | export const Default = Template.bind({});
17 |
18 | Default.args = {
19 | href: '/',
20 | children: 'Click Me',
21 | };
22 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/components/loading/index.ts:
--------------------------------------------------------------------------------
1 | export * from './loading';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/components/loading/loading.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { Loading } from './loading';
4 |
5 | const meta: Meta = {
6 | title: 'Components/Loading',
7 | component: Loading,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => ;
13 |
14 | export const Default = Template.bind({});
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/components/loading/loading.tsx:
--------------------------------------------------------------------------------
1 | import { Center, Spinner } from '@chakra-ui/react';
2 |
3 | export const Loading = () => {
4 | return (
5 |
6 |
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/components/not-found/index.ts:
--------------------------------------------------------------------------------
1 | export * from './not-found';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/components/not-found/not-found.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { NotFound } from './not-found';
4 |
5 | const meta: Meta = {
6 | title: 'Components/NotFound',
7 | component: NotFound,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => (
13 |
14 | );
15 |
16 | export const Default = Template.bind({});
17 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/components/not-found/not-found.tsx:
--------------------------------------------------------------------------------
1 | import { NotAllowedIcon } from '@chakra-ui/icons';
2 | import {
3 | Center,
4 | Heading,
5 | VStack,
6 | } from '@chakra-ui/react';
7 |
8 | export const NotFound = () => {
9 | return (
10 |
11 |
12 |
13 | Not Found
14 |
15 |
16 | );
17 | };
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/components/seo/index.ts:
--------------------------------------------------------------------------------
1 | export * from './seo';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/components/seo/seo.tsx:
--------------------------------------------------------------------------------
1 | import Head from 'next/head';
2 |
3 | export type SeoProps = {
4 | title: string;
5 | };
6 |
7 | export const Seo = ({ title }: SeoProps) => {
8 | return (
9 |
10 | {title}
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/config/theme.ts:
--------------------------------------------------------------------------------
1 | import { extendTheme } from '@chakra-ui/react';
2 |
3 | const colors = {
4 | primary: '#1a365d',
5 | primaryAccent: 'white',
6 | };
7 |
8 | const styles = {
9 | global: {
10 | 'html, body': {
11 | height: '100%',
12 | bg: 'gray.50',
13 | },
14 |
15 | '#__next': {
16 | height: '100%',
17 | bg: 'gray.50',
18 | },
19 | },
20 | };
21 |
22 | export const theme = extendTheme({ colors, styles });
23 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/features/auth/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-04/src/features/auth/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/features/auth/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-04/src/features/auth/components/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/features/auth/index.ts:
--------------------------------------------------------------------------------
1 | // types:
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/features/auth/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type AuthUser = Entity & {
4 | email: string;
5 | organizationId: string;
6 | };
7 |
8 | export type LoginData = {
9 | email: string;
10 | password: string;
11 | };
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/features/jobs/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-04/src/features/jobs/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/features/jobs/components/create-job-form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './create-job-form';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/features/jobs/components/dashboard-job-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dashboard-job-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/features/jobs/components/jobs-list/index.ts:
--------------------------------------------------------------------------------
1 | export * from './jobs-list';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/features/jobs/components/public-job-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './public-job-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/features/jobs/index.ts:
--------------------------------------------------------------------------------
1 | // components:
2 | export * from './components/create-job-form';
3 | export * from './components/dashboard-job-info';
4 | export * from './components/jobs-list';
5 | export * from './components/public-job-info';
6 |
7 | // types:
8 | export * from './types';
9 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/features/jobs/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Job = Entity & {
4 | organizationId: string;
5 | position: string;
6 | info: string;
7 | location: string;
8 | department: string;
9 | };
10 |
11 | export type CreateJobData = Pick<
12 | Job,
13 | 'position' | 'department' | 'location' | 'info'
14 | >;
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/features/organizations/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-04/src/features/organizations/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/features/organizations/components/organization-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './organization-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/features/organizations/index.ts:
--------------------------------------------------------------------------------
1 | // components:
2 | export * from './components/organization-info';
3 |
4 | // types:
5 | export * from './types';
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/features/organizations/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Organization = Entity & {
4 | adminId: string;
5 | name: string;
6 | email: string;
7 | phone: string;
8 | info: string;
9 | };
10 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/lib/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-04/src/lib/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/pages/404.tsx:
--------------------------------------------------------------------------------
1 | import { Center } from '@chakra-ui/react';
2 |
3 | import { Link } from '@/components/link';
4 | import { NotFound } from '@/components/not-found';
5 |
6 | const NotFoundPage = () => {
7 | return (
8 | <>
9 |
10 |
11 | Home
12 |
13 | >
14 | );
15 | };
16 |
17 | export default NotFoundPage;
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/stores/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-04/src/stores/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export type Entity = {
2 | id: string;
3 | createdAt: number;
4 | };
5 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/utils/format.ts:
--------------------------------------------------------------------------------
1 | export const formatDate = (date: number | string) => {
2 | return new Date(date).toLocaleDateString('en-US', {
3 | month: 'long',
4 | year: 'numeric',
5 | day: 'numeric',
6 | });
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-04/src/utils/uid.ts:
--------------------------------------------------------------------------------
1 | // https://gist.github.com/gordonbrander/2230317?permalink_comment_id=3443509#gistcomment-3443509
2 | export const uid = () => {
3 | return (
4 | performance.now().toString(36) +
5 | Math.random().toString(36)
6 | ).replace(/\./g, '');
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/components/button/index.ts:
--------------------------------------------------------------------------------
1 | export * from './button';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/components/content/content.tsx:
--------------------------------------------------------------------------------
1 | import { Box } from '@chakra-ui/react';
2 |
3 | export type ContentProps = {
4 | children: string;
5 | };
6 |
7 | export const Content = ({ children }: ContentProps) => {
8 | return (
9 |
10 | {children}
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/components/content/index.ts:
--------------------------------------------------------------------------------
1 | export * from './content';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/components/data-table/index.ts:
--------------------------------------------------------------------------------
1 | export * from './data-table';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/components/form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './input-field';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/components/info-card/index.ts:
--------------------------------------------------------------------------------
1 | export * from './info-card';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/components/link/index.ts:
--------------------------------------------------------------------------------
1 | export * from './link';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/components/loading/index.ts:
--------------------------------------------------------------------------------
1 | export * from './loading';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/components/loading/loading.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { Loading } from './loading';
4 |
5 | const meta: Meta = {
6 | title: 'Components/Loading',
7 | component: Loading,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => ;
13 |
14 | export const Default = Template.bind({});
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/components/loading/loading.tsx:
--------------------------------------------------------------------------------
1 | import { Center, Spinner } from '@chakra-ui/react';
2 |
3 | export const Loading = () => {
4 | return (
5 |
6 |
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/components/not-found/index.ts:
--------------------------------------------------------------------------------
1 | export * from './not-found';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/components/not-found/not-found.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { NotFound } from './not-found';
4 |
5 | const meta: Meta = {
6 | title: 'Components/NotFound',
7 | component: NotFound,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => (
13 |
14 | );
15 |
16 | export const Default = Template.bind({});
17 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/components/not-found/not-found.tsx:
--------------------------------------------------------------------------------
1 | import { NotAllowedIcon } from '@chakra-ui/icons';
2 | import {
3 | Center,
4 | Heading,
5 | VStack,
6 | } from '@chakra-ui/react';
7 |
8 | export const NotFound = () => {
9 | return (
10 |
11 |
12 |
13 | Not Found
14 |
15 |
16 | );
17 | };
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/components/seo/index.ts:
--------------------------------------------------------------------------------
1 | export * from './seo';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/components/seo/seo.tsx:
--------------------------------------------------------------------------------
1 | import Head from 'next/head';
2 |
3 | export type SeoProps = {
4 | title: string;
5 | };
6 |
7 | export const Seo = ({ title }: SeoProps) => {
8 | return (
9 |
10 | {title}
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/config/theme.ts:
--------------------------------------------------------------------------------
1 | import { extendTheme } from '@chakra-ui/react';
2 |
3 | const colors = {
4 | primary: '#1a365d',
5 | primaryAccent: 'white',
6 | };
7 |
8 | const styles = {
9 | global: {
10 | 'html, body': {
11 | height: '100%',
12 | bg: 'gray.50',
13 | },
14 |
15 | '#__next': {
16 | height: '100%',
17 | bg: 'gray.50',
18 | },
19 | },
20 | };
21 |
22 | export const theme = extendTheme({ colors, styles });
23 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/features/auth/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-05-start/src/features/auth/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/features/auth/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-05-start/src/features/auth/components/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/features/auth/index.ts:
--------------------------------------------------------------------------------
1 | // types:
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/features/auth/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type AuthUser = Entity & {
4 | email: string;
5 | organizationId: string;
6 | };
7 |
8 | export type LoginData = {
9 | email: string;
10 | password: string;
11 | };
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/features/jobs/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-05-start/src/features/jobs/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/features/jobs/components/create-job-form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './create-job-form';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/features/jobs/components/dashboard-job-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dashboard-job-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/features/jobs/components/jobs-list/index.ts:
--------------------------------------------------------------------------------
1 | export * from './jobs-list';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/features/jobs/components/public-job-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './public-job-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/features/jobs/index.ts:
--------------------------------------------------------------------------------
1 | // components:
2 | export * from './components/create-job-form';
3 | export * from './components/dashboard-job-info';
4 | export * from './components/jobs-list';
5 | export * from './components/public-job-info';
6 |
7 | // types:
8 | export * from './types';
9 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/features/jobs/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Job = Entity & {
4 | organizationId: string;
5 | position: string;
6 | info: string;
7 | location: string;
8 | department: string;
9 | };
10 |
11 | export type CreateJobData = Pick<
12 | Job,
13 | 'position' | 'department' | 'location' | 'info'
14 | >;
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/features/organizations/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-05-start/src/features/organizations/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/features/organizations/components/organization-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './organization-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/features/organizations/index.ts:
--------------------------------------------------------------------------------
1 | // components:
2 | export * from './components/organization-info';
3 |
4 | // types:
5 | export * from './types';
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/features/organizations/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Organization = Entity & {
4 | adminId: string;
5 | name: string;
6 | email: string;
7 | phone: string;
8 | info: string;
9 | };
10 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/pages/404.tsx:
--------------------------------------------------------------------------------
1 | import { Center } from '@chakra-ui/react';
2 |
3 | import { Link } from '@/components/link';
4 | import { NotFound } from '@/components/not-found';
5 |
6 | const NotFoundPage = () => {
7 | return (
8 | <>
9 |
10 |
11 | Home
12 |
13 | >
14 | );
15 | };
16 |
17 | export default NotFoundPage;
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/stores/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-05-start/src/stores/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/testing/mocks/browser.ts:
--------------------------------------------------------------------------------
1 | export const worker = {};
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/testing/mocks/db.ts:
--------------------------------------------------------------------------------
1 | export const db = {};
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/testing/mocks/handlers/auth.ts:
--------------------------------------------------------------------------------
1 | export const authHandlers = [];
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/testing/mocks/handlers/index.ts:
--------------------------------------------------------------------------------
1 | export const handlers = [];
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/testing/mocks/handlers/jobs.ts:
--------------------------------------------------------------------------------
1 | export const jobsHandlers = [];
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/testing/mocks/handlers/organizations.ts:
--------------------------------------------------------------------------------
1 | export const organizationsHandlers = [];
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/testing/mocks/index.ts:
--------------------------------------------------------------------------------
1 | export * from './handlers';
2 |
3 | export * from './db';
4 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/testing/mocks/initialize.ts:
--------------------------------------------------------------------------------
1 | export const initializeMocks = () => {};
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/testing/mocks/seed-db.ts:
--------------------------------------------------------------------------------
1 | export const seedDb = () => {};
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/testing/mocks/server.ts:
--------------------------------------------------------------------------------
1 | export const server = {};
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export type Entity = {
2 | id: string;
3 | createdAt: number;
4 | };
5 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/utils/format.ts:
--------------------------------------------------------------------------------
1 | export const formatDate = (date: number | string) => {
2 | return new Date(date).toLocaleDateString('en-US', {
3 | month: 'long',
4 | year: 'numeric',
5 | day: 'numeric',
6 | });
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-05-start/src/utils/uid.ts:
--------------------------------------------------------------------------------
1 | // https://gist.github.com/gordonbrander/2230317?permalink_comment_id=3443509#gistcomment-3443509
2 | export const uid = () => {
3 | return (
4 | performance.now().toString(36) +
5 | Math.random().toString(36)
6 | ).replace(/\./g, '');
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/components/button/index.ts:
--------------------------------------------------------------------------------
1 | export * from './button';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/components/content/content.tsx:
--------------------------------------------------------------------------------
1 | import { Box } from '@chakra-ui/react';
2 |
3 | export type ContentProps = {
4 | children: string;
5 | };
6 |
7 | export const Content = ({ children }: ContentProps) => {
8 | return (
9 |
10 | {children}
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/components/content/index.ts:
--------------------------------------------------------------------------------
1 | export * from './content';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/components/data-table/index.ts:
--------------------------------------------------------------------------------
1 | export * from './data-table';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/components/form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './input-field';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/components/info-card/index.ts:
--------------------------------------------------------------------------------
1 | export * from './info-card';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/components/link/index.ts:
--------------------------------------------------------------------------------
1 | export * from './link';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/components/link/link.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { Link, LinkProps } from './link';
4 |
5 | const meta: Meta = {
6 | title: 'Components/Link',
7 | component: Link,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => (
13 |
14 | );
15 |
16 | export const Default = Template.bind({});
17 |
18 | Default.args = {
19 | href: '/',
20 | children: 'Click Me',
21 | };
22 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/components/loading/index.ts:
--------------------------------------------------------------------------------
1 | export * from './loading';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/components/loading/loading.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { Loading } from './loading';
4 |
5 | const meta: Meta = {
6 | title: 'Components/Loading',
7 | component: Loading,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => ;
13 |
14 | export const Default = Template.bind({});
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/components/loading/loading.tsx:
--------------------------------------------------------------------------------
1 | import { Center, Spinner } from '@chakra-ui/react';
2 |
3 | export const Loading = () => {
4 | return (
5 |
6 |
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/components/not-found/index.ts:
--------------------------------------------------------------------------------
1 | export * from './not-found';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/components/not-found/not-found.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { NotFound } from './not-found';
4 |
5 | const meta: Meta = {
6 | title: 'Components/NotFound',
7 | component: NotFound,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => (
13 |
14 | );
15 |
16 | export const Default = Template.bind({});
17 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/components/not-found/not-found.tsx:
--------------------------------------------------------------------------------
1 | import { NotAllowedIcon } from '@chakra-ui/icons';
2 | import {
3 | Center,
4 | Heading,
5 | VStack,
6 | } from '@chakra-ui/react';
7 |
8 | export const NotFound = () => {
9 | return (
10 |
11 |
12 |
13 | Not Found
14 |
15 |
16 | );
17 | };
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/components/seo/index.ts:
--------------------------------------------------------------------------------
1 | export * from './seo';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/components/seo/seo.tsx:
--------------------------------------------------------------------------------
1 | import Head from 'next/head';
2 |
3 | export type SeoProps = {
4 | title: string;
5 | };
6 |
7 | export const Seo = ({ title }: SeoProps) => {
8 | return (
9 |
10 | {title}
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/config/theme.ts:
--------------------------------------------------------------------------------
1 | import { extendTheme } from '@chakra-ui/react';
2 |
3 | const colors = {
4 | primary: '#1a365d',
5 | primaryAccent: 'white',
6 | };
7 |
8 | const styles = {
9 | global: {
10 | 'html, body': {
11 | height: '100%',
12 | bg: 'gray.50',
13 | },
14 |
15 | '#__next': {
16 | height: '100%',
17 | bg: 'gray.50',
18 | },
19 | },
20 | };
21 |
22 | export const theme = extendTheme({ colors, styles });
23 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/features/auth/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-05/src/features/auth/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/features/auth/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-05/src/features/auth/components/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/features/auth/index.ts:
--------------------------------------------------------------------------------
1 | // types:
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/features/auth/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type AuthUser = Entity & {
4 | email: string;
5 | organizationId: string;
6 | };
7 |
8 | export type LoginData = {
9 | email: string;
10 | password: string;
11 | };
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/features/jobs/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-05/src/features/jobs/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/features/jobs/components/create-job-form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './create-job-form';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/features/jobs/components/dashboard-job-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dashboard-job-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/features/jobs/components/jobs-list/index.ts:
--------------------------------------------------------------------------------
1 | export * from './jobs-list';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/features/jobs/components/public-job-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './public-job-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/features/jobs/index.ts:
--------------------------------------------------------------------------------
1 | // components:
2 | export * from './components/create-job-form';
3 | export * from './components/dashboard-job-info';
4 | export * from './components/jobs-list';
5 | export * from './components/public-job-info';
6 |
7 | // types:
8 | export * from './types';
9 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/features/jobs/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Job = Entity & {
4 | organizationId: string;
5 | position: string;
6 | info: string;
7 | location: string;
8 | department: string;
9 | };
10 |
11 | export type CreateJobData = Pick<
12 | Job,
13 | 'position' | 'department' | 'location' | 'info'
14 | >;
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/features/organizations/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-05/src/features/organizations/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/features/organizations/components/organization-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './organization-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/features/organizations/index.ts:
--------------------------------------------------------------------------------
1 | // components:
2 | export * from './components/organization-info';
3 |
4 | // types:
5 | export * from './types';
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/features/organizations/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Organization = Entity & {
4 | adminId: string;
5 | name: string;
6 | email: string;
7 | phone: string;
8 | info: string;
9 | };
10 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/pages/404.tsx:
--------------------------------------------------------------------------------
1 | import { Center } from '@chakra-ui/react';
2 |
3 | import { Link } from '@/components/link';
4 | import { NotFound } from '@/components/not-found';
5 |
6 | const NotFoundPage = () => {
7 | return (
8 | <>
9 |
10 |
11 | Home
12 |
13 | >
14 | );
15 | };
16 |
17 | export default NotFoundPage;
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/stores/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-05/src/stores/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/testing/mocks/browser.ts:
--------------------------------------------------------------------------------
1 | import { setupWorker } from 'msw';
2 |
3 | import { handlers } from './handlers';
4 |
5 | export const worker = setupWorker(...handlers);
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/testing/mocks/index.ts:
--------------------------------------------------------------------------------
1 | export * from './handlers';
2 |
3 | export * from './db';
4 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/testing/mocks/initialize.ts:
--------------------------------------------------------------------------------
1 | import { IS_SERVER } from '@/config/constants';
2 |
3 | import { seedDb } from './seed-db';
4 |
5 | const initializeMocks = () => {
6 | if (IS_SERVER) {
7 | const { server } = require('./server');
8 | server.listen();
9 | } else {
10 | const { worker } = require('./browser');
11 | worker.start();
12 | }
13 | seedDb();
14 | };
15 |
16 | initializeMocks();
17 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/testing/mocks/seed-db.ts:
--------------------------------------------------------------------------------
1 | import { testData } from '../test-data';
2 |
3 | import { db } from './db';
4 |
5 | export const seedDb = () => {
6 | const userCount = db.user.count();
7 |
8 | if (userCount > 0) return;
9 |
10 | testData.users.forEach((user) => db.user.create(user));
11 |
12 | testData.organizations.forEach((organization) =>
13 | db.organization.create(organization)
14 | );
15 |
16 | testData.jobs.forEach((job) => db.job.create(job));
17 | };
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/testing/mocks/server.ts:
--------------------------------------------------------------------------------
1 | import { setupServer } from 'msw/node';
2 |
3 | import { handlers } from './handlers';
4 |
5 | export const server = setupServer(...handlers);
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export type Entity = {
2 | id: string;
3 | createdAt: number;
4 | };
5 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/utils/format.ts:
--------------------------------------------------------------------------------
1 | export const formatDate = (date: number | string) => {
2 | return new Date(date).toLocaleDateString('en-US', {
3 | month: 'long',
4 | year: 'numeric',
5 | day: 'numeric',
6 | });
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-05/src/utils/uid.ts:
--------------------------------------------------------------------------------
1 | // https://gist.github.com/gordonbrander/2230317?permalink_comment_id=3443509#gistcomment-3443509
2 | export const uid = () => {
3 | return (
4 | performance.now().toString(36) +
5 | Math.random().toString(36)
6 | ).replace(/\./g, '');
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/components/button/index.ts:
--------------------------------------------------------------------------------
1 | export * from './button';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/components/content/content.tsx:
--------------------------------------------------------------------------------
1 | import { Box } from '@chakra-ui/react';
2 |
3 | export type ContentProps = {
4 | children: string;
5 | };
6 |
7 | export const Content = ({ children }: ContentProps) => {
8 | return (
9 |
10 | {children}
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/components/content/index.ts:
--------------------------------------------------------------------------------
1 | export * from './content';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/components/data-table/index.ts:
--------------------------------------------------------------------------------
1 | export * from './data-table';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/components/form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './input-field';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/components/info-card/index.ts:
--------------------------------------------------------------------------------
1 | export * from './info-card';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/components/link/index.ts:
--------------------------------------------------------------------------------
1 | export * from './link';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/components/loading/index.ts:
--------------------------------------------------------------------------------
1 | export * from './loading';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/components/loading/loading.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { Loading } from './loading';
4 |
5 | const meta: Meta = {
6 | title: 'Components/Loading',
7 | component: Loading,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => ;
13 |
14 | export const Default = Template.bind({});
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/components/loading/loading.tsx:
--------------------------------------------------------------------------------
1 | import { Center, Spinner } from '@chakra-ui/react';
2 |
3 | export const Loading = () => {
4 | return (
5 |
6 |
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/components/not-found/index.ts:
--------------------------------------------------------------------------------
1 | export * from './not-found';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/components/not-found/not-found.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { NotFound } from './not-found';
4 |
5 | const meta: Meta = {
6 | title: 'Components/NotFound',
7 | component: NotFound,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => (
13 |
14 | );
15 |
16 | export const Default = Template.bind({});
17 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/components/not-found/not-found.tsx:
--------------------------------------------------------------------------------
1 | import { NotAllowedIcon } from '@chakra-ui/icons';
2 | import {
3 | Center,
4 | Heading,
5 | VStack,
6 | } from '@chakra-ui/react';
7 |
8 | export const NotFound = () => {
9 | return (
10 |
11 |
12 |
13 | Not Found
14 |
15 |
16 | );
17 | };
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/components/seo/index.ts:
--------------------------------------------------------------------------------
1 | export * from './seo';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/components/seo/seo.tsx:
--------------------------------------------------------------------------------
1 | import Head from 'next/head';
2 |
3 | export type SeoProps = {
4 | title: string;
5 | };
6 |
7 | export const Seo = ({ title }: SeoProps) => {
8 | return (
9 |
10 | {title}
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/config/theme.ts:
--------------------------------------------------------------------------------
1 | import { extendTheme } from '@chakra-ui/react';
2 |
3 | const colors = {
4 | primary: '#1a365d',
5 | primaryAccent: 'white',
6 | };
7 |
8 | const styles = {
9 | global: {
10 | 'html, body': {
11 | height: '100%',
12 | bg: 'gray.50',
13 | },
14 |
15 | '#__next': {
16 | height: '100%',
17 | bg: 'gray.50',
18 | },
19 | },
20 | };
21 |
22 | export const theme = extendTheme({ colors, styles });
23 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/features/auth/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-06-start/src/features/auth/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/features/auth/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-06-start/src/features/auth/components/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/features/auth/index.ts:
--------------------------------------------------------------------------------
1 | // types:
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/features/auth/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type AuthUser = Entity & {
4 | email: string;
5 | organizationId: string;
6 | };
7 |
8 | export type LoginData = {
9 | email: string;
10 | password: string;
11 | };
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/features/jobs/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-06-start/src/features/jobs/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/features/jobs/components/create-job-form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './create-job-form';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/features/jobs/components/dashboard-job-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dashboard-job-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/features/jobs/components/jobs-list/index.ts:
--------------------------------------------------------------------------------
1 | export * from './jobs-list';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/features/jobs/components/public-job-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './public-job-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/features/jobs/index.ts:
--------------------------------------------------------------------------------
1 | // components:
2 | export * from './components/create-job-form';
3 | export * from './components/dashboard-job-info';
4 | export * from './components/jobs-list';
5 | export * from './components/public-job-info';
6 |
7 | // types:
8 | export * from './types';
9 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/features/jobs/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Job = Entity & {
4 | organizationId: string;
5 | position: string;
6 | info: string;
7 | location: string;
8 | department: string;
9 | };
10 |
11 | export type CreateJobData = Pick<
12 | Job,
13 | 'position' | 'department' | 'location' | 'info'
14 | >;
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/features/organizations/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-06-start/src/features/organizations/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/features/organizations/components/organization-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './organization-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/features/organizations/index.ts:
--------------------------------------------------------------------------------
1 | // components:
2 | export * from './components/organization-info';
3 |
4 | // types:
5 | export * from './types';
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/features/organizations/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Organization = Entity & {
4 | adminId: string;
5 | name: string;
6 | email: string;
7 | phone: string;
8 | info: string;
9 | };
10 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/pages/404.tsx:
--------------------------------------------------------------------------------
1 | import { Center } from '@chakra-ui/react';
2 |
3 | import { Link } from '@/components/link';
4 | import { NotFound } from '@/components/not-found';
5 |
6 | const NotFoundPage = () => {
7 | return (
8 | <>
9 |
10 |
11 | Home
12 |
13 | >
14 | );
15 | };
16 |
17 | export default NotFoundPage;
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/stores/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-06-start/src/stores/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/testing/mocks/browser.ts:
--------------------------------------------------------------------------------
1 | import { setupWorker } from 'msw';
2 |
3 | import { handlers } from './handlers';
4 |
5 | export const worker = setupWorker(...handlers);
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/testing/mocks/index.ts:
--------------------------------------------------------------------------------
1 | export * from './handlers';
2 |
3 | export * from './db';
4 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/testing/mocks/initialize.ts:
--------------------------------------------------------------------------------
1 | import { IS_SERVER } from '@/config/constants';
2 |
3 | import { seedDb } from './seed-db';
4 |
5 | const initializeMocks = () => {
6 | if (IS_SERVER) {
7 | const { server } = require('./server');
8 | server.listen();
9 | } else {
10 | const { worker } = require('./browser');
11 | worker.start();
12 | }
13 | seedDb();
14 | };
15 |
16 | initializeMocks();
17 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/testing/mocks/seed-db.ts:
--------------------------------------------------------------------------------
1 | import { testData } from '../test-data';
2 |
3 | import { db } from './db';
4 |
5 | export const seedDb = () => {
6 | const userCount = db.user.count();
7 |
8 | if (userCount > 0) return;
9 |
10 | testData.users.forEach((user) => db.user.create(user));
11 |
12 | testData.organizations.forEach((organization) =>
13 | db.organization.create(organization)
14 | );
15 |
16 | testData.jobs.forEach((job) => db.job.create(job));
17 | };
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/testing/mocks/server.ts:
--------------------------------------------------------------------------------
1 | import { setupServer } from 'msw/node';
2 |
3 | import { handlers } from './handlers';
4 |
5 | export const server = setupServer(...handlers);
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export type Entity = {
2 | id: string;
3 | createdAt: number;
4 | };
5 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/utils/format.ts:
--------------------------------------------------------------------------------
1 | export const formatDate = (date: number | string) => {
2 | return new Date(date).toLocaleDateString('en-US', {
3 | month: 'long',
4 | year: 'numeric',
5 | day: 'numeric',
6 | });
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-06-start/src/utils/uid.ts:
--------------------------------------------------------------------------------
1 | // https://gist.github.com/gordonbrander/2230317?permalink_comment_id=3443509#gistcomment-3443509
2 | export const uid = () => {
3 | return (
4 | performance.now().toString(36) +
5 | Math.random().toString(36)
6 | ).replace(/\./g, '');
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/components/button/index.ts:
--------------------------------------------------------------------------------
1 | export * from './button';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/components/content/content.tsx:
--------------------------------------------------------------------------------
1 | import { Box } from '@chakra-ui/react';
2 |
3 | export type ContentProps = {
4 | children: string;
5 | };
6 |
7 | export const Content = ({ children }: ContentProps) => {
8 | return (
9 |
10 | {children}
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/components/content/index.ts:
--------------------------------------------------------------------------------
1 | export * from './content';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/components/data-table/index.ts:
--------------------------------------------------------------------------------
1 | export * from './data-table';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/components/form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './input-field';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/components/info-card/index.ts:
--------------------------------------------------------------------------------
1 | export * from './info-card';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/components/link/index.ts:
--------------------------------------------------------------------------------
1 | export * from './link';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/components/link/link.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { Link, LinkProps } from './link';
4 |
5 | const meta: Meta = {
6 | title: 'Components/Link',
7 | component: Link,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => (
13 |
14 | );
15 |
16 | export const Default = Template.bind({});
17 |
18 | Default.args = {
19 | href: '/',
20 | children: 'Click Me',
21 | };
22 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/components/loading/index.ts:
--------------------------------------------------------------------------------
1 | export * from './loading';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/components/loading/loading.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { Loading } from './loading';
4 |
5 | const meta: Meta = {
6 | title: 'Components/Loading',
7 | component: Loading,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => ;
13 |
14 | export const Default = Template.bind({});
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/components/loading/loading.tsx:
--------------------------------------------------------------------------------
1 | import { Center, Spinner } from '@chakra-ui/react';
2 |
3 | export const Loading = () => {
4 | return (
5 |
6 |
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/components/not-found/index.ts:
--------------------------------------------------------------------------------
1 | export * from './not-found';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/components/not-found/not-found.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { NotFound } from './not-found';
4 |
5 | const meta: Meta = {
6 | title: 'Components/NotFound',
7 | component: NotFound,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => (
13 |
14 | );
15 |
16 | export const Default = Template.bind({});
17 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/components/not-found/not-found.tsx:
--------------------------------------------------------------------------------
1 | import { NotAllowedIcon } from '@chakra-ui/icons';
2 | import {
3 | Center,
4 | Heading,
5 | VStack,
6 | } from '@chakra-ui/react';
7 |
8 | export const NotFound = () => {
9 | return (
10 |
11 |
12 |
13 | Not Found
14 |
15 |
16 | );
17 | };
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/components/seo/index.ts:
--------------------------------------------------------------------------------
1 | export * from './seo';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/components/seo/seo.tsx:
--------------------------------------------------------------------------------
1 | import Head from 'next/head';
2 |
3 | export type SeoProps = {
4 | title: string;
5 | };
6 |
7 | export const Seo = ({ title }: SeoProps) => {
8 | return (
9 |
10 | {title}
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/config/theme.ts:
--------------------------------------------------------------------------------
1 | import { extendTheme } from '@chakra-ui/react';
2 |
3 | const colors = {
4 | primary: '#1a365d',
5 | primaryAccent: 'white',
6 | };
7 |
8 | const styles = {
9 | global: {
10 | 'html, body': {
11 | height: '100%',
12 | bg: 'gray.50',
13 | },
14 |
15 | '#__next': {
16 | height: '100%',
17 | bg: 'gray.50',
18 | },
19 | },
20 | };
21 |
22 | export const theme = extendTheme({ colors, styles });
23 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/features/auth/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-06/src/features/auth/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/features/auth/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-06/src/features/auth/components/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/features/auth/index.ts:
--------------------------------------------------------------------------------
1 | // types:
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/features/auth/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type AuthUser = Entity & {
4 | email: string;
5 | organizationId: string;
6 | };
7 |
8 | export type LoginData = {
9 | email: string;
10 | password: string;
11 | };
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/features/jobs/components/create-job-form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './create-job-form';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/features/jobs/components/dashboard-job-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dashboard-job-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/features/jobs/components/jobs-list/index.ts:
--------------------------------------------------------------------------------
1 | export * from './jobs-list';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/features/jobs/components/public-job-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './public-job-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/features/jobs/index.ts:
--------------------------------------------------------------------------------
1 | // api:
2 | export * from './api/get-job';
3 | export * from './api/get-jobs';
4 |
5 | // components:
6 | export * from './components/create-job-form';
7 | export * from './components/dashboard-job-info';
8 | export * from './components/jobs-list';
9 | export * from './components/public-job-info';
10 |
11 | // types:
12 | export * from './types';
13 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/features/jobs/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Job = Entity & {
4 | organizationId: string;
5 | position: string;
6 | info: string;
7 | location: string;
8 | department: string;
9 | };
10 |
11 | export type CreateJobData = Pick<
12 | Job,
13 | 'position' | 'department' | 'location' | 'info'
14 | >;
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/features/organizations/components/organization-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './organization-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/features/organizations/index.ts:
--------------------------------------------------------------------------------
1 | // api:
2 | export * from './api/get-organization';
3 |
4 | // components:
5 | export * from './components/organization-info';
6 |
7 | // types:
8 | export * from './types';
9 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/features/organizations/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Organization = Entity & {
4 | adminId: string;
5 | name: string;
6 | email: string;
7 | phone: string;
8 | info: string;
9 | };
10 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/lib/react-query.ts:
--------------------------------------------------------------------------------
1 | import { QueryClient } from '@tanstack/react-query';
2 |
3 | export const queryClient = new QueryClient({
4 | defaultOptions: {
5 | queries: {
6 | retry: false,
7 | refetchOnWindowFocus: false,
8 | useErrorBoundary: true,
9 | },
10 | },
11 | });
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/pages/404.tsx:
--------------------------------------------------------------------------------
1 | import { Center } from '@chakra-ui/react';
2 |
3 | import { Link } from '@/components/link';
4 | import { NotFound } from '@/components/not-found';
5 |
6 | const NotFoundPage = () => {
7 | return (
8 | <>
9 |
10 |
11 | Home
12 |
13 | >
14 | );
15 | };
16 |
17 | export default NotFoundPage;
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/stores/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-06/src/stores/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/testing/mocks/browser.ts:
--------------------------------------------------------------------------------
1 | import { setupWorker } from 'msw';
2 |
3 | import { handlers } from './handlers';
4 |
5 | export const worker = setupWorker(...handlers);
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/testing/mocks/index.ts:
--------------------------------------------------------------------------------
1 | export * from './handlers';
2 |
3 | export * from './db';
4 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/testing/mocks/initialize.ts:
--------------------------------------------------------------------------------
1 | import { IS_SERVER } from '@/config/constants';
2 |
3 | import { seedDb } from './seed-db';
4 |
5 | const initializeMocks = () => {
6 | if (IS_SERVER) {
7 | const { server } = require('./server');
8 | server.listen();
9 | } else {
10 | const { worker } = require('./browser');
11 | worker.start();
12 | }
13 | seedDb();
14 | };
15 |
16 | initializeMocks();
17 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/testing/mocks/seed-db.ts:
--------------------------------------------------------------------------------
1 | import { testData } from '../test-data';
2 |
3 | import { db } from './db';
4 |
5 | export const seedDb = () => {
6 | const userCount = db.user.count();
7 |
8 | if (userCount > 0) return;
9 |
10 | testData.users.forEach((user) => db.user.create(user));
11 |
12 | testData.organizations.forEach((organization) =>
13 | db.organization.create(organization)
14 | );
15 |
16 | testData.jobs.forEach((job) => db.job.create(job));
17 | };
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/testing/mocks/server.ts:
--------------------------------------------------------------------------------
1 | import { setupServer } from 'msw/node';
2 |
3 | import { handlers } from './handlers';
4 |
5 | export const server = setupServer(...handlers);
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export type Entity = {
2 | id: string;
3 | createdAt: number;
4 | };
5 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/utils/format.ts:
--------------------------------------------------------------------------------
1 | export const formatDate = (date: number | string) => {
2 | return new Date(date).toLocaleDateString('en-US', {
3 | month: 'long',
4 | year: 'numeric',
5 | day: 'numeric',
6 | });
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-06/src/utils/uid.ts:
--------------------------------------------------------------------------------
1 | // https://gist.github.com/gordonbrander/2230317?permalink_comment_id=3443509#gistcomment-3443509
2 | export const uid = () => {
3 | return (
4 | performance.now().toString(36) +
5 | Math.random().toString(36)
6 | ).replace(/\./g, '');
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/components/button/index.ts:
--------------------------------------------------------------------------------
1 | export * from './button';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/components/content/content.tsx:
--------------------------------------------------------------------------------
1 | import { Box } from '@chakra-ui/react';
2 |
3 | export type ContentProps = {
4 | children: string;
5 | };
6 |
7 | export const Content = ({ children }: ContentProps) => {
8 | return (
9 |
10 | {children}
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/components/content/index.ts:
--------------------------------------------------------------------------------
1 | export * from './content';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/components/data-table/index.ts:
--------------------------------------------------------------------------------
1 | export * from './data-table';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/components/form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './input-field';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/components/info-card/index.ts:
--------------------------------------------------------------------------------
1 | export * from './info-card';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/components/link/index.ts:
--------------------------------------------------------------------------------
1 | export * from './link';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/components/loading/index.ts:
--------------------------------------------------------------------------------
1 | export * from './loading';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/components/loading/loading.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { Loading } from './loading';
4 |
5 | const meta: Meta = {
6 | title: 'Components/Loading',
7 | component: Loading,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => ;
13 |
14 | export const Default = Template.bind({});
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/components/loading/loading.tsx:
--------------------------------------------------------------------------------
1 | import { Center, Spinner } from '@chakra-ui/react';
2 |
3 | export const Loading = () => {
4 | return (
5 |
6 |
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/components/not-found/index.ts:
--------------------------------------------------------------------------------
1 | export * from './not-found';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/components/not-found/not-found.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { NotFound } from './not-found';
4 |
5 | const meta: Meta = {
6 | title: 'Components/NotFound',
7 | component: NotFound,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => (
13 |
14 | );
15 |
16 | export const Default = Template.bind({});
17 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/components/not-found/not-found.tsx:
--------------------------------------------------------------------------------
1 | import { NotAllowedIcon } from '@chakra-ui/icons';
2 | import {
3 | Center,
4 | Heading,
5 | VStack,
6 | } from '@chakra-ui/react';
7 |
8 | export const NotFound = () => {
9 | return (
10 |
11 |
12 |
13 | Not Found
14 |
15 |
16 | );
17 | };
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/components/notifications/index.ts:
--------------------------------------------------------------------------------
1 | export * from './notifications';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/components/notifications/notifications.tsx:
--------------------------------------------------------------------------------
1 | export const Notifications = () => {
2 | return <>Notifications>;
3 | };
4 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/components/seo/index.ts:
--------------------------------------------------------------------------------
1 | export * from './seo';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/components/seo/seo.tsx:
--------------------------------------------------------------------------------
1 | import Head from 'next/head';
2 |
3 | export type SeoProps = {
4 | title: string;
5 | };
6 |
7 | export const Seo = ({ title }: SeoProps) => {
8 | return (
9 |
10 | {title}
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/config/theme.ts:
--------------------------------------------------------------------------------
1 | import { extendTheme } from '@chakra-ui/react';
2 |
3 | const colors = {
4 | primary: '#1a365d',
5 | primaryAccent: 'white',
6 | };
7 |
8 | const styles = {
9 | global: {
10 | 'html, body': {
11 | height: '100%',
12 | bg: 'gray.50',
13 | },
14 |
15 | '#__next': {
16 | height: '100%',
17 | bg: 'gray.50',
18 | },
19 | },
20 | };
21 |
22 | export const theme = extendTheme({ colors, styles });
23 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/features/auth/api/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/code-stages/chapter-07-start/src/features/auth/api/.gitkeep
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/features/auth/components/login-form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './login-form';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/features/auth/components/protected/index.ts:
--------------------------------------------------------------------------------
1 | export * from './protected';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/features/auth/components/protected/protected.tsx:
--------------------------------------------------------------------------------
1 | import { ReactNode } from 'react';
2 |
3 | export type ProtectedProps = {
4 | children: ReactNode;
5 | };
6 |
7 | export const Protected = ({
8 | children,
9 | }: ProtectedProps) => {
10 | return <>{children}>;
11 | };
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/features/auth/index.ts:
--------------------------------------------------------------------------------
1 | // components:
2 | export * from './components/login-form';
3 | export * from './components/protected';
4 |
5 | // types:
6 | export * from './types';
7 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/features/auth/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type AuthUser = Entity & {
4 | email: string;
5 | organizationId: string;
6 | };
7 |
8 | export type LoginData = {
9 | email: string;
10 | password: string;
11 | };
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/features/jobs/components/create-job-form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './create-job-form';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/features/jobs/components/dashboard-job-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dashboard-job-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/features/jobs/components/jobs-list/index.ts:
--------------------------------------------------------------------------------
1 | export * from './jobs-list';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/features/jobs/components/public-job-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './public-job-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/features/jobs/index.ts:
--------------------------------------------------------------------------------
1 | // api:
2 | export * from './api/get-job';
3 | export * from './api/get-jobs';
4 |
5 | // components:
6 | export * from './components/create-job-form';
7 | export * from './components/dashboard-job-info';
8 | export * from './components/jobs-list';
9 | export * from './components/public-job-info';
10 |
11 | // types:
12 | export * from './types';
13 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/features/jobs/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Job = Entity & {
4 | organizationId: string;
5 | position: string;
6 | info: string;
7 | location: string;
8 | department: string;
9 | };
10 |
11 | export type CreateJobData = Pick<
12 | Job,
13 | 'position' | 'department' | 'location' | 'info'
14 | >;
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/features/organizations/components/organization-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './organization-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/features/organizations/index.ts:
--------------------------------------------------------------------------------
1 | // api:
2 | export * from './api/get-organization';
3 |
4 | // components:
5 | export * from './components/organization-info';
6 |
7 | // types:
8 | export * from './types';
9 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/features/organizations/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Organization = Entity & {
4 | adminId: string;
5 | name: string;
6 | email: string;
7 | phone: string;
8 | info: string;
9 | };
10 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/lib/react-query.ts:
--------------------------------------------------------------------------------
1 | import { QueryClient } from '@tanstack/react-query';
2 |
3 | export const queryClient = new QueryClient({
4 | defaultOptions: {
5 | queries: {
6 | retry: false,
7 | refetchOnWindowFocus: false,
8 | useErrorBoundary: true,
9 | },
10 | },
11 | });
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/pages/404.tsx:
--------------------------------------------------------------------------------
1 | import { Center } from '@chakra-ui/react';
2 |
3 | import { Link } from '@/components/link';
4 | import { NotFound } from '@/components/not-found';
5 |
6 | const NotFoundPage = () => {
7 | return (
8 | <>
9 |
10 |
11 | Home
12 |
13 | >
14 | );
15 | };
16 |
17 | export default NotFoundPage;
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/stores/notifications/index.ts:
--------------------------------------------------------------------------------
1 | export * from './notifications';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/stores/notifications/notifications.ts:
--------------------------------------------------------------------------------
1 | export {};
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/testing/mocks/browser.ts:
--------------------------------------------------------------------------------
1 | import { setupWorker } from 'msw';
2 |
3 | import { handlers } from './handlers';
4 |
5 | export const worker = setupWorker(...handlers);
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/testing/mocks/index.ts:
--------------------------------------------------------------------------------
1 | export * from './handlers';
2 |
3 | export * from './db';
4 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/testing/mocks/initialize.ts:
--------------------------------------------------------------------------------
1 | import { IS_SERVER } from '@/config/constants';
2 |
3 | import { seedDb } from './seed-db';
4 |
5 | const initializeMocks = () => {
6 | if (IS_SERVER) {
7 | const { server } = require('./server');
8 | server.listen();
9 | } else {
10 | const { worker } = require('./browser');
11 | worker.start();
12 | }
13 | seedDb();
14 | };
15 |
16 | initializeMocks();
17 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/testing/mocks/seed-db.ts:
--------------------------------------------------------------------------------
1 | import { testData } from '../test-data';
2 |
3 | import { db } from './db';
4 |
5 | export const seedDb = () => {
6 | const userCount = db.user.count();
7 |
8 | if (userCount > 0) return;
9 |
10 | testData.users.forEach((user) => db.user.create(user));
11 |
12 | testData.organizations.forEach((organization) =>
13 | db.organization.create(organization)
14 | );
15 |
16 | testData.jobs.forEach((job) => db.job.create(job));
17 | };
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/testing/mocks/server.ts:
--------------------------------------------------------------------------------
1 | import { setupServer } from 'msw/node';
2 |
3 | import { handlers } from './handlers';
4 |
5 | export const server = setupServer(...handlers);
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export type Entity = {
2 | id: string;
3 | createdAt: number;
4 | };
5 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/utils/format.ts:
--------------------------------------------------------------------------------
1 | export const formatDate = (date: number | string) => {
2 | return new Date(date).toLocaleDateString('en-US', {
3 | month: 'long',
4 | year: 'numeric',
5 | day: 'numeric',
6 | });
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-07-start/src/utils/uid.ts:
--------------------------------------------------------------------------------
1 | // https://gist.github.com/gordonbrander/2230317?permalink_comment_id=3443509#gistcomment-3443509
2 | export const uid = () => {
3 | return (
4 | performance.now().toString(36) +
5 | Math.random().toString(36)
6 | ).replace(/\./g, '');
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/components/button/index.ts:
--------------------------------------------------------------------------------
1 | export * from './button';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/components/content/content.tsx:
--------------------------------------------------------------------------------
1 | import { Box } from '@chakra-ui/react';
2 |
3 | export type ContentProps = {
4 | children: string;
5 | };
6 |
7 | export const Content = ({ children }: ContentProps) => {
8 | return (
9 |
10 | {children}
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/components/content/index.ts:
--------------------------------------------------------------------------------
1 | export * from './content';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/components/data-table/index.ts:
--------------------------------------------------------------------------------
1 | export * from './data-table';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/components/form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './input-field';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/components/info-card/index.ts:
--------------------------------------------------------------------------------
1 | export * from './info-card';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/components/link/index.ts:
--------------------------------------------------------------------------------
1 | export * from './link';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/components/link/link.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { Link, LinkProps } from './link';
4 |
5 | const meta: Meta = {
6 | title: 'Components/Link',
7 | component: Link,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => (
13 |
14 | );
15 |
16 | export const Default = Template.bind({});
17 |
18 | Default.args = {
19 | href: '/',
20 | children: 'Click Me',
21 | };
22 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/components/loading/index.ts:
--------------------------------------------------------------------------------
1 | export * from './loading';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/components/loading/loading.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { Loading } from './loading';
4 |
5 | const meta: Meta = {
6 | title: 'Components/Loading',
7 | component: Loading,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => ;
13 |
14 | export const Default = Template.bind({});
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/components/loading/loading.tsx:
--------------------------------------------------------------------------------
1 | import { Center, Spinner } from '@chakra-ui/react';
2 |
3 | export const Loading = () => {
4 | return (
5 |
6 |
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/components/not-found/index.ts:
--------------------------------------------------------------------------------
1 | export * from './not-found';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/components/not-found/not-found.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { NotFound } from './not-found';
4 |
5 | const meta: Meta = {
6 | title: 'Components/NotFound',
7 | component: NotFound,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => (
13 |
14 | );
15 |
16 | export const Default = Template.bind({});
17 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/components/not-found/not-found.tsx:
--------------------------------------------------------------------------------
1 | import { NotAllowedIcon } from '@chakra-ui/icons';
2 | import {
3 | Center,
4 | Heading,
5 | VStack,
6 | } from '@chakra-ui/react';
7 |
8 | export const NotFound = () => {
9 | return (
10 |
11 |
12 |
13 | Not Found
14 |
15 |
16 | );
17 | };
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/components/notifications/index.ts:
--------------------------------------------------------------------------------
1 | export * from './notifications';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/components/seo/index.ts:
--------------------------------------------------------------------------------
1 | export * from './seo';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/components/seo/seo.tsx:
--------------------------------------------------------------------------------
1 | import Head from 'next/head';
2 |
3 | export type SeoProps = {
4 | title: string;
5 | };
6 |
7 | export const Seo = ({ title }: SeoProps) => {
8 | return (
9 |
10 | {title}
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/config/theme.ts:
--------------------------------------------------------------------------------
1 | import { extendTheme } from '@chakra-ui/react';
2 |
3 | const colors = {
4 | primary: '#1a365d',
5 | primaryAccent: 'white',
6 | };
7 |
8 | const styles = {
9 | global: {
10 | 'html, body': {
11 | height: '100%',
12 | bg: 'gray.50',
13 | },
14 |
15 | '#__next': {
16 | height: '100%',
17 | bg: 'gray.50',
18 | },
19 | },
20 | };
21 |
22 | export const theme = extendTheme({ colors, styles });
23 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/features/auth/components/login-form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './login-form';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/features/auth/components/protected/index.ts:
--------------------------------------------------------------------------------
1 | export * from './protected';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/features/auth/index.ts:
--------------------------------------------------------------------------------
1 | // api:
2 | export * from './api/get-auth-user';
3 | export * from './api/logout';
4 |
5 | // components:
6 | export * from './components/login-form';
7 | export * from './components/protected';
8 |
9 | // types:
10 | export * from './types';
11 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/features/auth/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type AuthUser = Entity & {
4 | email: string;
5 | organizationId: string;
6 | };
7 |
8 | export type LoginData = {
9 | email: string;
10 | password: string;
11 | };
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/features/jobs/components/create-job-form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './create-job-form';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/features/jobs/components/dashboard-job-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dashboard-job-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/features/jobs/components/jobs-list/index.ts:
--------------------------------------------------------------------------------
1 | export * from './jobs-list';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/features/jobs/components/public-job-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './public-job-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/features/jobs/index.ts:
--------------------------------------------------------------------------------
1 | // api:
2 | export * from './api/get-job';
3 | export * from './api/get-jobs';
4 |
5 | // components:
6 | export * from './components/create-job-form';
7 | export * from './components/dashboard-job-info';
8 | export * from './components/jobs-list';
9 | export * from './components/public-job-info';
10 |
11 | // types:
12 | export * from './types';
13 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/features/jobs/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Job = Entity & {
4 | organizationId: string;
5 | position: string;
6 | info: string;
7 | location: string;
8 | department: string;
9 | };
10 |
11 | export type CreateJobData = Pick<
12 | Job,
13 | 'position' | 'department' | 'location' | 'info'
14 | >;
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/features/organizations/components/organization-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './organization-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/features/organizations/index.ts:
--------------------------------------------------------------------------------
1 | // api:
2 | export * from './api/get-organization';
3 |
4 | // components:
5 | export * from './components/organization-info';
6 |
7 | // types:
8 | export * from './types';
9 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/features/organizations/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Organization = Entity & {
4 | adminId: string;
5 | name: string;
6 | email: string;
7 | phone: string;
8 | info: string;
9 | };
10 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/lib/react-query.ts:
--------------------------------------------------------------------------------
1 | import { QueryClient } from '@tanstack/react-query';
2 |
3 | export const queryClient = new QueryClient({
4 | defaultOptions: {
5 | queries: {
6 | retry: false,
7 | refetchOnWindowFocus: false,
8 | useErrorBoundary: true,
9 | },
10 | },
11 | });
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/pages/404.tsx:
--------------------------------------------------------------------------------
1 | import { Center } from '@chakra-ui/react';
2 |
3 | import { Link } from '@/components/link';
4 | import { NotFound } from '@/components/not-found';
5 |
6 | const NotFoundPage = () => {
7 | return (
8 | <>
9 |
10 |
11 | Home
12 |
13 | >
14 | );
15 | };
16 |
17 | export default NotFoundPage;
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/stores/notifications/index.ts:
--------------------------------------------------------------------------------
1 | export * from './notifications';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/testing/mocks/browser.ts:
--------------------------------------------------------------------------------
1 | import { setupWorker } from 'msw';
2 |
3 | import { handlers } from './handlers';
4 |
5 | export const worker = setupWorker(...handlers);
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/testing/mocks/index.ts:
--------------------------------------------------------------------------------
1 | export * from './handlers';
2 |
3 | export * from './db';
4 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/testing/mocks/initialize.ts:
--------------------------------------------------------------------------------
1 | import { IS_SERVER } from '@/config/constants';
2 |
3 | import { seedDb } from './seed-db';
4 |
5 | const initializeMocks = () => {
6 | if (IS_SERVER) {
7 | const { server } = require('./server');
8 | server.listen();
9 | } else {
10 | const { worker } = require('./browser');
11 | worker.start();
12 | }
13 | seedDb();
14 | };
15 |
16 | initializeMocks();
17 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/testing/mocks/seed-db.ts:
--------------------------------------------------------------------------------
1 | import { testData } from '../test-data';
2 |
3 | import { db } from './db';
4 |
5 | export const seedDb = () => {
6 | const userCount = db.user.count();
7 |
8 | if (userCount > 0) return;
9 |
10 | testData.users.forEach((user) => db.user.create(user));
11 |
12 | testData.organizations.forEach((organization) =>
13 | db.organization.create(organization)
14 | );
15 |
16 | testData.jobs.forEach((job) => db.job.create(job));
17 | };
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/testing/mocks/server.ts:
--------------------------------------------------------------------------------
1 | import { setupServer } from 'msw/node';
2 |
3 | import { handlers } from './handlers';
4 |
5 | export const server = setupServer(...handlers);
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export type Entity = {
2 | id: string;
3 | createdAt: number;
4 | };
5 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/utils/format.ts:
--------------------------------------------------------------------------------
1 | export const formatDate = (date: number | string) => {
2 | return new Date(date).toLocaleDateString('en-US', {
3 | month: 'long',
4 | year: 'numeric',
5 | day: 'numeric',
6 | });
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-07/src/utils/uid.ts:
--------------------------------------------------------------------------------
1 | // https://gist.github.com/gordonbrander/2230317?permalink_comment_id=3443509#gistcomment-3443509
2 | export const uid = () => {
3 | return (
4 | performance.now().toString(36) +
5 | Math.random().toString(36)
6 | ).replace(/\./g, '');
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/cypress.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'cypress';
2 |
3 | export default defineConfig({
4 | video: false,
5 | videoUploadOnPasses: false,
6 | e2e: {
7 | // We've imported your old cypress plugins here.
8 | // You may want to clean this up later by importing these.
9 | setupNodeEvents(on, config) {
10 | return require('./cypress/plugins/index.ts')(
11 | on,
12 | config
13 | );
14 | },
15 | },
16 | });
17 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/cypress/e2e/dashboard.cy.ts:
--------------------------------------------------------------------------------
1 | describe('dashboard', () => {
2 | it('should authenticate into the dashboard', () => {});
3 |
4 | it('should navigate to and visit the job details page', () => {});
5 |
6 | it('should create a new job', () => {});
7 |
8 | it('should log out from the dashboard', () => {});
9 | });
10 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/cypress/e2e/public.cy.ts:
--------------------------------------------------------------------------------
1 | describe('public application flow', () => {
2 | it('should display the organization public page', () => {});
3 |
4 | it('should navigate to and display the public job details page', () => {});
5 | });
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/cypress/fixtures/example.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Using fixtures to represent data",
3 | "email": "hello@cypress.io",
4 | "body": "Fixtures are a great way to mock data for responses to routes"
5 | }
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/cypress/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "esModuleInterop": true,
4 | "target": "es5",
5 | "lib": ["es5", "dom"],
6 | "types": [
7 | "node",
8 | "cypress",
9 | "@testing-library/cypress"
10 | ]
11 | },
12 | "include": ["**/*.ts"]
13 | }
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/__tests__/dashboard-create-job-page.test.tsx:
--------------------------------------------------------------------------------
1 | describe('Dashboard Create Job Page', () => {
2 | it.todo('should create a new job');
3 | });
4 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/__tests__/dashboard-job-page.test.tsx:
--------------------------------------------------------------------------------
1 | describe('Dashboard Job Page', () => {
2 | it.todo('should render all the job details');
3 | });
4 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/__tests__/dashboard-jobs-page.test.tsx:
--------------------------------------------------------------------------------
1 | describe('Dashboard Jobs Page', () => {
2 | it.todo('should render the jobs list');
3 | });
4 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/__tests__/login-page.test.tsx:
--------------------------------------------------------------------------------
1 | describe('Login Page', () => {
2 | it.todo('should login the user into the dashboard');
3 | });
4 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/__tests__/public-job-page.test.tsx:
--------------------------------------------------------------------------------
1 | describe('Public Job Page', () => {
2 | it.todo(
3 | 'should use getServerSideProps that fetches and returns the proper data'
4 | );
5 |
6 | it.todo('should render the job details');
7 |
8 | it.todo(
9 | 'should render the not found message if the data does not exist'
10 | );
11 | });
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/__tests__/public-organization-page.test.tsx:
--------------------------------------------------------------------------------
1 | describe('Public Organization Page', () => {
2 | it.todo(
3 | 'should use getServerSideProps that fetches and returns the proper data'
4 | );
5 |
6 | it.todo('should render the organization details');
7 |
8 | it.todo(
9 | 'should render the not found message if the organization is not found'
10 | );
11 | });
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/components/button/index.ts:
--------------------------------------------------------------------------------
1 | export * from './button';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/components/content/content.tsx:
--------------------------------------------------------------------------------
1 | import { Box } from '@chakra-ui/react';
2 |
3 | export type ContentProps = {
4 | children: string;
5 | };
6 |
7 | export const Content = ({ children }: ContentProps) => {
8 | return (
9 |
10 | {children}
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/components/content/index.ts:
--------------------------------------------------------------------------------
1 | export * from './content';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/components/data-table/index.ts:
--------------------------------------------------------------------------------
1 | export * from './data-table';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/components/form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './input-field';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/components/info-card/index.ts:
--------------------------------------------------------------------------------
1 | export * from './info-card';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/components/link/index.ts:
--------------------------------------------------------------------------------
1 | export * from './link';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/components/loading/index.ts:
--------------------------------------------------------------------------------
1 | export * from './loading';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/components/loading/loading.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { Loading } from './loading';
4 |
5 | const meta: Meta = {
6 | title: 'Components/Loading',
7 | component: Loading,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => ;
13 |
14 | export const Default = Template.bind({});
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/components/loading/loading.tsx:
--------------------------------------------------------------------------------
1 | import { Center, Spinner } from '@chakra-ui/react';
2 |
3 | export const Loading = () => {
4 | return (
5 |
6 |
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/components/not-found/index.ts:
--------------------------------------------------------------------------------
1 | export * from './not-found';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/components/not-found/not-found.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { NotFound } from './not-found';
4 |
5 | const meta: Meta = {
6 | title: 'Components/NotFound',
7 | component: NotFound,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => (
13 |
14 | );
15 |
16 | export const Default = Template.bind({});
17 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/components/not-found/not-found.tsx:
--------------------------------------------------------------------------------
1 | import { NotAllowedIcon } from '@chakra-ui/icons';
2 | import {
3 | Center,
4 | Heading,
5 | VStack,
6 | } from '@chakra-ui/react';
7 |
8 | export const NotFound = () => {
9 | return (
10 |
11 |
12 |
13 | Not Found
14 |
15 |
16 | );
17 | };
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/components/notifications/index.ts:
--------------------------------------------------------------------------------
1 | export * from './notifications';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/components/seo/index.ts:
--------------------------------------------------------------------------------
1 | export * from './seo';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/components/seo/seo.tsx:
--------------------------------------------------------------------------------
1 | import Head from 'next/head';
2 |
3 | export type SeoProps = {
4 | title: string;
5 | };
6 |
7 | export const Seo = ({ title }: SeoProps) => {
8 | return (
9 |
10 | {title}
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/config/theme.ts:
--------------------------------------------------------------------------------
1 | import { extendTheme } from '@chakra-ui/react';
2 |
3 | const colors = {
4 | primary: '#1a365d',
5 | primaryAccent: 'white',
6 | };
7 |
8 | const styles = {
9 | global: {
10 | 'html, body': {
11 | height: '100%',
12 | bg: 'gray.50',
13 | },
14 |
15 | '#__next': {
16 | height: '100%',
17 | bg: 'gray.50',
18 | },
19 | },
20 | };
21 |
22 | export const theme = extendTheme({ colors, styles });
23 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/features/auth/components/login-form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './login-form';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/features/auth/components/protected/index.ts:
--------------------------------------------------------------------------------
1 | export * from './protected';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/features/auth/index.ts:
--------------------------------------------------------------------------------
1 | // api:
2 | export * from './api/get-auth-user';
3 | export * from './api/logout';
4 |
5 | // components:
6 | export * from './components/login-form';
7 | export * from './components/protected';
8 |
9 | // types:
10 | export * from './types';
11 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/features/auth/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type AuthUser = Entity & {
4 | email: string;
5 | organizationId: string;
6 | };
7 |
8 | export type LoginData = {
9 | email: string;
10 | password: string;
11 | };
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/features/jobs/components/create-job-form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './create-job-form';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/features/jobs/components/dashboard-job-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dashboard-job-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/features/jobs/components/jobs-list/index.ts:
--------------------------------------------------------------------------------
1 | export * from './jobs-list';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/features/jobs/components/public-job-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './public-job-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/features/jobs/index.ts:
--------------------------------------------------------------------------------
1 | // api:
2 | export * from './api/get-job';
3 | export * from './api/get-jobs';
4 |
5 | // components:
6 | export * from './components/create-job-form';
7 | export * from './components/dashboard-job-info';
8 | export * from './components/jobs-list';
9 | export * from './components/public-job-info';
10 |
11 | // types:
12 | export * from './types';
13 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/features/jobs/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Job = Entity & {
4 | organizationId: string;
5 | position: string;
6 | info: string;
7 | location: string;
8 | department: string;
9 | };
10 |
11 | export type CreateJobData = Pick<
12 | Job,
13 | 'position' | 'department' | 'location' | 'info'
14 | >;
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/features/organizations/components/organization-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './organization-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/features/organizations/index.ts:
--------------------------------------------------------------------------------
1 | // api:
2 | export * from './api/get-organization';
3 |
4 | // components:
5 | export * from './components/organization-info';
6 |
7 | // types:
8 | export * from './types';
9 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/features/organizations/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Organization = Entity & {
4 | adminId: string;
5 | name: string;
6 | email: string;
7 | phone: string;
8 | info: string;
9 | };
10 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/lib/react-query.ts:
--------------------------------------------------------------------------------
1 | import { QueryClient } from '@tanstack/react-query';
2 |
3 | export const queryClient = new QueryClient({
4 | defaultOptions: {
5 | queries: {
6 | retry: false,
7 | refetchOnWindowFocus: false,
8 | useErrorBoundary: true,
9 | },
10 | },
11 | });
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/pages/404.tsx:
--------------------------------------------------------------------------------
1 | import { Center } from '@chakra-ui/react';
2 |
3 | import { Link } from '@/components/link';
4 | import { NotFound } from '@/components/not-found';
5 |
6 | const NotFoundPage = () => {
7 | return (
8 | <>
9 |
10 |
11 | Home
12 |
13 | >
14 | );
15 | };
16 |
17 | export default NotFoundPage;
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/stores/notifications/__tests__/notifications.test.ts:
--------------------------------------------------------------------------------
1 | describe('notifications store', () => {
2 | it.todo('should add and remove notifications');
3 | });
4 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/stores/notifications/index.ts:
--------------------------------------------------------------------------------
1 | export * from './notifications';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/testing/mocks/browser.ts:
--------------------------------------------------------------------------------
1 | import { setupWorker } from 'msw';
2 |
3 | import { handlers } from './handlers';
4 |
5 | export const worker = setupWorker(...handlers);
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/testing/mocks/index.ts:
--------------------------------------------------------------------------------
1 | export * from './handlers';
2 |
3 | export * from './db';
4 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/testing/mocks/initialize.ts:
--------------------------------------------------------------------------------
1 | import { IS_SERVER } from '@/config/constants';
2 |
3 | import { seedDb } from './seed-db';
4 |
5 | const initializeMocks = () => {
6 | if (IS_SERVER) {
7 | const { server } = require('./server');
8 | server.listen();
9 | } else {
10 | const { worker } = require('./browser');
11 | worker.start();
12 | }
13 | seedDb();
14 | };
15 |
16 | initializeMocks();
17 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/testing/mocks/seed-db.ts:
--------------------------------------------------------------------------------
1 | import { testData } from '../test-data';
2 |
3 | import { db } from './db';
4 |
5 | export const seedDb = () => {
6 | const userCount = db.user.count();
7 |
8 | if (userCount > 0) return;
9 |
10 | testData.users.forEach((user) => db.user.create(user));
11 |
12 | testData.organizations.forEach((organization) =>
13 | db.organization.create(organization)
14 | );
15 |
16 | testData.jobs.forEach((job) => db.job.create(job));
17 | };
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/testing/mocks/server.ts:
--------------------------------------------------------------------------------
1 | import { setupServer } from 'msw/node';
2 |
3 | import { handlers } from './handlers';
4 |
5 | export const server = setupServer(...handlers);
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export type Entity = {
2 | id: string;
3 | createdAt: number;
4 | };
5 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/utils/format.ts:
--------------------------------------------------------------------------------
1 | export const formatDate = (date: number | string) => {
2 | return new Date(date).toLocaleDateString('en-US', {
3 | month: 'long',
4 | year: 'numeric',
5 | day: 'numeric',
6 | });
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-08-start/src/utils/uid.ts:
--------------------------------------------------------------------------------
1 | // https://gist.github.com/gordonbrander/2230317?permalink_comment_id=3443509#gistcomment-3443509
2 | export const uid = () => {
3 | return (
4 | performance.now().toString(36) +
5 | Math.random().toString(36)
6 | ).replace(/\./g, '');
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/cypress.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'cypress';
2 |
3 | export default defineConfig({
4 | video: false,
5 | videoUploadOnPasses: false,
6 | e2e: {
7 | // We've imported your old cypress plugins here.
8 | // You may want to clean this up later by importing these.
9 | setupNodeEvents(on, config) {
10 | return require('./cypress/plugins/index.ts')(
11 | on,
12 | config
13 | );
14 | },
15 | },
16 | });
17 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/cypress/fixtures/example.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Using fixtures to represent data",
3 | "email": "hello@cypress.io",
4 | "body": "Fixtures are a great way to mock data for responses to routes"
5 | }
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/cypress/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "esModuleInterop": true,
4 | "target": "es5",
5 | "lib": ["es5", "dom"],
6 | "types": [
7 | "node",
8 | "cypress",
9 | "@testing-library/cypress"
10 | ]
11 | },
12 | "include": ["**/*.ts"]
13 | }
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/components/button/index.ts:
--------------------------------------------------------------------------------
1 | export * from './button';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/components/content/content.tsx:
--------------------------------------------------------------------------------
1 | import { Box } from '@chakra-ui/react';
2 |
3 | export type ContentProps = {
4 | children: string;
5 | };
6 |
7 | export const Content = ({ children }: ContentProps) => {
8 | return (
9 |
10 | {children}
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/components/content/index.ts:
--------------------------------------------------------------------------------
1 | export * from './content';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/components/data-table/index.ts:
--------------------------------------------------------------------------------
1 | export * from './data-table';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/components/form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './input-field';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/components/info-card/index.ts:
--------------------------------------------------------------------------------
1 | export * from './info-card';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/components/link/index.ts:
--------------------------------------------------------------------------------
1 | export * from './link';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/components/loading/index.ts:
--------------------------------------------------------------------------------
1 | export * from './loading';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/components/loading/loading.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { Loading } from './loading';
4 |
5 | const meta: Meta = {
6 | title: 'Components/Loading',
7 | component: Loading,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => ;
13 |
14 | export const Default = Template.bind({});
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/components/loading/loading.tsx:
--------------------------------------------------------------------------------
1 | import { Center, Spinner } from '@chakra-ui/react';
2 |
3 | export const Loading = () => {
4 | return (
5 |
6 |
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/components/not-found/index.ts:
--------------------------------------------------------------------------------
1 | export * from './not-found';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/components/not-found/not-found.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { NotFound } from './not-found';
4 |
5 | const meta: Meta = {
6 | title: 'Components/NotFound',
7 | component: NotFound,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => (
13 |
14 | );
15 |
16 | export const Default = Template.bind({});
17 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/components/not-found/not-found.tsx:
--------------------------------------------------------------------------------
1 | import { NotAllowedIcon } from '@chakra-ui/icons';
2 | import {
3 | Center,
4 | Heading,
5 | VStack,
6 | } from '@chakra-ui/react';
7 |
8 | export const NotFound = () => {
9 | return (
10 |
11 |
12 |
13 | Not Found
14 |
15 |
16 | );
17 | };
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/components/notifications/index.ts:
--------------------------------------------------------------------------------
1 | export * from './notifications';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/components/seo/index.ts:
--------------------------------------------------------------------------------
1 | export * from './seo';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/components/seo/seo.tsx:
--------------------------------------------------------------------------------
1 | import Head from 'next/head';
2 |
3 | export type SeoProps = {
4 | title: string;
5 | };
6 |
7 | export const Seo = ({ title }: SeoProps) => {
8 | return (
9 |
10 | {title}
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/config/theme.ts:
--------------------------------------------------------------------------------
1 | import { extendTheme } from '@chakra-ui/react';
2 |
3 | const colors = {
4 | primary: '#1a365d',
5 | primaryAccent: 'white',
6 | };
7 |
8 | const styles = {
9 | global: {
10 | 'html, body': {
11 | height: '100%',
12 | bg: 'gray.50',
13 | },
14 |
15 | '#__next': {
16 | height: '100%',
17 | bg: 'gray.50',
18 | },
19 | },
20 | };
21 |
22 | export const theme = extendTheme({ colors, styles });
23 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/features/auth/components/login-form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './login-form';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/features/auth/components/protected/index.ts:
--------------------------------------------------------------------------------
1 | export * from './protected';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/features/auth/index.ts:
--------------------------------------------------------------------------------
1 | // api:
2 | export * from './api/get-auth-user';
3 | export * from './api/logout';
4 |
5 | // components:
6 | export * from './components/login-form';
7 | export * from './components/protected';
8 |
9 | // types:
10 | export * from './types';
11 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/features/auth/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type AuthUser = Entity & {
4 | email: string;
5 | organizationId: string;
6 | };
7 |
8 | export type LoginData = {
9 | email: string;
10 | password: string;
11 | };
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/features/jobs/components/create-job-form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './create-job-form';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/features/jobs/components/dashboard-job-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dashboard-job-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/features/jobs/components/jobs-list/index.ts:
--------------------------------------------------------------------------------
1 | export * from './jobs-list';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/features/jobs/components/public-job-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './public-job-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/features/jobs/index.ts:
--------------------------------------------------------------------------------
1 | // api:
2 | export * from './api/get-job';
3 | export * from './api/get-jobs';
4 |
5 | // components:
6 | export * from './components/create-job-form';
7 | export * from './components/dashboard-job-info';
8 | export * from './components/jobs-list';
9 | export * from './components/public-job-info';
10 |
11 | // types:
12 | export * from './types';
13 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/features/jobs/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Job = Entity & {
4 | organizationId: string;
5 | position: string;
6 | info: string;
7 | location: string;
8 | department: string;
9 | };
10 |
11 | export type CreateJobData = Pick<
12 | Job,
13 | 'position' | 'department' | 'location' | 'info'
14 | >;
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/features/organizations/components/organization-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './organization-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/features/organizations/index.ts:
--------------------------------------------------------------------------------
1 | // api:
2 | export * from './api/get-organization';
3 |
4 | // components:
5 | export * from './components/organization-info';
6 |
7 | // types:
8 | export * from './types';
9 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/features/organizations/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Organization = Entity & {
4 | adminId: string;
5 | name: string;
6 | email: string;
7 | phone: string;
8 | info: string;
9 | };
10 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/lib/react-query.ts:
--------------------------------------------------------------------------------
1 | import { QueryClient } from '@tanstack/react-query';
2 |
3 | export const queryClient = new QueryClient({
4 | defaultOptions: {
5 | queries: {
6 | retry: false,
7 | refetchOnWindowFocus: false,
8 | useErrorBoundary: true,
9 | },
10 | },
11 | });
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/pages/404.tsx:
--------------------------------------------------------------------------------
1 | import { Center } from '@chakra-ui/react';
2 |
3 | import { Link } from '@/components/link';
4 | import { NotFound } from '@/components/not-found';
5 |
6 | const NotFoundPage = () => {
7 | return (
8 | <>
9 |
10 |
11 | Home
12 |
13 | >
14 | );
15 | };
16 |
17 | export default NotFoundPage;
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/stores/notifications/index.ts:
--------------------------------------------------------------------------------
1 | export * from './notifications';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/testing/mocks/browser.ts:
--------------------------------------------------------------------------------
1 | import { setupWorker } from 'msw';
2 |
3 | import { handlers } from './handlers';
4 |
5 | export const worker = setupWorker(...handlers);
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/testing/mocks/index.ts:
--------------------------------------------------------------------------------
1 | export * from './handlers';
2 |
3 | export * from './db';
4 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/testing/mocks/initialize.ts:
--------------------------------------------------------------------------------
1 | import { IS_SERVER } from '@/config/constants';
2 |
3 | import { seedDb } from './seed-db';
4 |
5 | const initializeMocks = () => {
6 | if (IS_SERVER) {
7 | const { server } = require('./server');
8 | server.listen();
9 | } else {
10 | const { worker } = require('./browser');
11 | worker.start();
12 | }
13 | seedDb();
14 | };
15 |
16 | initializeMocks();
17 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/testing/mocks/seed-db.ts:
--------------------------------------------------------------------------------
1 | import { testData } from '../test-data';
2 |
3 | import { db } from './db';
4 |
5 | export const seedDb = () => {
6 | const userCount = db.user.count();
7 |
8 | if (userCount > 0) return;
9 |
10 | testData.users.forEach((user) => db.user.create(user));
11 |
12 | testData.organizations.forEach((organization) =>
13 | db.organization.create(organization)
14 | );
15 |
16 | testData.jobs.forEach((job) => db.job.create(job));
17 | };
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/testing/mocks/server.ts:
--------------------------------------------------------------------------------
1 | import { setupServer } from 'msw/node';
2 |
3 | import { handlers } from './handlers';
4 |
5 | export const server = setupServer(...handlers);
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export type Entity = {
2 | id: string;
3 | createdAt: number;
4 | };
5 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/utils/format.ts:
--------------------------------------------------------------------------------
1 | export const formatDate = (date: number | string) => {
2 | return new Date(date).toLocaleDateString('en-US', {
3 | month: 'long',
4 | year: 'numeric',
5 | day: 'numeric',
6 | });
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-08/src/utils/uid.ts:
--------------------------------------------------------------------------------
1 | // https://gist.github.com/gordonbrander/2230317?permalink_comment_id=3443509#gistcomment-3443509
2 | export const uid = () => {
3 | return (
4 | performance.now().toString(36) +
5 | Math.random().toString(36)
6 | ).replace(/\./g, '');
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/cypress.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'cypress';
2 |
3 | export default defineConfig({
4 | video: false,
5 | videoUploadOnPasses: false,
6 | e2e: {
7 | // We've imported your old cypress plugins here.
8 | // You may want to clean this up later by importing these.
9 | setupNodeEvents(on, config) {
10 | return require('./cypress/plugins/index.ts')(
11 | on,
12 | config
13 | );
14 | },
15 | },
16 | });
17 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/cypress/fixtures/example.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Using fixtures to represent data",
3 | "email": "hello@cypress.io",
4 | "body": "Fixtures are a great way to mock data for responses to routes"
5 | }
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/cypress/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "esModuleInterop": true,
4 | "target": "es5",
5 | "lib": ["es5", "dom"],
6 | "types": [
7 | "node",
8 | "cypress",
9 | "@testing-library/cypress"
10 | ]
11 | },
12 | "include": ["**/*.ts"]
13 | }
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/components/button/index.ts:
--------------------------------------------------------------------------------
1 | export * from './button';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/components/content/content.tsx:
--------------------------------------------------------------------------------
1 | import { Box } from '@chakra-ui/react';
2 |
3 | export type ContentProps = {
4 | children: string;
5 | };
6 |
7 | export const Content = ({ children }: ContentProps) => {
8 | return (
9 |
10 | {children}
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/components/content/index.ts:
--------------------------------------------------------------------------------
1 | export * from './content';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/components/data-table/index.ts:
--------------------------------------------------------------------------------
1 | export * from './data-table';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/components/form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './input-field';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/components/info-card/index.ts:
--------------------------------------------------------------------------------
1 | export * from './info-card';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/components/link/index.ts:
--------------------------------------------------------------------------------
1 | export * from './link';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/components/loading/index.ts:
--------------------------------------------------------------------------------
1 | export * from './loading';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/components/loading/loading.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { Loading } from './loading';
4 |
5 | const meta: Meta = {
6 | title: 'Components/Loading',
7 | component: Loading,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => ;
13 |
14 | export const Default = Template.bind({});
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/components/loading/loading.tsx:
--------------------------------------------------------------------------------
1 | import { Center, Spinner } from '@chakra-ui/react';
2 |
3 | export const Loading = () => {
4 | return (
5 |
6 |
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/components/not-found/index.ts:
--------------------------------------------------------------------------------
1 | export * from './not-found';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/components/not-found/not-found.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { NotFound } from './not-found';
4 |
5 | const meta: Meta = {
6 | title: 'Components/NotFound',
7 | component: NotFound,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => (
13 |
14 | );
15 |
16 | export const Default = Template.bind({});
17 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/components/not-found/not-found.tsx:
--------------------------------------------------------------------------------
1 | import { NotAllowedIcon } from '@chakra-ui/icons';
2 | import {
3 | Center,
4 | Heading,
5 | VStack,
6 | } from '@chakra-ui/react';
7 |
8 | export const NotFound = () => {
9 | return (
10 |
11 |
12 |
13 | Not Found
14 |
15 |
16 | );
17 | };
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/components/notifications/index.ts:
--------------------------------------------------------------------------------
1 | export * from './notifications';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/components/seo/index.ts:
--------------------------------------------------------------------------------
1 | export * from './seo';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/components/seo/seo.tsx:
--------------------------------------------------------------------------------
1 | import Head from 'next/head';
2 |
3 | export type SeoProps = {
4 | title: string;
5 | };
6 |
7 | export const Seo = ({ title }: SeoProps) => {
8 | return (
9 |
10 | {title}
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/config/theme.ts:
--------------------------------------------------------------------------------
1 | import { extendTheme } from '@chakra-ui/react';
2 |
3 | const colors = {
4 | primary: '#1a365d',
5 | primaryAccent: 'white',
6 | };
7 |
8 | const styles = {
9 | global: {
10 | 'html, body': {
11 | height: '100%',
12 | bg: 'gray.50',
13 | },
14 |
15 | '#__next': {
16 | height: '100%',
17 | bg: 'gray.50',
18 | },
19 | },
20 | };
21 |
22 | export const theme = extendTheme({ colors, styles });
23 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/features/auth/components/login-form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './login-form';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/features/auth/components/protected/index.ts:
--------------------------------------------------------------------------------
1 | export * from './protected';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/features/auth/index.ts:
--------------------------------------------------------------------------------
1 | // api:
2 | export * from './api/get-auth-user';
3 | export * from './api/logout';
4 |
5 | // components:
6 | export * from './components/login-form';
7 | export * from './components/protected';
8 |
9 | // types:
10 | export * from './types';
11 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/features/auth/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type AuthUser = Entity & {
4 | email: string;
5 | organizationId: string;
6 | };
7 |
8 | export type LoginData = {
9 | email: string;
10 | password: string;
11 | };
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/features/jobs/components/create-job-form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './create-job-form';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/features/jobs/components/dashboard-job-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dashboard-job-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/features/jobs/components/jobs-list/index.ts:
--------------------------------------------------------------------------------
1 | export * from './jobs-list';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/features/jobs/components/public-job-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './public-job-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/features/jobs/index.ts:
--------------------------------------------------------------------------------
1 | // api:
2 | export * from './api/get-job';
3 | export * from './api/get-jobs';
4 |
5 | // components:
6 | export * from './components/create-job-form';
7 | export * from './components/dashboard-job-info';
8 | export * from './components/jobs-list';
9 | export * from './components/public-job-info';
10 |
11 | // types:
12 | export * from './types';
13 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/features/jobs/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Job = Entity & {
4 | organizationId: string;
5 | position: string;
6 | info: string;
7 | location: string;
8 | department: string;
9 | };
10 |
11 | export type CreateJobData = Pick<
12 | Job,
13 | 'position' | 'department' | 'location' | 'info'
14 | >;
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/features/organizations/components/organization-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './organization-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/features/organizations/index.ts:
--------------------------------------------------------------------------------
1 | // api:
2 | export * from './api/get-organization';
3 |
4 | // components:
5 | export * from './components/organization-info';
6 |
7 | // types:
8 | export * from './types';
9 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/features/organizations/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Organization = Entity & {
4 | adminId: string;
5 | name: string;
6 | email: string;
7 | phone: string;
8 | info: string;
9 | };
10 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/lib/react-query.ts:
--------------------------------------------------------------------------------
1 | import { QueryClient } from '@tanstack/react-query';
2 |
3 | export const queryClient = new QueryClient({
4 | defaultOptions: {
5 | queries: {
6 | retry: false,
7 | refetchOnWindowFocus: false,
8 | useErrorBoundary: true,
9 | },
10 | },
11 | });
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/pages/404.tsx:
--------------------------------------------------------------------------------
1 | import { Center } from '@chakra-ui/react';
2 |
3 | import { Link } from '@/components/link';
4 | import { NotFound } from '@/components/not-found';
5 |
6 | const NotFoundPage = () => {
7 | return (
8 | <>
9 |
10 |
11 | Home
12 |
13 | >
14 | );
15 | };
16 |
17 | export default NotFoundPage;
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/stores/notifications/index.ts:
--------------------------------------------------------------------------------
1 | export * from './notifications';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/testing/mocks/browser.ts:
--------------------------------------------------------------------------------
1 | import { setupWorker } from 'msw';
2 |
3 | import { handlers } from './handlers';
4 |
5 | export const worker = setupWorker(...handlers);
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/testing/mocks/index.ts:
--------------------------------------------------------------------------------
1 | export * from './handlers';
2 |
3 | export * from './db';
4 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/testing/mocks/initialize.ts:
--------------------------------------------------------------------------------
1 | import { IS_SERVER } from '@/config/constants';
2 |
3 | import { seedDb } from './seed-db';
4 |
5 | const initializeMocks = () => {
6 | if (IS_SERVER) {
7 | const { server } = require('./server');
8 | server.listen();
9 | } else {
10 | const { worker } = require('./browser');
11 | worker.start();
12 | }
13 | seedDb();
14 | };
15 |
16 | initializeMocks();
17 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/testing/mocks/server.ts:
--------------------------------------------------------------------------------
1 | import { setupServer } from 'msw/node';
2 |
3 | import { handlers } from './handlers';
4 |
5 | export const server = setupServer(...handlers);
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export type Entity = {
2 | id: string;
3 | createdAt: number;
4 | };
5 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/utils/format.ts:
--------------------------------------------------------------------------------
1 | export const formatDate = (date: number | string) => {
2 | return new Date(date).toLocaleDateString('en-US', {
3 | month: 'long',
4 | year: 'numeric',
5 | day: 'numeric',
6 | });
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-09-start/src/utils/uid.ts:
--------------------------------------------------------------------------------
1 | // https://gist.github.com/gordonbrander/2230317?permalink_comment_id=3443509#gistcomment-3443509
2 | export const uid = () => {
3 | return (
4 | performance.now().toString(36) +
5 | Math.random().toString(36)
6 | ).replace(/\./g, '');
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/cypress.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'cypress';
2 |
3 | export default defineConfig({
4 | video: false,
5 | videoUploadOnPasses: false,
6 | e2e: {
7 | // We've imported your old cypress plugins here.
8 | // You may want to clean this up later by importing these.
9 | setupNodeEvents(on, config) {
10 | return require('./cypress/plugins/index.ts')(
11 | on,
12 | config
13 | );
14 | },
15 | },
16 | });
17 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/cypress/fixtures/example.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Using fixtures to represent data",
3 | "email": "hello@cypress.io",
4 | "body": "Fixtures are a great way to mock data for responses to routes"
5 | }
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/cypress/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "esModuleInterop": true,
4 | "target": "es5",
5 | "lib": ["es5", "dom"],
6 | "types": [
7 | "node",
8 | "cypress",
9 | "@testing-library/cypress"
10 | ]
11 | },
12 | "include": ["**/*.ts"]
13 | }
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/components/button/index.ts:
--------------------------------------------------------------------------------
1 | export * from './button';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/components/content/content.tsx:
--------------------------------------------------------------------------------
1 | import { Box } from '@chakra-ui/react';
2 |
3 | export type ContentProps = {
4 | children: string;
5 | };
6 |
7 | export const Content = ({ children }: ContentProps) => {
8 | return (
9 |
10 | {children}
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/components/content/index.ts:
--------------------------------------------------------------------------------
1 | export * from './content';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/components/data-table/index.ts:
--------------------------------------------------------------------------------
1 | export * from './data-table';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/components/form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './input-field';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/components/info-card/index.ts:
--------------------------------------------------------------------------------
1 | export * from './info-card';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/components/link/index.ts:
--------------------------------------------------------------------------------
1 | export * from './link';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/components/loading/index.ts:
--------------------------------------------------------------------------------
1 | export * from './loading';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/components/loading/loading.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { Loading } from './loading';
4 |
5 | const meta: Meta = {
6 | title: 'Components/Loading',
7 | component: Loading,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => ;
13 |
14 | export const Default = Template.bind({});
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/components/loading/loading.tsx:
--------------------------------------------------------------------------------
1 | import { Center, Spinner } from '@chakra-ui/react';
2 |
3 | export const Loading = () => {
4 | return (
5 |
6 |
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/components/not-found/index.ts:
--------------------------------------------------------------------------------
1 | export * from './not-found';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/components/not-found/not-found.stories.tsx:
--------------------------------------------------------------------------------
1 | import { Meta, Story } from '@storybook/react';
2 |
3 | import { NotFound } from './not-found';
4 |
5 | const meta: Meta = {
6 | title: 'Components/NotFound',
7 | component: NotFound,
8 | };
9 |
10 | export default meta;
11 |
12 | const Template: Story = (props) => (
13 |
14 | );
15 |
16 | export const Default = Template.bind({});
17 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/components/not-found/not-found.tsx:
--------------------------------------------------------------------------------
1 | import { NotAllowedIcon } from '@chakra-ui/icons';
2 | import {
3 | Center,
4 | Heading,
5 | VStack,
6 | } from '@chakra-ui/react';
7 |
8 | export const NotFound = () => {
9 | return (
10 |
11 |
12 |
13 | Not Found
14 |
15 |
16 | );
17 | };
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/components/notifications/index.ts:
--------------------------------------------------------------------------------
1 | export * from './notifications';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/components/seo/index.ts:
--------------------------------------------------------------------------------
1 | export * from './seo';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/components/seo/seo.tsx:
--------------------------------------------------------------------------------
1 | import Head from 'next/head';
2 |
3 | export type SeoProps = {
4 | title: string;
5 | };
6 |
7 | export const Seo = ({ title }: SeoProps) => {
8 | return (
9 |
10 | {title}
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/config/theme.ts:
--------------------------------------------------------------------------------
1 | import { extendTheme } from '@chakra-ui/react';
2 |
3 | const colors = {
4 | primary: '#1a365d',
5 | primaryAccent: 'white',
6 | };
7 |
8 | const styles = {
9 | global: {
10 | 'html, body': {
11 | height: '100%',
12 | bg: 'gray.50',
13 | },
14 |
15 | '#__next': {
16 | height: '100%',
17 | bg: 'gray.50',
18 | },
19 | },
20 | };
21 |
22 | export const theme = extendTheme({ colors, styles });
23 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/features/auth/components/login-form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './login-form';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/features/auth/components/protected/index.ts:
--------------------------------------------------------------------------------
1 | export * from './protected';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/features/auth/index.ts:
--------------------------------------------------------------------------------
1 | // api:
2 | export * from './api/get-auth-user';
3 | export * from './api/logout';
4 |
5 | // components:
6 | export * from './components/login-form';
7 | export * from './components/protected';
8 |
9 | // types:
10 | export * from './types';
11 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/features/auth/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type AuthUser = Entity & {
4 | email: string;
5 | organizationId: string;
6 | };
7 |
8 | export type LoginData = {
9 | email: string;
10 | password: string;
11 | };
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/features/jobs/components/create-job-form/index.ts:
--------------------------------------------------------------------------------
1 | export * from './create-job-form';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/features/jobs/components/dashboard-job-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dashboard-job-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/features/jobs/components/jobs-list/index.ts:
--------------------------------------------------------------------------------
1 | export * from './jobs-list';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/features/jobs/components/public-job-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './public-job-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/features/jobs/index.ts:
--------------------------------------------------------------------------------
1 | // api:
2 | export * from './api/get-job';
3 | export * from './api/get-jobs';
4 |
5 | // components:
6 | export * from './components/create-job-form';
7 | export * from './components/dashboard-job-info';
8 | export * from './components/jobs-list';
9 | export * from './components/public-job-info';
10 |
11 | // types:
12 | export * from './types';
13 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/features/jobs/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Job = Entity & {
4 | organizationId: string;
5 | position: string;
6 | info: string;
7 | location: string;
8 | department: string;
9 | };
10 |
11 | export type CreateJobData = Pick<
12 | Job,
13 | 'position' | 'department' | 'location' | 'info'
14 | >;
15 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/features/organizations/components/organization-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './organization-info';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/features/organizations/index.ts:
--------------------------------------------------------------------------------
1 | // api:
2 | export * from './api/get-organization';
3 |
4 | // components:
5 | export * from './components/organization-info';
6 |
7 | // types:
8 | export * from './types';
9 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/features/organizations/types/index.ts:
--------------------------------------------------------------------------------
1 | import { Entity } from '@/types';
2 |
3 | export type Organization = Entity & {
4 | adminId: string;
5 | name: string;
6 | email: string;
7 | phone: string;
8 | info: string;
9 | };
10 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/lib/react-query.ts:
--------------------------------------------------------------------------------
1 | import { QueryClient } from '@tanstack/react-query';
2 |
3 | export const queryClient = new QueryClient({
4 | defaultOptions: {
5 | queries: {
6 | retry: false,
7 | refetchOnWindowFocus: false,
8 | useErrorBoundary: true,
9 | },
10 | },
11 | });
12 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/pages/404.tsx:
--------------------------------------------------------------------------------
1 | import { Center } from '@chakra-ui/react';
2 |
3 | import { Link } from '@/components/link';
4 | import { NotFound } from '@/components/not-found';
5 |
6 | const NotFoundPage = () => {
7 | return (
8 | <>
9 |
10 |
11 | Home
12 |
13 | >
14 | );
15 | };
16 |
17 | export default NotFoundPage;
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/stores/notifications/index.ts:
--------------------------------------------------------------------------------
1 | export * from './notifications';
2 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/testing/mocks/browser.ts:
--------------------------------------------------------------------------------
1 | import { setupWorker } from 'msw';
2 |
3 | import { handlers } from './handlers';
4 |
5 | export const worker = setupWorker(...handlers);
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/testing/mocks/index.ts:
--------------------------------------------------------------------------------
1 | export * from './handlers';
2 |
3 | export * from './db';
4 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/testing/mocks/initialize.ts:
--------------------------------------------------------------------------------
1 | import { IS_SERVER } from '@/config/constants';
2 |
3 | import { seedDb } from './seed-db';
4 |
5 | const initializeMocks = () => {
6 | if (IS_SERVER) {
7 | const { server } = require('./server');
8 | server.listen();
9 | } else {
10 | const { worker } = require('./browser');
11 | worker.start();
12 | }
13 | seedDb();
14 | };
15 |
16 | initializeMocks();
17 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/testing/mocks/seed-db.ts:
--------------------------------------------------------------------------------
1 | import { testData } from '../test-data';
2 |
3 | import { db } from './db';
4 |
5 | export const seedDb = () => {
6 | const userCount = db.user.count();
7 |
8 | if (userCount > 0) return;
9 |
10 | testData.users.forEach((user) => db.user.create(user));
11 |
12 | testData.organizations.forEach((organization) =>
13 | db.organization.create(organization)
14 | );
15 |
16 | testData.jobs.forEach((job) => db.job.create(job));
17 | };
18 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/testing/mocks/server.ts:
--------------------------------------------------------------------------------
1 | import { setupServer } from 'msw/node';
2 |
3 | import { handlers } from './handlers';
4 |
5 | export const server = setupServer(...handlers);
6 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export type Entity = {
2 | id: string;
3 | createdAt: number;
4 | };
5 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/utils/format.ts:
--------------------------------------------------------------------------------
1 | export const formatDate = (date: number | string) => {
2 | return new Date(date).toLocaleDateString('en-US', {
3 | month: 'long',
4 | year: 'numeric',
5 | day: 'numeric',
6 | });
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/src/utils/uid.ts:
--------------------------------------------------------------------------------
1 | // https://gist.github.com/gordonbrander/2230317?permalink_comment_id=3443509#gistcomment-3443509
2 | export const uid = () => {
3 | return (
4 | performance.now().toString(36) +
5 | Math.random().toString(36)
6 | ).replace(/\./g, '');
7 | };
8 |
--------------------------------------------------------------------------------
/code-stages/chapter-09/vercel.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 2,
3 | "github": {
4 | "enabled": false
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/lint-staged.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | '*.{ts,tsx}': [
3 | 'npm run lint',
4 | "bash -c 'npm run types:check'",
5 | 'npm run format:check',
6 | ],
7 | };
8 |
--------------------------------------------------------------------------------
/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/basic-features/typescript for more information.
6 |
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | module.exports = {
3 | reactStrictMode: true,
4 | experimental: {
5 | esmExternals: false,
6 | },
7 | };
8 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PacktPublishing/React-Application-Architecture-for-Production/40cd19895fa025e7c48127f187035ec451874061/public/favicon.ico
--------------------------------------------------------------------------------
/scripts/clear-stage.js:
--------------------------------------------------------------------------------
1 | const { clearCurrent } = require('./utils');
2 |
3 | async function clearStage() {
4 | await clearCurrent();
5 |
6 | console.log('Success: stage cleared!');
7 | }
8 |
9 | clearStage();
10 |
--------------------------------------------------------------------------------