diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..106b3f2 --- /dev/null +++ b/.env.example @@ -0,0 +1,15 @@ +NEXT_PUBLIC_ENABLE_REDUX_DEV_TOOLS= +NEXT_PUBLIC_AUTH0_CLIENT_ID= +NEXT_PUBLIC_AUTH0_DOMAIN= +NEXT_PUBLIC_AWS_COGNITO_IDENTITY_POOL_ID= +NEXT_PUBLIC_AWS_COGNITO_REGION= +NEXT_PUBLIC_AWS_PROJECT_REGION= +NEXT_PUBLIC_AWS_USER_POOLS_ID= +NEXT_PUBLIC_AWS_USER_POOLS_WEB_CLIENT_ID= +NEXT_PUBLIC_FIREBASE_API_KEY= +NEXT_PUBLIC_FIREBASE_APP_ID= +NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN= +NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID= +NEXT_PUBLIC_FIREBASE_PROJECT_ID= +NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET= +NEXT_PUBLIC_GTM_CONTAINER_ID= diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..7f16f4f --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,15 @@ +{ + "extends": "next/core-web-vitals", + "rules": { + "@next/next/no-img-element": "off", + "jsx-a11y/alt-text": "off", + "react/display-name": "off", + "react/no-children-prop": "off", + "react/jsx-max-props-per-line": [ + 1, + { + "maximum": 1 + } + ] + } +} diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..fbd75d3 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=lf \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0f2b54d --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build +.next + +# misc +.DS_Store +.eslintcache +/.env +/.env.local +/.env.development.local +/.env.test.local +/.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/README.md b/README.md new file mode 100644 index 0000000..c87e042 --- /dev/null +++ b/README.md @@ -0,0 +1,34 @@ +This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file. + +[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`. + +The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/_docs/analytics-configuration.md b/_docs/analytics-configuration.md new file mode 100644 index 0000000..f3af94a --- /dev/null +++ b/_docs/analytics-configuration.md @@ -0,0 +1,32 @@ +--- +title: Analytics Configuration +--- + +# Configuration + +## Create GTM account + +In order to use the GTM platform, you need to create a GTM account. Read more about it +[here](https://support.google.com/tagmanager/answer/6103696?hl=en#install&zippy=%2Cweb-pages). + +## Set up configuration options + +The app uses environment variables because it can be deployed with different accounts +for `development`, `qa`, and `production`. This allows you to configure the GTM library differently +for each environment. + +Open `.env` file (or create) in the project's root folder and set the +variable `NEXT_PUBLIC_GTM_CONTAINER_ID` with the container ID provided by GTM platform. + +```shell +NEXT_PUBLIC_GTM_CONTAINER_ID=GTM-XXXXXX +``` + +If you do not want to set up environment variables, settings can be applied simply on +the `gtmConfig` object found in the `src/config.js` file. + +```js +export const gtmConfig = { + containerId: '' +}; +``` diff --git a/_docs/analytics-event-tracking.md b/_docs/analytics-event-tracking.md new file mode 100644 index 0000000..dc8170d --- /dev/null +++ b/_docs/analytics-event-tracking.md @@ -0,0 +1,66 @@ +--- +title: Event tracking +--- + +# Event tracking + +By default, the GTM library's push platform captures the browser location data, such as url, +pathname, title, and other details. You can extend it to match your business needs. For example, you +may need the event name, site section, campaign name, product name, price, process step, etc. + +## Page view + +```jsx +// src/pages/login.js +import { useEffect } from 'react'; +import { gtm } from '../lib/gtm'; + +const Login = () => { + useEffect(() => { + gtm.push({event: 'page_view'}); + }, []); + + return ( +
+ content +
+ ); +}; +``` + +This example shows you how to track the page view event once the page component gets mounted. It can +also be used on mounting virtual pages, such as modals, dialogs, etc. + +## Other action + +```jsx +// src/pages/product.js +import { gtm } from '../lib/gtm'; + +const Product = () => { + const handleAddToCart = () => { + gtm.push({ + event: 'add_to_cart', + price: '317,65', + currency: 'EUR', + name: 'Dell Monitor 27"' + }); + }; + + return ( +
+
Dell Monitor 27"
+
EUR 317,65
+ +
+ ); +}; +``` + +As it can be seen, this example has multiple variables to help you identify the product that was +added to cart and its price. These are called conversion variables in most systems, and they are +used to determine the user behaviour after visiting a specific page or site section. If the user +does not complete the checkout process, you are able to identify most products added to the cart, +and make decisions based on metrics. diff --git a/_docs/analytics-introduction.md b/_docs/analytics-introduction.md new file mode 100644 index 0000000..14b4093 --- /dev/null +++ b/_docs/analytics-introduction.md @@ -0,0 +1,28 @@ +--- +title: Analytics Introduction +--- + +# Introduction + +For many companies is important to understand the user traffic, origin and behaviour. This may apply +to your business, and you can find an example in the app. + +## Google Tag Manager (GTM) + +In previous versions the app used `Google Analytics` directly, but for this version it uses GTM. +This enables a lot more control over the analytics implementation and also helps you display things +like GDPR modal, various targeted content; control the data transfer, cookies and other aspects +based on user data privacy preferences. Read more about GTM +[here](https://support.google.com/tagmanager/answer/6102821?hl=en&ref_topic=3441530). + +## How GTM it works + +In order to use the `GTM platform` you set up a container, then you create a tag for each provider +you need, for example, Google Analytics. Then, using the triggers, you control multiple tags based +on data pushed to the data layer. The data pushed gets computed on the client (browser), and then +the library determines which tags will be loaded. + +## How is it implemented + +The app uses a small singleton class to help with loading the `GTM library`, initialize it and track +events via the GTM available methods. diff --git a/_docs/auth-guard.md b/_docs/auth-guard.md new file mode 100644 index 0000000..bfa46cd --- /dev/null +++ b/_docs/auth-guard.md @@ -0,0 +1,39 @@ +--- +title: Auth Guard +--- + +# Auth Guard + +This is a simple component that can be used to protect a private route. It controls whether it +should allow navigation to a requested route based on given context. Similar to the GuestGuard, +the app provides a `hoc` to prevent the entire page render. + +## Example + +```jsx +// src/pages/dashboard/index.js +import { withAuthGuard } from '../../hocs/with-auth-guard'; + +const Overview = () => { + return ( +
+ content +
+ ); +}; + +export default withAuthGuard(Overview); +``` + +## How it works + +It connects with the authentication provider (Amplify, Auth0, Firebase, or JWT, depending on your +setup) and extracts the required data to detect whether it should render the children passed as +props, otherwise it redirects to the `Login` component with a redirect url query string parameter +to allow the Login component to redirect back to the requested url after a successful +authentication. + +## How it can be extended + +As mentioned, this is a sample component, thus it can and should be adjusted to match your business +needs. diff --git a/_docs/authentication-amplify.md b/_docs/authentication-amplify.md new file mode 100644 index 0000000..34ca543 --- /dev/null +++ b/_docs/authentication-amplify.md @@ -0,0 +1,147 @@ +--- +title: Amplify +--- + +# Amplify + +AWS Amplify is a set of services accompanied by various tools and libraries created to help the +development of apps. Their suite offers among other features, an authentication feature, which can +be used as a stand-alone authentication system. The project is able to be used with this +authentication system, as well. Should you want to implement any of the other features Amplify +offers, you can refer to their [documentation](https://docs.amplify.aws/). + +## Set up your Amplify account + +The documentation for this, can be found in the official documentation of the service, mentioned +above. + +## Configuration + +In order to configure Amplify client library you have to open (or create) `.env` file in the +project's root folder and set the following variables as presented in your Amplify account settings: + +```shell +NEXT_PUBLIC_AWS_COGNITO_IDENTITY_POOL_ID= +NEXT_PUBLIC_AWS_COGNITO_REGION= +NEXT_PUBLIC_AWS_PROJECT_REGION= +NEXT_PUBLIC_AWS_USER_POOLS_ID= +NEXT_PUBLIC_AWS_USER_POOLS_WEB_CLIENT_ID= +``` + +If you do not want to set up environment variables, settings can be applied simply on +the `amplifyConfig` object found in the `src/config.js` file. + +```js +export const amplifyConfig = { + aws_project_region: '', + aws_cognito_identity_pool_id: '', + aws_cognito_region: '', + aws_user_pools_id: '', + aws_user_pools_web_client_id: '' +}; +``` + +## How it was implemented + +As mentioned above, Amplify offers a set of components to help your development process, although +they're not used in the app. + +The `Auth` singleton from the library is used to provide the authentication feature to a context ( +which wraps the content of the `App` component). + +This aforementioned context is then used in the component tree to access the `Auth` public methods. +It provides the user authentication status and user profile, if available. + +## How to use Amplify Provider + +By default, the project uses a mocked `JWT provider` (as in: it doesn't use an actual JWT based +authentication server). To make use of Amplify simply follow these steps: + +### Step 1. Replace the provider and consumer + +Open `src/pages/_app.js` file and replace the following line: + +```js +import { AuthConsumer, AuthProvider } from '../contexts/jwt-context'; +``` + +with + +```js +import { AuthConsumer, AuthProvider } from '../contexts/amplify-context'; +``` + +### Step 2. Replace the hook context + +Open `src/hooks/use-auth.js` file and replace the following line: + +```js +import { AuthContext } from '../contexts/jwt-context'; +``` + +with + +```js +import { AuthContext } from '../contexts/amplify-context'; +``` + +## How to use auth + +### Retrieve user profile + +In the example below, you can find how it can be used in any component not just the `App`. Should +you want to use it in any other component, you'll have to import the `useAuth` hook and use it as +needed. + +```jsx +// src/pages/index.js +import { useAuth } from '../hooks/use-auth'; + +const Home = () => { + const { user } = useAuth(); + + return ( +
+ Email: {user.email} +
+ ); +}; +``` + +### Auth methods / actions + +> For simplicity and space limitations, the code below is used only to exemplify, actual code can be found in the components. + +```jsx +// src/pages/index.js +import { useAuth } from '../hooks/use-auth'; + +const Home = () => { + const { login } = useAuth(); + + const handleLogin = () => { + // Email/username and password + login('demo@melsoft.co.za', 'Password123!'); + }; + + return ( +
+ +
+ ); +}; +``` + +## Implemented flows + +Currently, the app only covers the main flows: + +- Sign in +- Sign up +- Confirm sign up +- Resend sign up +- Forgot password +- Forgot password submit +- Logout diff --git a/_docs/authentication-auth0.md b/_docs/authentication-auth0.md new file mode 100644 index 0000000..d977fd4 --- /dev/null +++ b/_docs/authentication-auth0.md @@ -0,0 +1,135 @@ +--- +title: Auth0 +--- + +# Auth0 + +Auth0 is an easy to implement, adaptable authentication and authorization platform. Auth0 provides a +library built for React, but the app uses a more generic library designed for universal SPAs. This +gives you more control over the components, as the app needs to provide support for multiple +authentication providers. You can refer to their [documentation](https://auth0.com/docs/) +as you deem fit, or in case you need things not covered in the app. + +## Set up your Auth0 account + +The documentation for this, can be found in the official documentation of the service, mentioned +above. + +## Configuration + +To configure Auth0 client library you have to open (or create) `.env` file in the project's root +folder and set the following variables as presented in your Auth0 account settings: + +```shell +NEXT_PUBLIC_AUTH0_CLIENT_ID= +NEXT_PUBLIC_AUTH0_DOMAIN= +``` + +If you do not want to set up environment variables you can simply set the `auth0Config` object +from `src/config.js` file. + +```js +export const auth0Config = { + client_id: '', + domain: '' +}; +``` + +## How it was implemented + +As mentioned, Auth0 offers a set of components to help your development process, although they're +not used in the app. + +The `Auth0Client` class from the library is used to provide the authentication feature to a +context (which wraps the content of the `App` component). + +This aforementioned context is then used in the component tree to access the `Auth0Client` instance +public methods. It provides the user authentication status and user profile, if available. + +## How to use Auth0 Provider + +By default, the project uses a mocked `JWT provider` (as in: it doesn't use an actual JWT based +authentication server). To make use of Amplify simply follow these steps: + +### Step 1. Replace the provider + +Open `src/pages/_app.js` file and replace the following line: + +```js +import { AuthConsumer, AuthProvider } from '../contexts/jwt-context'; +``` + +with + +```js +import { AuthConsumer, AuthProvider } from '../contexts/auth0-context'; +``` + +### Step 2. Replace the hook context + +Open `src/hooks/use-auth.js` file and replace the following line: + +```js +import { AuthContext } from '../contexts/jwt-context'; +``` + +with + +```js +import { AuthContext } from '../contexts/auth0-context'; +``` + +## How to use auth + +### Retrieve user profile + +In the example below, you can find how it can be used in any component not just the `App`. Should +you want to use it in any other component, you'll have to import the `useAuth` hook and use it as +needed. + +```jsx +// src/pages/index.js +import { useAuth } from '../hooks/use-auth'; + +const Home = () => { + const { user } = useAuth(); + + return ( +
+ Email: {user.email} +
+ ); +}; +``` + +### Auth methods / actions + +> For simplicity and space limitations, the code below is used only to exemplify, actual code can be found in the components. + +```jsx +// src/pages/index.js +import { useAuth } from '../hooks/use-auth'; + +const Home = () => { + const { loginWithPopup } = useAuth(); + + const handleLogin = () => { + loginWithPopup(); + }; + + return ( +
+ +
+ ); +}; +``` + +## Implemented flows + +Currently, the app only covers the main flows: + +- Login with popup (also used to register) +- Logout diff --git a/_docs/authentication-firebase.md b/_docs/authentication-firebase.md new file mode 100644 index 0000000..d7b9dac --- /dev/null +++ b/_docs/authentication-firebase.md @@ -0,0 +1,146 @@ +--- +title: Firebase +--- + +# Firebase + +Firebase is a complete set of solutions, from Analytics to Cloud Functions. In the app at hand, only +the authentication service is used, although you can decide to use more of their features. Please +refer to their [documentation](https://firebase.google.com/docs) +as you deem necessary. + +## Set up your Firebase account + +The documentation for this, can be found in the official documentation of the service, mentioned +above. + +## Configuration + +To configure Firebase client library you have to open (or create) `.env` file in the project's root +folder and set the following variables as presented in your Firebase account settings: + +```shell +NEXT_PUBLIC_FIREBASE_API_KEY= +NEXT_PUBLIC_FIREBASE_APP_ID= +NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN= +NEXT_PUBLIC_FIREBASE_DATABASE_URL= +NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID= +NEXT_PUBLIC_FIREBASE_PROJECT_ID= +NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET= +``` + +If you do not want to set up environment variables, settings can be applied simply on +the `firebaseConfig` object found in the `src/config.js` file. + +```js +export const firebaseConfig = { + apiKey: '', + appId: '', + authDomain: '', + messagingSenderId: '', + projectId: '', + storageBucket: '' +}; +``` + +## How it was implemented + +As mentioned above, Firebase offers a set of components to help your development process, although +they're not used in the app. + +The `firebase.auth` factory from the library is used to create and provide the authentication +feature to a context (which wraps the content of the `App` component). + +This aforementioned context is then used in the component tree to access the `Auth` public methods. +It provides the user authentication status and user profile, if available. + +## How to use Firebase Auth Provider + +By default, the project uses a mocked `JWT provider` (as in: it doesn't use an actual JWT based +authentication server). To make use of Amplify simply follow these steps: + +### Step 1. Replace the provider + +Open `src/pages/_app.js` file and replace the following line: + +```js +import { AuthConsumer, AuthProvider } from '../contexts/jwt-context'; +``` + +with + +```js +import { AuthConsumer, AuthProvider } from '../contexts/firebase-auth-context'; +``` + +### Step 2. Replace the hook context + +Open `src/hooks/use-auth.js` file and replace the following line: + +```js +import { AuthContext } from '../contexts/jwt-context'; +``` + +with + +```js +import { AuthContext } from '../contexts/firebase-auth-context'; +``` + +## How to use auth + +### Retrieve user profile + +In the example below, you can find how it can be used in any component not just the `App`. Should +you want to use it in any other component, you'll have to import the `useAuth` hook and use it as +needed. + +```jsx +// src/pages/index.js +import { useAuth } from '../hooks/use-auth'; + +const Home = () => { + const { user } = useAuth(); + + return ( +
+ Email: {user.email} +
+ ); +}; +``` + +### Auth methods / actions + +> For simplicity and space limitations, the code below is used only to exemplify, actual code can be found in the components. + +```jsx +// src/pages/index.js +import { useAuth } from '../hooks/use-auth'; + +const Home = () => { + const { signInWithEmailAndPassword } = useAuth(); + + const handleLogin = () => { + // Email and password + signInWithEmailAndPassword('demo@devias.io', 'Password123!'); + }; + + return ( +
+ +
+ ); +}; +``` + +## Implemented flows + +Currently, the app only covers the main flows: + +- Create user with email and password +- Sign in with email and password +- Sign in with popup (Google) +- Logout diff --git a/_docs/authentication-jwt.md b/_docs/authentication-jwt.md new file mode 100644 index 0000000..fef0c06 --- /dev/null +++ b/_docs/authentication-jwt.md @@ -0,0 +1,105 @@ +--- +title: JWT +--- + +# JSON Web Token (JWT) + +Most auth providers use this strategy under the hood to provide access tokens. Currently, the app +doesn't cover the backend service, and this service is mocked (faked) using http client +interceptors. The implementation is basic, but enough to give you a starting point. + +## How it was implemented + +Since tokens are meant to be created on the backend server, they are built with encrypt, encode and +decode utility methods because they are not meant to be used on the client. These utilities can be +found in `src/utils/jwt`. These are for development purposes only, and you must remove (or avoid +using) them. + +## How to use JWT Provider + +The app is delivered with JWT Provider as default auth strategy. If you changed or removed it, and +you want it back, simply follow these steps: + +### Step 1. Import the provider + +Open `src/pages/_app.js` file, import the provider and wrap the App component with it. + +```js +// src/pages/_app.js +import { AuthConsumer, AuthProvider } from '../contexts/jwt-context'; + +const App = (props) => { + const { Component, pageProps } = props; + + return ( + + + + ); +}; +``` + +### Step 2. Set the hook context + +Open `src/hooks/use-auth.js` file and replace the current context the following line: + +```js +import { AuthContext } from '../contexts/jwt-context'; +``` + +## How to use auth + +### Retrieve user profile + +In the example below, you can find how it can be used in any component not just the `App`. Should +you want to use it in any other component, you'll have to import the `useAuth` hook and use it as +needed. + +```jsx +// src/pages/index.js +import { useAuth } from '../hooks/use-auth'; + +const Home = () => { + const { user } = useAuth(); + + return ( +
+ Email: {user.email} +
+ ); +}; +``` + +### Auth methods / actions + +> For simplicity and space limitations, the code below is used only to exemplify, actual code can be found in the components. + +```jsx +// src/pages/index.js +import { useAuth } from '../hooks/use-auth'; + +const Home = () => { + const { login } = useAuth(); + + const handleLogin = () => { + // Email/username and password + login('demo@melsoft.co.za', 'Password123!'); + }; + + return ( +
+ +
+ ); +}; +``` + +## Implemented flows + +Currently, the app only covers the main flows: + +- Register +- Login +- Logout diff --git a/_docs/changelog.md b/_docs/changelog.md new file mode 100644 index 0000000..59a2855 --- /dev/null +++ b/_docs/changelog.md @@ -0,0 +1,288 @@ +--- +title: Changelog +--- + +## v5.3.0 + +###### Sep 15, 2022 + +- Update dependencies + +## v5.2.0 + +###### May 23, 2022 + +- Update dependencies + +## v5.1.0 + +###### Feb 9, 2022 + +- Activate Typescript Strict mode +- Update Firebase to v9 +- Replace Auth0 Popup with Redirect +- Fix dependencies security issues +- Update types and interfaces +- Update dependencies +- Update Sketch files to v5 + +## v5.0.2 + +###### Nov 4, 2021 + +- Reduce compile time +- Update layout strategy + +## v5.0.1 + +###### Nov 3, 2021 + +- Fix auth guard redirect bug + +## v5.0.0 + +###### Nov 2, 2021 + +- Migrate `CRA` to `Next.js 12` +- Migrate code to MUI v5 +- Add `Company Details` pages +- Add `Job Create` flow +- Add `Job Listing` page +- Add `Logistics Dashboard` page +- Cleanup code +- Remove `react-modal-image` dependency +- Update `Account` pages +- Update `Blog Platfrom` page designs +- Update `Calendar` app layout +- Update `Chat` app layout +- Update `Chat` logic +- Update `Customer Details` page +- Update `Customer List` filters +- Update `Invoice List` filters +- Update `Invoice List` page layout +- Update `Kaban` app +- Update `Landing` page +- Update `Mail` app layout +- Update `Order List` filters +- Update `Order List` page layout +- Update `Product List` filters +- Update `Product List` table +- Update design system + +--- + +## v4.1.0 + +###### May 24, 2021 + +- Add Sketch and Figma dark versions +- Add `react-hot-toast` dependency +- Fix Calendar App `Date` data type stored in Redux state warning +- Fix Kanban App card move bug +- Fix RTL bug +- Fix `nprogress` display bug +- Implement mocked api clients instead of mocked axios interceptors +- Remove `axios` and `axios-mock-adapter` dependencies +- Remove `notistack` dependency +- Remove `web-vitals` dependency +- Replace `Hidden` component with `sx` logic +- Update `material-ui` and other dependencies + +--- + +## v4.0.0 + +###### Mar 17, 2021 + +- Add `@emotion/react` and `@emotion/styled` dependencies +- Add `AWS Amplify` auth platform +- Add `Google Tag Manager` to implement tags concept +- Add `StrictMode` +- Add `date-fns` dependency to parse dates +- Add `gray-matter` dependency +- Add `react-i18next` dependency to implement multi-language +- Add `stylis` and `stylis-plugin-rtl` dependencies +- Add `web-vitals` dependency +- Add new components +- Add new pages +- Drop `IE11` support +- Fix some TS types +- Implement `sx` prop where needed +- Regroup pages +- Remove `Google Analytics` +- Remove `js-cookie` dependency +- Remove `jsonwebtoken` dependency +- Remove `jwt-decode` dependency +- Remove `lodash` dependency +- Remove `mdx` dependency +- Remove `moment` dependency +- Remove `react-chartjs-2` dependency +- Remove `uuid` dependency +- Rename components for simpler folder structure +- Replace `moment` with `date-fns` +- Replace `react-chartjs-2` with `react-apexcharts` +- Replace `react-helmet` with `react-helmet-async` dependency +- Replace `useStyles` with `experimentalStyled` strategy +- Update `@fullcalendar` dependency +- Update `@material-ui/core` and `@material-ui/icons` dependencies +- Update `react-router` to v6 +- Update existing components to match Material-UI v5 +- Update theme to use Material-UI v5 theme format + +## v3.1.0 + +###### Aug 1, 2020 + +### JavaScript + +`JavaScript` version is now in sync with the `TypeScript` version, both with the same features. + +### TypeScript + +No changes. + +--- + +## v3.0.0 + +###### July 26, 2020 + +The release introduces a new version of the product written in `TypeScript`. + +### JavaScript + +No changes. + +### TypeScript + +- Fix server-side rendering issue with SettingsProvider +- Implement `Auth0` and `Firebase Authentication` +- Improve components +- Reimplement `JWT Auth` using `Redux Context API` +- Reimplement Redux using `Redux Toolkit` +- Remove a few components `Social` platform to be able to add new ones in future updates +- Update `Login` and `Register` pages +- Update `Calendar` and `Chat` apps +- Update dependencies +- Update mocked chart to match the types +- Update `Projects` platform + +--- + +## v2.0.0 + +###### Apr 10, 2020 + +- Add `apexcharts` dependency +- Add `formik` dependency +- Add `immer` dependency +- Add `joy` dependency +- Add `mdx` dependency +- Add `notistack` dependency +- Add `react-modal-image` dependency +- Add new pages +- Implement Redux in `Chat`, `Kanban`, `Mail` apps +- Implement `AuthService` and `AuthGuard` +- Implement app settings manager +- Implement multiple themes +- Refactor components to accept multi-theme +- Remove multiple css classes and replaced the styling with `Box` component +- Update all pages implementing new Material-UI features +- Update docs to use `mdx` +- Update the mock adapter, now accepting post requests +- Update typography + +--- + +## v1.4.0 + +###### Feb 25, 2020 + +- Fix `uuid` import bug +- Update dependencies + +--- + +## v1.3.0 + +###### Sep 7, 2019 + +- Add component pages +- Add `eslint-config-airbnb` dependency +- Add `eslint-config-prettier` dependency +- Add `eslint-plugin-import` dependency +- Add `eslint-plugin-jsx-a11y` dependency +- Add `eslint-plugin-react-hooks` dependency +- Add `IE11` support +- Add `Container` component to each page to replace custom styling +- Add `RT`L support +- Fix a bug for Edge & Safari where users couldn't scroll properly +- Remove deep folder nesting to keep a clean structure +- Replace custom `useRouter` hook with `useLocation`, `useHistory` and `useParams` + from `react-router` +- Update code style to match with Airbnb style +- Update dependencies +- Update import paths +- Update the layouts to fix scroll issues + +--- + +## v1.2.0 + +###### Aug 7, 2019 + +- Add `axios` and `axios-mock-adapter` modules to simulate server response for fetch requests +- Create 3 individual layouts for error, auth and dashboard pages +- Fix navigation expand issue +- Move helpers files to `utils` folder +- Move all lib mixins to `mixins` folder +- Remove `chart.js` files +- Remove unused helpers +- Remove unused utils +- Rename few components +- Replace the routing system from 1.1.0 version with an easier solution +- Update `Calendar` page code +- Update `Chat` page code +- Update `Error` page code + +--- + +## v1.1.1 + +###### Aug 1, 2019 + +- Remove `PerfectScrollBar` to fix `Navbar` and content scroll issues + +--- + +## v1.1.0 + +###### July 31, 2019 + +- Add `Figma` source files +- Add `PrismJS` dependency +- Add `redux` dependency +- Change the layout logic +- Create `CodeBlock` component +- Create changelog page +- Create documentation pages +- Fix scroll bugs +- Implement `redux` in some components +- Implement code splitting to lazy load pages +- Implement layout system based on route settings +- Implement route authorization guard based on authenticated user role and route settings +- Implement routing system +- Merge layouts in one layout only that can be configured dynamically +- Rename few components +- Replace `underscore` with `lodash` +- Update dependencies +- Update folder structure, grouped all pages in the same folder +- Update presentation page + +--- + +## v1.0.0 + +###### July 20, 2019 + +Initial release. diff --git a/_docs/contact.md b/_docs/contact.md new file mode 100644 index 0000000..8317efc --- /dev/null +++ b/_docs/contact.md @@ -0,0 +1,23 @@ +--- +title: Contact +--- + +# Contact + +Our support mainly covers pre-sale questions, basic product questions and bug reports through our +support email: +[support@deviasio.zendesk.com](mailto:support@deviasio.zendesk.com). + +To be eligible to request the technical support you must have purchased the theme and have at least +one Standard or Extended license. + +On submitting a support request please do describe your issue with more details. If you can provide +a link to your developing site then this can help us to solve your issue faster. + +All 3rd party plugins used in the theme are provided as bonus, and we do not give any guarantee to +their functionalities. Our support does not cover any 3rd party plugin customization or bug fixes +that are not in our control. + +Customers are always welcome to ask for feature requests and give suggestions that can improve our +premium themes. All feature requests definitely will be considered, and the new features will be +released with upcoming releases. diff --git a/_docs/dependencies.md b/_docs/dependencies.md new file mode 100644 index 0000000..f2d5bca --- /dev/null +++ b/_docs/dependencies.md @@ -0,0 +1,65 @@ +--- +title: Dependencies +--- + +# Dependencies + +The app is built using the latest trends with periodic updates. The optional dependencies are used +to create app features. If you do not need a feature, please remove the dependency to keep the +project files clean and reduce dependency download and install time. + +## Important dependencies + +- `@emotion/cache` - Styling +- `@emotion/react` - Styling +- `@emotion/styled` - Styling +- `@mui/icons-material` - MUI icons +- `@mui/lab` - Base theme components +- `@mui/material` - Base theme components +- `@mui/system` - Base theme system utilities +- `date-fns` - Utils to parse date and time +- `react` - Core +- `next` - Core +- `stylis` - Styling +- `stylis-plugin-rtl` - Styling + +## Optional dependencies + +- `@auth0/auth0-spa-js` - Handle Auth0 authentication +- `@fullcalendar/core` - Calendar +- `@fullcalendar/daygrid` - Calendar +- `@fullcalendar/interaction` - Calendar +- `@fullcalendar/list` - Calendar +- `@fullcalendar/react` - Calendar +- `@fullcalendar/timegrid` - Calendar +- `@fullcalendar/timeline` - Calendar +- `@react-pdf/renderer` - Render invoice +- `@reduxjs/toolkit` - Utilities for Redux +- `apexcharts` - Create charts +- `aws-amplify` - Handle Amplify authentication +- `draft-js` - Text editor core library +- `firebase` - Handle Firebase authentication +- `formik` - Handle form and input events +- `gray-matter` - Parse docs markdown files +- `i18next` - Internationalization framework +- `lodash` - Library for merge and debounce utilities +- `nprogress` - Display page loading progress bar +- `numeral` - Utility to format numbers +- `prop-types` - Add prop type schema for components +- `react-apexcharts` - Chart components built over apexcharts library +- `react-beautiful-dnd` - Enable drag and drop functionality for Kanban +- `react-draft-wysiwyg` - Editor components built over draft-js library +- `react-dropzone` - Drop zone functionality for FileDropzone component +- `react-hot-toast` - Display and manage notifications +- `react-i18next` - React wrapper over i18next library +- `react-markdown` - Parse markdown in html elements +- `react-modal-image` - Open an image in a modal with fullscreen options +- `simplebar` - Replace browser scrollbar with custom component +- `simplebar-react` - Simplebar React wrapper +- `react-quill` - Text editor alternative +- `react-redux` - React components for Redux +- `react-syntax-highlighter` - Highlight markdown code +- `redux-devtools-extension` - Display Redux State and Actions in devtools +- `redux-thunk` - Middleware to enable Redux async actions +- `redux` - State manager for Calendar, Chat, Kanban, and Mail apps +- `yup` - Validation library diff --git a/_docs/deployment.md b/_docs/deployment.md new file mode 100644 index 0000000..5dc3617 --- /dev/null +++ b/_docs/deployment.md @@ -0,0 +1,61 @@ +--- +title: Deployment +--- + +# Deployment + +## Node.js Server + +Next.js can be deployed to any hosting provider that supports Node.js. Make sure your `package.json` +has the `"build"` and `"start"` scripts: + +```json +{ + "scripts": { + "dev": "next", + "build": "next build", + "start": "next start" + } +} +``` + +`next build` builds the production application in the `.next` folder. After building, `next start` +starts a Node.js server that supports hybrid pages, serving both statically generated and +server-side rendered pages. + +## Static HTML Export + +`next export` allows you to export your app to static HTML, which can be run standalone without the +need of a Node.js server. + +The exported app supports almost every feature of Next.js, including dynamic routes, prefetching, +preloading and dynamic imports. + +`next export` works by prerendering all pages to HTML. For dynamic routes, your page can export a +`getStaticPaths` function to let the exporter know which HTML pages to generate for that route. + +By default, `next export` will generate an `out` directory, which can be served by any static +hosting service or CDN. + +The choice of your server software isn’t important either. Since the output of the export command +is completely platform-agnostic, there’s no need to explicitly use Node. + +### Vercel Deployment + +The easiest way to deploy Next.js to production is to use the `Vercel` platform from the creators of +Next.js. `Vercel` is a cloud platform for static sites, hybrid apps, and Serverless Functions. Read +more about it from [official docs](https://nextjs.org/docs/deployment) + +### Netlify Deployment + +Netlify lets you link a GitHub, GitLab, or Bitbucket repository to a site for continuous deployment. +Each time you push to your Git provider, Netlify runs a build with your tool of choice and deploys +the result to their CDN. Read more about it from +[official docs](https://docs.netlify.com/configure-builds/get-started) + +### Firebase Hosting + +Using the Firebase CLI, you deploy files from local directories on your computer to your Hosting +server. Beyond serving static content, you can use Cloud Functions for Firebase or Cloud Run to +serve dynamic content and host microservices on your sites. Read more about it +from [official docs](https://firebase.google.com/docs/hosting). diff --git a/_docs/environment-variables.md b/_docs/environment-variables.md new file mode 100644 index 0000000..088cf46 --- /dev/null +++ b/_docs/environment-variables.md @@ -0,0 +1,67 @@ +--- +title: Environment Variables +--- + +# Environment Variables + +By default, Next.js compiler looks for `.env` file in projects root folder and reads +its content. In the project files you'll find a file `.env.example` that contains all the +environment variables that were used in the app environment. **Not all are required.** + +## Loading Environment Variables + +Next.js has built-in support for loading environment variables from `.env` file into `process.env`. + +An example `.env`: + +```shell +DB_HOST=localhost +DB_USER=myuser +DB_PASS=mypassword +``` + +This loads `process.env.DB_HOST`, `process.env.DB_USER`, and `process.env.DB_PASS` into the Node.js +environment automatically allowing you to use them in Next.js data fetching methods and API routes. + +For example, using `getStaticProps`: + +```js +// pages/index.js +export async function getStaticProps() { + const db = await myDB.connect({ + host: process.env.DB_HOST, + username: process.env.DB_USER, + password: process.env.DB_PASS, + }); + // ... +} +``` + +## Exposing Environment Variables to the Browser + +By default environment variables are only available in the Node.js environment, meaning they won't +be exposed to the browser. + +In order to expose a variable to the browser you have to prefix the variable with `NEXT_PUBLIC_`. +For example: + +```shell +NEXT_PUBLIC_ANALYTICS_ID=abcdefghijk +``` + +> WARNING: Do not store any secrets (such as private API keys or passwords) in the public variables! +> These environment variables are embedded into the build, meaning anyone can view them by +> inspecting your app's files. + +## Private Variables + +Having access to the `NODE_ENV` is also useful for performing actions conditionally: + +```js +if (process.env.NODE_ENV !== 'production') { + analytics.disable(); +} +``` + +Read more about environment +variables [here](https://create-react-app.dev/docs/adding-custom-environment-variables). diff --git a/_docs/further-support.md b/_docs/further-support.md new file mode 100644 index 0000000..9819287 --- /dev/null +++ b/_docs/further-support.md @@ -0,0 +1,12 @@ +--- +title: Further Support +--- + +# Further Support + +This documentation covers only broad use cases and relies on you or your developers having existing +and pretty extensive previous knowledge of the libraries in use, as well as web technologies. Should +this not be your scenario, please keep in mind our team offers special training and exclusive for +pay support, and based on your project size and our availability, we can take custom requests at a +fee. For more details please get in contact with our team of experts on +[https://devias.io/contact](https://devias.io/contact). diff --git a/_docs/getting-started.md b/_docs/getting-started.md new file mode 100644 index 0000000..4470313 --- /dev/null +++ b/_docs/getting-started.md @@ -0,0 +1,67 @@ +--- +title: Getting Started +--- + +# Getting Started + +Before proceeding, you'll need to have the last stable [NodeJS](https://nodejs.org/en/) +and [npm](https://www.npmjs.com) +installed on your machine. + +You can use [nvm](https://github.com/creationix/nvm#installation) (macOS/Linux) or +[nvm-windows](https://github.com/coreybutler/nvm-windows#node-version-manager-nvm-for-windows) to +switch Node versions between different projects. + +## Install dependencies + +Open the project folder and install its dependencies. You can use any package manager you +want: [Yarn](https://yarnpkg.com) +or [npm](https://www.npmjs.com). There might be other package managers that were not listed here. + +```shell +cd project-folder +npm install +``` + +## Start development server + +Once the installation is done, you can now run your app by running `npm run dev` or `yarn dev`. + +```shell +npm run dev +``` + +You will see something similar to: + +```shell +ready - started server on 0.0.0.0:3000, url: http://localhost:3000 +info - automatically enabled Fast Refresh for 1 custom loader +event - compiled successfully in 4.7s (1535 modules) +``` + +This runs the app in development mode. Open [localhost:3000](http://localhost:3000) to view it in +the browser. + +While in development mode, the page will automatically reload if you make changes to the code. +Should you have any, you will see the build errors and lint warnings in the console. + +The app uses `ESLint`, so you will get detailed warnings and errors as well as best practice hints. + +## Build project files + +```shell +npm run build +``` + +or `yarn build` + +Builds the app for production to the build folder. It correctly bundles React in production mode and +optimizes the build for the best performance. + +The build is minified, and the filenames include hashes. + +If you have made your necessary changes, by this time, your app should ready to be deployed. + +> Please keep in mind that this project **_does not_** handle any backend logic nor databases; it is just a frontend you can use +> it with any backend you want. This means that you will have to build such a backend or use any existing one you might +> already have. diff --git a/_docs/guest-guard.md b/_docs/guest-guard.md new file mode 100644 index 0000000..ca4da66 --- /dev/null +++ b/_docs/guest-guard.md @@ -0,0 +1,41 @@ +--- +title: Guest Guard +--- + +# Guest Guard + +There are some situations when you want to make a route visible exclusively for users that are not +authenticated, such as +`/authentication/register`, `/authentication/login`, etc. + +For such situations, the app provides you with a sample `GuestGuard` component that can be used to +make redirect the user to a certain route (currently `/dashboard`). Should you want to modify said +route you can do so by modifying the `GuestGuard` component. There was no need to make a more complex +logic for this GuestGuard component, as the business logic needed for your specific app might +need a different approach regardless. + +To be able to prevent the entire page render, the app provides a simple `hoc` utility that wraps the +page with the GuestGuard. + +## Example + +```jsx +// src/pages/authentication/login.js +import { withGuestGuard } from '../../hocs/with-guest-guard'; + +const Login = () => { + return ( +
+ content +
+ ); +}; + +export default withGuestGuard(Login); +``` + +## How it works + +It connects with the authentication provider (Amplify, Auth0, Firebase, or JWT, depending on your +setup) and extracts the required data to detect whether it can render the children passed as props, +otherwise it redirects the user to the `/dashboard` route. diff --git a/_docs/internationalization.md b/_docs/internationalization.md new file mode 100644 index 0000000..a58048a --- /dev/null +++ b/_docs/internationalization.md @@ -0,0 +1,67 @@ +--- +title: Internationalization +--- + +# Internationalization + +Supporting multiple languages may represent an important feature for your app. To have this enabled +the app uses +`i18next` framework. Read more about it [here](https://www.i18next.com/). + +## How it works + +You might need to change all instances of inline text in any components to be wrapped with the `t()` +function as presented below. + +The library needs a configuration and initialization file, in this case, `src/i18n.js` file. + +First step is to declare the app translations as resources. + +```js +const resources = { + en: { + translation: { + 'Welcome to React': 'Welcome to React and react-i18next' + } + }, + fr: { + translation: { + 'Welcome to React': 'Bienvenue à React et react-i18next' + } + }, + es: { + translation: { + 'Welcome to React': 'Bienvenido a React and react-i18next' + } + }, + // ... +}; +``` + +These translations need to be passed in the `i18n.init()` function to make them available +inside `App` components tree using the `useTranslation` hook. + +```jsx +// src/pages/index.js +import { useTranslation } from 'react-i18next'; + +const Home = () => { + const { t } = useTranslation(); + + return ( +

+ {t('Welcome to React')} +

+ ); +} +``` + +For all configuration options, please follow the +[official documentation](https://www.i18next.com/overview/configuration-options). + +## Removing internationalization support + +1. Remove `import './i18n` line from `App` component. +2. Remove `i18n.js` configuration file from `src` folder. +3. Remove `LanguagePopover` component since it connects with the library. +3. Uninstall `i18next` and `react-i18next` dependencies. diff --git a/_docs/redux.md b/_docs/redux.md new file mode 100644 index 0000000..181a93a --- /dev/null +++ b/_docs/redux.md @@ -0,0 +1,206 @@ +--- +title: Redux +--- + +# Redux + +Redux is more robust alternative for state management, that offers more helpful features out of the +box. Follow the +[official documentation](https://redux.js.org/basics/usage-with-react) to understand the entire +concept behind it. + +## Usage + +The app uses `Redux Toolkit` with hooks (Thunk method, not Sagas) to manage the state +for `Calendar`, `Chat`, +`Kanban` and `Mail` apps. + +This can be replaced with `Context API`, or any other system, in a matter of hours due the clean +structure of the project. + +The app at hand uses Redux, but you can find Context API examples in the project. You can also opt +for +[Recoil](https://recoiljs.org/), maintained by **Facebook**, a new alternative that allows you to +split the state in multiple "atoms". An example is not included, but the ones from Facebook +documentation should be simple enough to use in your project. + +## How to use + +There are 2 main folders: + +1. `src/slices` where you can find the implementation of the reducer logic. +2. `src/store` which exports a store and combines the reducers in one root reducer. + +If you're new to Redux Toolkit, please read +their [official documentation](https://redux-toolkit.js.org/usage/usage-guide) +to understand the basics. + +## Example + +You can take as an example the blog feature of this app where; should you want to implement Redux; +you can do it as follows: + +### Create a new slice + +Create a new file in `src/slices`, and name it `blog.js`. Now open this new file with your favorite +IDE, and import +`createSlice` from `@reduxjs/toolkit` package to create the new slice. + +```js +import { createSlice } from '@reduxjs/toolkit'; + +const initialState = { + articles: [] +}; + +const slice = createSlice({ + name: 'blog', + initialState, + reducers: {} +}); + +export const { reducer } = slice; + +export default slice; +``` + +It is important to assign a name to the slice and an initial state. + +### Create a reducer action + +Let's get back to the newly created slice and add a `setArticles` action. + +```js +const slice = createSlice({ + name: 'blog', + initialState, + reducers: { + setArticles(state, payload) { + // You should get articles from the action payload. + // For simplicity's sake let's use static data instead. + + state.articles = [ + { + id: '1', + title: 'My first article' + } + ]; + } + } +}); +``` + +> Important: The state is a Proxy object, you cannot update it directly, and you have to update its keys instead. +> +> For example `state = { name: 'Alex' }` will break the state, but `state.user = { name: 'Alex' }` works as expected. + +### Create a thunk method + +This allows you to dispatch multiple actions, extremely useful for async requests. + +In the created slice file, create a `getPosts` method that dispatches the slice `setArticles` +action. + +```js +export const getPosts = () => async (dispatch) => { + // Here make an async request to your sever and extract the data from the server response + // const response = await axios.get('/__fake-api__/blog/articles'); + // const { data } = reponse; + + const data = [ + { + id: '1', + title: 'My first article' + } + ]; + + dispatch(slice.actions.setArticles(data)); +}; +``` + +Now, that you have a method that dispatches an action, you can update the `setArticles` action to +use the data from the payload. + +```js +const slice = createSlice({ + name: 'blog', + initialState, + reducers: { + setArticles(state, payload) { + state.articles = payload.articles; + } + } +}); +``` + +### Combine the new slice in the root reducer + +In the file `src/store/rootReducer.js` use the reducer from your newly created slice. + +```js +import {reducer as blogReducer} from 'src/slices/blog'; + +const rootReducer = combineReducers({ + // ...other reducers + blog: blogReducer +}); +``` + +### Using the slice state + +```jsx +import { useSelector } from 'react-redux'; + +const Blog = () => { + const { articles } = useSelector((state) => state.blog); + + return ( +
+
+ {articles.map((article) => ( +
+ Article ID: {article.id} +
+ ))} +
+
+ ); +}; +``` + +> Please refrain from changing the state directly (without an action) in order to avoid chained re-renders. + +### Dispatching an action + +This is the last step of the process. Execute the method `getPosts` to dispatch the slice action +and update the slice state. Once the action sets the new state, the app will re-render your current +component, and the articles will be displayed. + +```jsx +import { useDispatch, useSelector } from 'react-redux'; +import { getPosts } from 'src/slices/blog'; + +const Blog = () => { + const dispatch = useDispatch(); + const { articles } = useSelector((state) => state.blog); + + const handleClick = () => { + dispatch(getPosts()); + }; + + return ( +
+
+ {articles.map((article) => ( +
+ Article ID: {article.id} +
+ ))} +
+ +
+ ); +}; +``` diff --git a/_docs/role-based-guard.md b/_docs/role-based-guard.md new file mode 100644 index 0000000..70609e5 --- /dev/null +++ b/_docs/role-based-guard.md @@ -0,0 +1,58 @@ +--- +title: Role Based Guard +--- + +# Role Based Guard + +Many apps have complex user interfaces and flows. Some might have a list of routes for specific user +roles or rights, such as admin, editor, content manager, etc, or even display a completely different +interface for the same route. If that's the case for your project, you may want to check whether the +user is authenticated their Access Control List (ACL) +This depends a lot on your business, and your chosen ACL implementation / provider. + +Guarding is a concept that usually refers to route protection, but it can also be applied to +components, and instead of redirecting the user to another route, you can render a different +component. + +## How it can be implemented + +This guard is not created as there's no real way to know the actual business case, the needs, or the +strategy used in your specific app. Meanwhile, there are some standardized ACL strategies, there are +still too many of them and picking one is not fathomable in any way. + +As an effect you can find below a suggestion on how it _could_ be implemented, should you want it. + +In situations where various rights determine bits of the same UI, you may want to change the +redirection to either only display the functionality as disabled or simply not display it. The +conditional rendering scenario is a much easier one. + +```jsx +const RoleBasedGuard = (props) => { + const { children, permissions } = props; + const { user } = useAuth(); + + // Here check the user permissions + const canView = true; + + if (!canView) { + return null; + } + + return <>{children}; +}; + +const Overview = () => { + return ( +
+ +
+ +
+
+ +
+ ); +}; +``` diff --git a/_docs/routing.md b/_docs/routing.md new file mode 100644 index 0000000..36ca3ca --- /dev/null +++ b/_docs/routing.md @@ -0,0 +1,37 @@ +--- +title: Routing +--- + +# Routing + +Next.js has a file-system based router built on the concept of pages. + +When a file is added to the `pages` directory it's automatically available as a route. + +The files inside the `pages` directory can be used to define most common patterns. + +## Index routes + +The router will automatically route files named index to the root of the directory. + +- `pages/index.js` → `/` +- `pages/blog/index.js` → `/blog` + +## Nested routes + +The router supports nested files. If you create a nested folder structure files will be automatically routed in the same way still. + +- `pages/blog/first-post.js` → `/blog/first-post` +- `pages/dashboard/settings/username.js` → `/dashboard/settings/username` + +## Dynamic route segments + +Defining routes by using predefined paths is not always enough for complex applications. In Next.js +you can add brackets to a page ([param]) to create a dynamic route (a.k.a. url slugs, pretty urls, +and others). + +To match a dynamic segment you can use the bracket syntax. This allows you to match named parameters. + +- `pages/blog/[slug].js` → `/blog/:slug` (`/blog/hello-world`) +- `pages/[username]/settings.js` → `/:username/settings` (`/foo/settings`) +- `pages/post/[...all].js` → `/post/*` (`/post/2020/id/title`) diff --git a/_docs/rtl.md b/_docs/rtl.md new file mode 100644 index 0000000..3b8a1c8 --- /dev/null +++ b/_docs/rtl.md @@ -0,0 +1,38 @@ +--- +title: RTL +--- + +# RTL + +Text direction is extremely important for cultures where "right-to-left" writing is used. The app +has this functionality implemented. + +## How it works + +The wrapper component, `RTL`, is necessary to be above the app content in the tree. The component +changes the document direction, and appends a `stylis` plugin which converts all component styles to +mirror the margins and paddings. + +```jsx +// src/pages/_app.js +const App = (props) => { + const { Component, pageProps } = props; + + return ( + + + + ); +}; +``` + +`direction` prop can be `"ltr"` or `"rtl"`. When using `"ltr"` the component simply renders the +children, without affecting the styling. + +## Removing RTL support + +If you do not need to support RTL, you can remove it by following the next steps. + +1. Remove `RTL` component from `src/components`. +2. Remove `RTL` component import and usage from `App` component. +2. Uninstall the `@emotion/cache` and`stylis-plugin-rtl` dependencies. diff --git a/_docs/server-calls.md b/_docs/server-calls.md new file mode 100644 index 0000000..b0e911d --- /dev/null +++ b/_docs/server-calls.md @@ -0,0 +1,145 @@ +--- +title: Server Calls +--- + +# Server Calls + +The application simulates all server calls using in memory data storage. This can be easily modified +to connect to any server. + +You can use any library you like. Most apps use [Axios](https://github.com/axios/axios) since it +allows you to create instances, attach interceptors, and many other features. Another good +alternative could be [Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API). + +## Example of current implementation + +```jsx +class CustomerApi { + getCustomers() { + return Promise.resolve([ + { + id: '238339KDC', + name: 'John' + } + ]); + } +}; + +const customerApi = new CustomerApi(); + +const Customers = () => { + const [customers, setCustomers] = useState(null); + + useEffect(() => { + const getCustomers = async () => { + const result = await customerApi.getCustomers(); + setCustomers(result); + }; + + getCustomers(); + }, []); + + return ( +
+ {/* render content */} +
+ ); +}; +``` + +The `customerApi` is a singleton class instance that simply responds with a Promise. You can add as +many requests methods as you need, test request structure or even use as middleware between UI and +server request to process your input and output data. + +## Example with Fetch + +```jsx +const Customers = () => { + const [customers, setCustomers] = useState(null); + + useEffect(() => { + const getCustomers = async () => { + const response = await fetch('/api/customers'); + const data = await response.json(); + setCustomers(data); + }; + + getCustomers(); + }, []); + + return ( +
+ {/* render content */} +
+ ); +}; +``` + +## Example with Axios + +```jsx +import axios from 'axios'; // You need to install it + +const Customers = () => { + const [customers, setCustomers] = useState(null); + + useEffect(() => { + const getCustomers = async () => { + const response = await axios.get('/api/customers'); + setCustomers(response.data); + }; + + getCustomers(); + }, []); + + return ( +
+ {/* render content */} +
+ ); +}; +``` + +## Axios Request interceptors + +By using Axios you are able to +integrate [Axios Mock Adapter](https://github.com/ctimmerm/axios-mock-adapter) to simulate real +server calls. To archive that, you have to create an Axios instance and use it whenever you make a +request call. Now you can extend your instance and add Axios Mock Adapter to listen for requests and +return custom data. + +## Adding request interceptors + +It takes ony a few seconds to add a new http request listener. The interceptor has a similar format +to Express JS, for example: + +```js +import axios from 'axios'; // You need to install it +import AxiosMockAdapter from 'axios-mock-adapter'; // You need to install it + +export const axiosInstance = axios.create(); + +axiosInstance.interceptors.response.use( + (response) => response, + (error) => Promise.reject((error.response && error.response.data) || 'Something went wrong') +); + +const mock = new AxiosMockAdapter(axiosInstance, {delayResponse: 0}); + +mock.onGet('/__fake-api__/invoices').reply(200, { + invoices: [ + {id: 1, total: 32.43}, + {id: 2, total: 67.00} + ] +}); +``` + +Now instead of importing axios from `axios` node module, import the exported `axiosInstance` to get +the customers' data. + +## Removing existing request interceptors + +There are two ways: + +1. Simply use a new axios instance. +2. Remove the mocked listeners. diff --git a/_docs/settings.md b/_docs/settings.md new file mode 100644 index 0000000..234d630 --- /dev/null +++ b/_docs/settings.md @@ -0,0 +1,108 @@ +--- +title: Settings +--- + +# Settings + +It is important for your customers to have some control over the app interface. To make that +possible you need a way to let the app know which are the user preferences. In order to achieve it, +the app uses a context that can make its data available in the entire component tree for usage and +control. + +Currently, the app allows you to control the `theme`, and you can choose between available options, +toggle `RTL` +(right-to-left text direction). This is a simple implementation to give you an idea +on how can the configurations be made. It might be in your best interest to adjust it to your +business needs. You might want to have a specific app interface, and allow other setup options, or +remove some of the existing ones. + +## How it works + +```jsx +// src/pages/_app.js +import { SettingsProvider } from '../contexts/settings-context'; + +const App = (props) => { + const { Component, pageProps } = props; + + return ( + + + + ); +}; +``` + +The content of the `App` component is wrapped with the `SettingsProvider`, and by doing this its +context data is made available inside the component tree. + +## How to use + +There are two methods, using the hook or the context consumer. + +```jsx +// src/pages/index.js +import { useSettings } from '../hooks/useSettings'; + +const Home = () => { + const { settings } = useSettings(); + + return ( +
+ Current theme: {settings.theme} +
+ ); +}; +``` + +```jsx +// src/pages/index.js +import { SettingsConsumer } from '../contexts/settings-context'; + +const Home = () => { + return ( + + {({settings}) => ( +
+ Current theme: {settings.theme} +
+ )} +
+ ); +}; +``` + +## Triggering the settings update + +It can be implemented in any component within seconds. + +```jsx +// src/pages/index.js +import { useSettings } from '../hooks/useSettings'; + +const Home = () => { + const { settings, saveSettings } = useSettings(); + + const handleSave = () => { + saveSettings({ + ...settings, + theme: 'dark' + }); + }; + + return ( +
+ +
+ ); +}; +``` + +## Store / restore user preferences + +The SettingsContext on mount event, it extracts stored settings from `localStorage` (if available); +if not, a default value is provided. This can be extended and, instead of using the localStorage, +you can use a server. This gives the user the possibility to have the same settings across multiple +devices. diff --git a/_docs/theming.md b/_docs/theming.md new file mode 100644 index 0000000..516fa5c --- /dev/null +++ b/_docs/theming.md @@ -0,0 +1,77 @@ +--- +title: Theming +--- + +# Theming + +MUI offers a utility function: `createTheme()` that creates a theme which can be passed to +the theme provider; otherwise the theme provider uses the default theme. The theme provider makes +the theme available in the component tree, and can be used via the `sx` prop, or inside styled +components using the MUI styled engine (`styled`). + +## Creating a theme + +The app allows you to choose between multiple theme setups, thus a wrapper was created over +the `createTheme`. Currently, the function accepts a configuration object with the following keys: + +- `direction` [ 'ltr' | 'rtl' ] - Sets the text direction. If you need RTL support, please ensure + you use `RTL` component. +- `responsiveFontSizes` [ boolean ] - Adaptive font size for small devices. +- `mode` [ 'light' | 'dark' ] - Select a specific theme configuration. You can add your own styling + or adjust current options. + +```js +// src/pages/index.js +import { ThemeProvider } from '@mui/material/styles'; +import { createTheme } from '../theme'; + +const Home = () => { + const theme = createTheme({ + direction: 'ltr', + responsiveFontSizes: true, + mode: 'dark' + }); + + return ( + +
+ content +
+
+ ); +} +``` + +## Nested themes + +Multiple themes can be nested. The app implements this behaviour to display the components on +light/dark palette mode without changing the app global theme. + +```jsx +// src/pages/index.js +import { ThemeProvider } from '@mui/material/styles'; +import { createTheme } from '../theme'; + +const Home = () => { + const theme = createTheme({ + direction: 'ltr', + responsiveFontSizes: true, + mode: 'dark' + }); + + const theme2 = createTheme({ + mode: 'light' + }); + + return ( + +
+
Main theme
+ +
Inner theme
+
+
+
+ ); +} +``` diff --git a/_docs/welcome.md b/_docs/welcome.md new file mode 100644 index 0000000..c86ae32 --- /dev/null +++ b/_docs/welcome.md @@ -0,0 +1,19 @@ +--- +title: Welcome +--- + +# About the documentation + +Welcome to the documentation for Devias Material Kit Pro! This documentation will take you +from [getting started](getting-started) +with our kit to customizing it and making it work for your use case. + +## Something Missing? + +If you have ideas for more "How To" recipes that should be on this page, please, let us know or +contribute some! + +## Feedback + +We are always happy for you to send your feedback +at [support@deviasio.zendesk.com](mailto:support@deviasio.zendesk.com). diff --git a/next.config.js b/next.config.js new file mode 100644 index 0000000..c574ff1 --- /dev/null +++ b/next.config.js @@ -0,0 +1,27 @@ +/** @type {import('next').NextConfig} */ +const config = { + swcMinify: true, + reactStrictMode: false, + webpack(config) { + config.module.rules.push({ + test: /\.svg$/, + use: ['@svgr/webpack'] + }); + return config; + }, + async redirects() { + return [ + { + source: '/authentication', + destination: '/docs/welcome', + permanent: true + } + ]; + } +}; + +// Remove this if you're not using Fullcalendar features +const withTM = require('next-transpile-modules')([ +]); + +module.exports = withTM(config); diff --git a/out/401.html b/out/401.html new file mode 100644 index 0000000..145e0c6 --- /dev/null +++ b/out/401.html @@ -0,0 +1 @@ +Material Kit Pro
\ No newline at end of file diff --git a/out/404.html b/out/404.html new file mode 100644 index 0000000..eab5390 --- /dev/null +++ b/out/404.html @@ -0,0 +1 @@ +Material Kit Pro
\ No newline at end of file diff --git a/out/500.html b/out/500.html new file mode 100644 index 0000000..71f69a2 --- /dev/null +++ b/out/500.html @@ -0,0 +1 @@ +Material Kit Pro
\ No newline at end of file diff --git a/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/analytics-configuration.json b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/analytics-configuration.json new file mode 100644 index 0000000..01987c9 --- /dev/null +++ b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/analytics-configuration.json @@ -0,0 +1 @@ +{"pageProps":{"article":{"content":"\n# Configuration\n\n## Create GTM account\n\nIn order to use the GTM platform, you need to create a GTM account. Read more about it\n[here](https://support.google.com/tagmanager/answer/6103696?hl=en#install&zippy=%2Cweb-pages).\n\n## Set up configuration options\n\nThe app uses environment variables because it can be deployed with different accounts\nfor `development`, `qa`, and `production`. This allows you to configure the GTM library differently\nfor each environment.\n\nOpen `.env` file (or create) in the project's root folder and set the\nvariable `NEXT_PUBLIC_GTM_CONTAINER_ID` with the container ID provided by GTM platform.\n\n```shell\nNEXT_PUBLIC_GTM_CONTAINER_ID=GTM-XXXXXX\n```\n\nIf you do not want to set up environment variables, settings can be applied simply on\nthe `gtmConfig` object found in the `src/config.js` file.\n\n```js\nexport const gtmConfig = {\n containerId: ''\n};\n```\n","slug":"analytics-configuration","title":"Analytics Configuration"}},"__N_SSG":true} \ No newline at end of file diff --git a/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/analytics-event-tracking.json b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/analytics-event-tracking.json new file mode 100644 index 0000000..621f878 --- /dev/null +++ b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/analytics-event-tracking.json @@ -0,0 +1 @@ +{"pageProps":{"article":{"content":"\n# Event tracking\n\nBy default, the GTM library's push platform captures the browser location data, such as url,\npathname, title, and other details. You can extend it to match your business needs. For example, you\nmay need the event name, site section, campaign name, product name, price, process step, etc.\n\n## Page view\n\n```jsx\n// src/pages/login.js\nimport { useEffect } from 'react';\nimport { gtm } from '../lib/gtm';\n\nconst Login = () => {\n useEffect(() => {\n gtm.push({event: 'page_view'});\n }, []);\n\n return (\n
\n content\n
\n );\n};\n```\n\nThis example shows you how to track the page view event once the page component gets mounted. It can\nalso be used on mounting virtual pages, such as modals, dialogs, etc.\n\n## Other action\n\n```jsx\n// src/pages/product.js\nimport { gtm } from '../lib/gtm';\n\nconst Product = () => {\n const handleAddToCart = () => {\n gtm.push({\n event: 'add_to_cart',\n price: '317,65',\n currency: 'EUR',\n name: 'Dell Monitor 27\"'\n });\n };\n\n return (\n
\n
Dell Monitor 27\"
\n
EUR 317,65
\n \n
\n );\n};\n```\n\nAs it can be seen, this example has multiple variables to help you identify the product that was\nadded to cart and its price. These are called conversion variables in most systems, and they are\nused to determine the user behaviour after visiting a specific page or site section. If the user\ndoes not complete the checkout process, you are able to identify most products added to the cart,\nand make decisions based on metrics.\n","slug":"analytics-event-tracking","title":"Event tracking"}},"__N_SSG":true} \ No newline at end of file diff --git a/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/analytics-introduction.json b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/analytics-introduction.json new file mode 100644 index 0000000..9251e48 --- /dev/null +++ b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/analytics-introduction.json @@ -0,0 +1 @@ +{"pageProps":{"article":{"content":"\n# Introduction\n\nFor many companies is important to understand the user traffic, origin and behaviour. This may apply\nto your business, and you can find an example in the app.\n\n## Google Tag Manager (GTM)\n\nIn previous versions the app used `Google Analytics` directly, but for this version it uses GTM.\nThis enables a lot more control over the analytics implementation and also helps you display things\nlike GDPR modal, various targeted content; control the data transfer, cookies and other aspects\nbased on user data privacy preferences. Read more about GTM\n[here](https://support.google.com/tagmanager/answer/6102821?hl=en&ref_topic=3441530).\n\n## How GTM it works\n\nIn order to use the `GTM platform` you set up a container, then you create a tag for each provider\nyou need, for example, Google Analytics. Then, using the triggers, you control multiple tags based\non data pushed to the data layer. The data pushed gets computed on the client (browser), and then\nthe library determines which tags will be loaded.\n\n## How is it implemented\n\nThe app uses a small singleton class to help with loading the `GTM library`, initialize it and track\nevents via the GTM available methods.\n","slug":"analytics-introduction","title":"Analytics Introduction"}},"__N_SSG":true} \ No newline at end of file diff --git a/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/auth-guard.json b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/auth-guard.json new file mode 100644 index 0000000..2d14074 --- /dev/null +++ b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/auth-guard.json @@ -0,0 +1 @@ +{"pageProps":{"article":{"content":"\n# Auth Guard\n\nThis is a simple component that can be used to protect a private route. It controls whether it\nshould allow navigation to a requested route based on given context. Similar to the GuestGuard,\nthe app provides a `hoc` to prevent the entire page render.\n\n## Example\n\n```jsx\n// src/pages/dashboard/index.js\nimport { withAuthGuard } from '../../hocs/with-auth-guard';\n\nconst Overview = () => {\n return (\n
\n content\n
\n );\n};\n\nexport default withAuthGuard(Overview);\n```\n\n## How it works\n\nIt connects with the authentication provider (Amplify, Auth0, Firebase, or JWT, depending on your\nsetup) and extracts the required data to detect whether it should render the children passed as\nprops, otherwise it redirects to the `Login` component with a redirect url query string parameter\nto allow the Login component to redirect back to the requested url after a successful \nauthentication.\n\n## How it can be extended\n\nAs mentioned, this is a sample component, thus it can and should be adjusted to match your business\nneeds.\n","slug":"auth-guard","title":"Auth Guard"}},"__N_SSG":true} \ No newline at end of file diff --git a/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/authentication-amplify.json b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/authentication-amplify.json new file mode 100644 index 0000000..aa6d98e --- /dev/null +++ b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/authentication-amplify.json @@ -0,0 +1 @@ +{"pageProps":{"article":{"content":"\n# Amplify\n\nAWS Amplify is a set of services accompanied by various tools and libraries created to help the\ndevelopment of apps. Their suite offers among other features, an authentication feature, which can\nbe used as a stand-alone authentication system. The project is able to be used with this\nauthentication system, as well. Should you want to implement any of the other features Amplify\noffers, you can refer to their [documentation](https://docs.amplify.aws/).\n\n## Set up your Amplify account\n\nThe documentation for this, can be found in the official documentation of the service, mentioned\nabove.\n\n## Configuration\n\nIn order to configure Amplify client library you have to open (or create) `.env` file in the\nproject's root folder and set the following variables as presented in your Amplify account settings:\n\n```shell\nNEXT_PUBLIC_AWS_COGNITO_IDENTITY_POOL_ID=\nNEXT_PUBLIC_AWS_COGNITO_REGION=\nNEXT_PUBLIC_AWS_PROJECT_REGION=\nNEXT_PUBLIC_AWS_USER_POOLS_ID=\nNEXT_PUBLIC_AWS_USER_POOLS_WEB_CLIENT_ID=\n```\n\nIf you do not want to set up environment variables, settings can be applied simply on\nthe `amplifyConfig` object found in the `src/config.js` file.\n\n```js\nexport const amplifyConfig = {\n aws_project_region: '',\n aws_cognito_identity_pool_id: '',\n aws_cognito_region: '',\n aws_user_pools_id: '',\n aws_user_pools_web_client_id: ''\n};\n```\n\n## How it was implemented\n\nAs mentioned above, Amplify offers a set of components to help your development process, although\nthey're not used in the app.\n\nThe `Auth` singleton from the library is used to provide the authentication feature to a context (\nwhich wraps the content of the `App` component).\n\nThis aforementioned context is then used in the component tree to access the `Auth` public methods.\nIt provides the user authentication status and user profile, if available.\n\n## How to use Amplify Provider\n\nBy default, the project uses a mocked `JWT provider` (as in: it doesn't use an actual JWT based\nauthentication server). To make use of Amplify simply follow these steps:\n\n### Step 1. Replace the provider and consumer\n\nOpen `src/pages/_app.js` file and replace the following line:\n\n```js\nimport { AuthConsumer, AuthProvider } from '../contexts/jwt-context';\n```\n\nwith\n\n```js\nimport { AuthConsumer, AuthProvider } from '../contexts/amplify-context';\n```\n\n### Step 2. Replace the hook context\n\nOpen `src/hooks/use-auth.js` file and replace the following line:\n\n```js\nimport { AuthContext } from '../contexts/jwt-context';\n```\n\nwith\n\n```js\nimport { AuthContext } from '../contexts/amplify-context';\n```\n\n## How to use auth\n\n### Retrieve user profile\n\nIn the example below, you can find how it can be used in any component not just the `App`. Should\nyou want to use it in any other component, you'll have to import the `useAuth` hook and use it as\nneeded.\n\n```jsx\n// src/pages/index.js\nimport { useAuth } from '../hooks/use-auth';\n\nconst Home = () => {\n const { user } = useAuth();\n\n return (\n
\n Email: {user.email}\n
\n );\n};\n```\n\n### Auth methods / actions\n\n> For simplicity and space limitations, the code below is used only to exemplify, actual code can be found in the components.\n\n```jsx\n// src/pages/index.js\nimport { useAuth } from '../hooks/use-auth';\n\nconst Home = () => {\n const { login } = useAuth();\n \n const handleLogin = () => {\n // Email/username and password\n login('demo@melsoft.co.za', 'Password123!');\n };\n\n return (\n
\n \n
\n );\n};\n```\n\n## Implemented flows\n\nCurrently, the app only covers the main flows:\n\n- Sign in\n- Sign up\n- Confirm sign up\n- Resend sign up\n- Forgot password\n- Forgot password submit\n- Logout\n","slug":"authentication-amplify","title":"Amplify"}},"__N_SSG":true} \ No newline at end of file diff --git a/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/authentication-auth0.json b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/authentication-auth0.json new file mode 100644 index 0000000..e1538e9 --- /dev/null +++ b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/authentication-auth0.json @@ -0,0 +1 @@ +{"pageProps":{"article":{"content":"\n# Auth0\n\nAuth0 is an easy to implement, adaptable authentication and authorization platform. Auth0 provides a\nlibrary built for React, but the app uses a more generic library designed for universal SPAs. This\ngives you more control over the components, as the app needs to provide support for multiple\nauthentication providers. You can refer to their [documentation](https://auth0.com/docs/)\nas you deem fit, or in case you need things not covered in the app.\n\n## Set up your Auth0 account\n\nThe documentation for this, can be found in the official documentation of the service, mentioned\nabove.\n\n## Configuration\n\nTo configure Auth0 client library you have to open (or create) `.env` file in the project's root\nfolder and set the following variables as presented in your Auth0 account settings:\n\n```shell\nNEXT_PUBLIC_AUTH0_CLIENT_ID=\nNEXT_PUBLIC_AUTH0_DOMAIN=\n```\n\nIf you do not want to set up environment variables you can simply set the `auth0Config` object\nfrom `src/config.js` file.\n\n```js\nexport const auth0Config = {\n client_id: '',\n domain: ''\n};\n```\n\n## How it was implemented\n\nAs mentioned, Auth0 offers a set of components to help your development process, although they're\nnot used in the app.\n\nThe `Auth0Client` class from the library is used to provide the authentication feature to a\ncontext (which wraps the content of the `App` component).\n\nThis aforementioned context is then used in the component tree to access the `Auth0Client` instance\npublic methods. It provides the user authentication status and user profile, if available.\n\n## How to use Auth0 Provider\n\nBy default, the project uses a mocked `JWT provider` (as in: it doesn't use an actual JWT based\nauthentication server). To make use of Amplify simply follow these steps:\n\n### Step 1. Replace the provider\n\nOpen `src/pages/_app.js` file and replace the following line:\n\n```js\nimport { AuthConsumer, AuthProvider } from '../contexts/jwt-context';\n```\n\nwith\n\n```js\nimport { AuthConsumer, AuthProvider } from '../contexts/auth0-context';\n```\n\n### Step 2. Replace the hook context\n\nOpen `src/hooks/use-auth.js` file and replace the following line:\n\n```js\nimport { AuthContext } from '../contexts/jwt-context';\n```\n\nwith\n\n```js\nimport { AuthContext } from '../contexts/auth0-context';\n```\n\n## How to use auth\n\n### Retrieve user profile\n\nIn the example below, you can find how it can be used in any component not just the `App`. Should\nyou want to use it in any other component, you'll have to import the `useAuth` hook and use it as\nneeded.\n\n```jsx\n// src/pages/index.js\nimport { useAuth } from '../hooks/use-auth';\n\nconst Home = () => {\n const { user } = useAuth();\n\n return (\n
\n Email: {user.email}\n
\n );\n};\n```\n\n### Auth methods / actions\n\n> For simplicity and space limitations, the code below is used only to exemplify, actual code can be found in the components.\n\n```jsx\n// src/pages/index.js\nimport { useAuth } from '../hooks/use-auth';\n\nconst Home = () => {\n const { loginWithPopup } = useAuth();\n \n const handleLogin = () => {\n loginWithPopup();\n };\n\n return (\n
\n \n
\n );\n};\n```\n\n## Implemented flows\n\nCurrently, the app only covers the main flows:\n\n- Login with popup (also used to register)\n- Logout\n","slug":"authentication-auth0","title":"Auth0"}},"__N_SSG":true} \ No newline at end of file diff --git a/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/authentication-firebase.json b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/authentication-firebase.json new file mode 100644 index 0000000..09bb52d --- /dev/null +++ b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/authentication-firebase.json @@ -0,0 +1 @@ +{"pageProps":{"article":{"content":"\n# Firebase\n\nFirebase is a complete set of solutions, from Analytics to Cloud Functions. In the app at hand, only\nthe authentication service is used, although you can decide to use more of their features. Please\nrefer to their [documentation](https://firebase.google.com/docs)\nas you deem necessary.\n\n## Set up your Firebase account\n\nThe documentation for this, can be found in the official documentation of the service, mentioned\nabove.\n\n## Configuration\n\nTo configure Firebase client library you have to open (or create) `.env` file in the project's root\nfolder and set the following variables as presented in your Firebase account settings:\n\n```shell\nNEXT_PUBLIC_FIREBASE_API_KEY=\nNEXT_PUBLIC_FIREBASE_APP_ID=\nNEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=\nNEXT_PUBLIC_FIREBASE_DATABASE_URL=\nNEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=\nNEXT_PUBLIC_FIREBASE_PROJECT_ID=\nNEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=\n```\n\nIf you do not want to set up environment variables, settings can be applied simply on\nthe `firebaseConfig` object found in the `src/config.js` file.\n\n```js\nexport const firebaseConfig = {\n apiKey: '',\n appId: '',\n authDomain: '',\n messagingSenderId: '',\n projectId: '',\n storageBucket: ''\n};\n```\n\n## How it was implemented\n\nAs mentioned above, Firebase offers a set of components to help your development process, although\nthey're not used in the app.\n\nThe `firebase.auth` factory from the library is used to create and provide the authentication\nfeature to a context (which wraps the content of the `App` component).\n\nThis aforementioned context is then used in the component tree to access the `Auth` public methods.\nIt provides the user authentication status and user profile, if available.\n\n## How to use Firebase Auth Provider\n\nBy default, the project uses a mocked `JWT provider` (as in: it doesn't use an actual JWT based\nauthentication server). To make use of Amplify simply follow these steps:\n\n### Step 1. Replace the provider\n\nOpen `src/pages/_app.js` file and replace the following line:\n\n```js\nimport { AuthConsumer, AuthProvider } from '../contexts/jwt-context';\n```\n\nwith\n\n```js\nimport { AuthConsumer, AuthProvider } from '../contexts/firebase-auth-context';\n```\n\n### Step 2. Replace the hook context\n\nOpen `src/hooks/use-auth.js` file and replace the following line:\n\n```js\nimport { AuthContext } from '../contexts/jwt-context';\n```\n\nwith\n\n```js\nimport { AuthContext } from '../contexts/firebase-auth-context';\n```\n\n## How to use auth\n\n### Retrieve user profile\n\nIn the example below, you can find how it can be used in any component not just the `App`. Should\nyou want to use it in any other component, you'll have to import the `useAuth` hook and use it as\nneeded.\n\n```jsx\n// src/pages/index.js\nimport { useAuth } from '../hooks/use-auth';\n\nconst Home = () => {\n const { user } = useAuth();\n\n return (\n
\n Email: {user.email}\n
\n );\n};\n```\n\n### Auth methods / actions\n\n> For simplicity and space limitations, the code below is used only to exemplify, actual code can be found in the components.\n\n```jsx\n// src/pages/index.js\nimport { useAuth } from '../hooks/use-auth';\n\nconst Home = () => {\n const { signInWithEmailAndPassword } = useAuth();\n \n const handleLogin = () => {\n // Email and password\n signInWithEmailAndPassword('demo@devias.io', 'Password123!');\n };\n\n return (\n
\n \n
\n );\n};\n```\n\n## Implemented flows\n\nCurrently, the app only covers the main flows:\n\n- Create user with email and password\n- Sign in with email and password\n- Sign in with popup (Google)\n- Logout\n","slug":"authentication-firebase","title":"Firebase"}},"__N_SSG":true} \ No newline at end of file diff --git a/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/authentication-jwt.json b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/authentication-jwt.json new file mode 100644 index 0000000..1de980d --- /dev/null +++ b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/authentication-jwt.json @@ -0,0 +1 @@ +{"pageProps":{"article":{"content":"\n# JSON Web Token (JWT)\n\nMost auth providers use this strategy under the hood to provide access tokens. Currently, the app\ndoesn't cover the backend service, and this service is mocked (faked) using http client\ninterceptors. The implementation is basic, but enough to give you a starting point.\n\n## How it was implemented\n\nSince tokens are meant to be created on the backend server, they are built with encrypt, encode and\ndecode utility methods because they are not meant to be used on the client. These utilities can be\nfound in `src/utils/jwt`. These are for development purposes only, and you must remove (or avoid\nusing) them.\n\n## How to use JWT Provider\n\nThe app is delivered with JWT Provider as default auth strategy. If you changed or removed it, and\nyou want it back, simply follow these steps:\n\n### Step 1. Import the provider\n\nOpen `src/pages/_app.js` file, import the provider and wrap the App component with it.\n\n```js\n// src/pages/_app.js\nimport { AuthConsumer, AuthProvider } from '../contexts/jwt-context';\n\nconst App = (props) => {\n const { Component, pageProps } = props;\n \n return (\n \n \n \n );\n};\n```\n\n### Step 2. Set the hook context\n\nOpen `src/hooks/use-auth.js` file and replace the current context the following line:\n\n```js\nimport { AuthContext } from '../contexts/jwt-context';\n```\n\n## How to use auth\n\n### Retrieve user profile\n\nIn the example below, you can find how it can be used in any component not just the `App`. Should\nyou want to use it in any other component, you'll have to import the `useAuth` hook and use it as\nneeded.\n\n```jsx\n// src/pages/index.js\nimport { useAuth } from '../hooks/use-auth';\n\nconst Home = () => {\n const { user } = useAuth();\n\n return (\n
\n Email: {user.email}\n
\n );\n};\n```\n\n### Auth methods / actions\n\n> For simplicity and space limitations, the code below is used only to exemplify, actual code can be found in the components.\n\n```jsx\n// src/pages/index.js\nimport { useAuth } from '../hooks/use-auth';\n\nconst Home = () => {\n const { login } = useAuth();\n \n const handleLogin = () => {\n // Email/username and password\n login('demo@melsoft.co.za', 'Password123!');\n };\n\n return (\n
\n \n
\n );\n};\n```\n\n## Implemented flows\n\nCurrently, the app only covers the main flows:\n\n- Register\n- Login\n- Logout\n","slug":"authentication-jwt","title":"JWT"}},"__N_SSG":true} \ No newline at end of file diff --git a/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/changelog.json b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/changelog.json new file mode 100644 index 0000000..61169b2 --- /dev/null +++ b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/changelog.json @@ -0,0 +1 @@ +{"pageProps":{"article":{"content":"\n## v5.3.0\n\n###### Sep 15, 2022\n\n- Update dependencies\n\n## v5.2.0\n\n###### May 23, 2022\n\n- Update dependencies\n\n## v5.1.0\n\n###### Feb 9, 2022\n\n- Activate Typescript Strict mode\n- Update Firebase to v9\n- Replace Auth0 Popup with Redirect\n- Fix dependencies security issues\n- Update types and interfaces\n- Update dependencies\n- Update Sketch files to v5\n\n## v5.0.2\n\n###### Nov 4, 2021\n\n- Reduce compile time\n- Update layout strategy\n\n## v5.0.1\n\n###### Nov 3, 2021\n\n- Fix auth guard redirect bug\n\n## v5.0.0\n\n###### Nov 2, 2021\n\n- Migrate `CRA` to `Next.js 12`\n- Migrate code to MUI v5\n- Add `Company Details` pages\n- Add `Job Create` flow\n- Add `Job Listing` page\n- Add `Logistics Dashboard` page\n- Cleanup code\n- Remove `react-modal-image` dependency\n- Update `Account` pages\n- Update `Blog Platfrom` page designs\n- Update `Calendar` app layout\n- Update `Chat` app layout\n- Update `Chat` logic\n- Update `Customer Details` page\n- Update `Customer List` filters\n- Update `Invoice List` filters\n- Update `Invoice List` page layout\n- Update `Kaban` app\n- Update `Landing` page\n- Update `Mail` app layout\n- Update `Order List` filters\n- Update `Order List` page layout\n- Update `Product List` filters\n- Update `Product List` table\n- Update design system\n\n---\n\n## v4.1.0\n\n###### May 24, 2021\n\n- Add Sketch and Figma dark versions\n- Add `react-hot-toast` dependency\n- Fix Calendar App `Date` data type stored in Redux state warning\n- Fix Kanban App card move bug\n- Fix RTL bug\n- Fix `nprogress` display bug\n- Implement mocked api clients instead of mocked axios interceptors\n- Remove `axios` and `axios-mock-adapter` dependencies\n- Remove `notistack` dependency\n- Remove `web-vitals` dependency\n- Replace `Hidden` component with `sx` logic\n- Update `material-ui` and other dependencies\n\n---\n\n## v4.0.0\n\n###### Mar 17, 2021\n\n- Add `@emotion/react` and `@emotion/styled` dependencies\n- Add `AWS Amplify` auth platform\n- Add `Google Tag Manager` to implement tags concept\n- Add `StrictMode`\n- Add `date-fns` dependency to parse dates\n- Add `gray-matter` dependency\n- Add `react-i18next` dependency to implement multi-language\n- Add `stylis` and `stylis-plugin-rtl` dependencies\n- Add `web-vitals` dependency\n- Add new components\n- Add new pages\n- Drop `IE11` support\n- Fix some TS types\n- Implement `sx` prop where needed\n- Regroup pages\n- Remove `Google Analytics`\n- Remove `js-cookie` dependency\n- Remove `jsonwebtoken` dependency\n- Remove `jwt-decode` dependency\n- Remove `lodash` dependency\n- Remove `mdx` dependency\n- Remove `moment` dependency\n- Remove `react-chartjs-2` dependency\n- Remove `uuid` dependency\n- Rename components for simpler folder structure\n- Replace `moment` with `date-fns`\n- Replace `react-chartjs-2` with `react-apexcharts`\n- Replace `react-helmet` with `react-helmet-async` dependency\n- Replace `useStyles` with `experimentalStyled` strategy\n- Update `@fullcalendar` dependency\n- Update `@material-ui/core` and `@material-ui/icons` dependencies\n- Update `react-router` to v6\n- Update existing components to match Material-UI v5\n- Update theme to use Material-UI v5 theme format\n\n## v3.1.0\n\n###### Aug 1, 2020\n\n### JavaScript\n\n`JavaScript` version is now in sync with the `TypeScript` version, both with the same features.\n\n### TypeScript\n\nNo changes.\n\n---\n\n## v3.0.0\n\n###### July 26, 2020\n\nThe release introduces a new version of the product written in `TypeScript`.\n\n### JavaScript\n\nNo changes.\n\n### TypeScript\n\n- Fix server-side rendering issue with SettingsProvider\n- Implement `Auth0` and `Firebase Authentication`\n- Improve components\n- Reimplement `JWT Auth` using `Redux Context API`\n- Reimplement Redux using `Redux Toolkit`\n- Remove a few components `Social` platform to be able to add new ones in future updates\n- Update `Login` and `Register` pages\n- Update `Calendar` and `Chat` apps\n- Update dependencies\n- Update mocked chart to match the types\n- Update `Projects` platform\n\n---\n\n## v2.0.0\n\n###### Apr 10, 2020\n\n- Add `apexcharts` dependency\n- Add `formik` dependency\n- Add `immer` dependency\n- Add `joy` dependency\n- Add `mdx` dependency\n- Add `notistack` dependency\n- Add `react-modal-image` dependency\n- Add new pages\n- Implement Redux in `Chat`, `Kanban`, `Mail` apps\n- Implement `AuthService` and `AuthGuard`\n- Implement app settings manager\n- Implement multiple themes\n- Refactor components to accept multi-theme\n- Remove multiple css classes and replaced the styling with `Box` component\n- Update all pages implementing new Material-UI features\n- Update docs to use `mdx`\n- Update the mock adapter, now accepting post requests\n- Update typography\n\n---\n\n## v1.4.0\n\n###### Feb 25, 2020\n\n- Fix `uuid` import bug\n- Update dependencies\n\n---\n\n## v1.3.0\n\n###### Sep 7, 2019\n\n- Add component pages\n- Add `eslint-config-airbnb` dependency\n- Add `eslint-config-prettier` dependency\n- Add `eslint-plugin-import` dependency\n- Add `eslint-plugin-jsx-a11y` dependency\n- Add `eslint-plugin-react-hooks` dependency\n- Add `IE11` support\n- Add `Container` component to each page to replace custom styling\n- Add `RT`L support\n- Fix a bug for Edge & Safari where users couldn't scroll properly\n- Remove deep folder nesting to keep a clean structure\n- Replace custom `useRouter` hook with `useLocation`, `useHistory` and `useParams`\n from `react-router`\n- Update code style to match with Airbnb style\n- Update dependencies\n- Update import paths\n- Update the layouts to fix scroll issues\n\n---\n\n## v1.2.0\n\n###### Aug 7, 2019\n\n- Add `axios` and `axios-mock-adapter` modules to simulate server response for fetch requests\n- Create 3 individual layouts for error, auth and dashboard pages\n- Fix navigation expand issue\n- Move helpers files to `utils` folder\n- Move all lib mixins to `mixins` folder\n- Remove `chart.js` files\n- Remove unused helpers\n- Remove unused utils\n- Rename few components\n- Replace the routing system from 1.1.0 version with an easier solution\n- Update `Calendar` page code\n- Update `Chat` page code\n- Update `Error` page code\n\n---\n\n## v1.1.1\n\n###### Aug 1, 2019\n\n- Remove `PerfectScrollBar` to fix `Navbar` and content scroll issues\n\n---\n\n## v1.1.0\n\n###### July 31, 2019\n\n- Add `Figma` source files\n- Add `PrismJS` dependency\n- Add `redux` dependency\n- Change the layout logic\n- Create `CodeBlock` component\n- Create changelog page\n- Create documentation pages\n- Fix scroll bugs\n- Implement `redux` in some components\n- Implement code splitting to lazy load pages\n- Implement layout system based on route settings\n- Implement route authorization guard based on authenticated user role and route settings\n- Implement routing system\n- Merge layouts in one layout only that can be configured dynamically\n- Rename few components\n- Replace `underscore` with `lodash`\n- Update dependencies\n- Update folder structure, grouped all pages in the same folder\n- Update presentation page\n\n---\n\n## v1.0.0\n\n###### July 20, 2019\n\nInitial release.\n","slug":"changelog","title":"Changelog"}},"__N_SSG":true} \ No newline at end of file diff --git a/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/contact.json b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/contact.json new file mode 100644 index 0000000..e06a9e6 --- /dev/null +++ b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/contact.json @@ -0,0 +1 @@ +{"pageProps":{"article":{"content":"\n# Contact\n\nOur support mainly covers pre-sale questions, basic product questions and bug reports through our\nsupport email:\n[support@deviasio.zendesk.com](mailto:support@deviasio.zendesk.com).\n\nTo be eligible to request the technical support you must have purchased the theme and have at least\none Standard or Extended license.\n\nOn submitting a support request please do describe your issue with more details. If you can provide\na link to your developing site then this can help us to solve your issue faster.\n\nAll 3rd party plugins used in the theme are provided as bonus, and we do not give any guarantee to\ntheir functionalities. Our support does not cover any 3rd party plugin customization or bug fixes\nthat are not in our control.\n\nCustomers are always welcome to ask for feature requests and give suggestions that can improve our\npremium themes. All feature requests definitely will be considered, and the new features will be\nreleased with upcoming releases.\n","slug":"contact","title":"Contact"}},"__N_SSG":true} \ No newline at end of file diff --git a/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/dependencies.json b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/dependencies.json new file mode 100644 index 0000000..c6d370c --- /dev/null +++ b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/dependencies.json @@ -0,0 +1 @@ +{"pageProps":{"article":{"content":"\n# Dependencies\n\nThe app is built using the latest trends with periodic updates. The optional dependencies are used\nto create app features. If you do not need a feature, please remove the dependency to keep the\nproject files clean and reduce dependency download and install time.\n\n## Important dependencies\n\n- `@emotion/cache` - Styling\n- `@emotion/react` - Styling\n- `@emotion/styled` - Styling\n- `@mui/icons-material` - MUI icons\n- `@mui/lab` - Base theme components\n- `@mui/material` - Base theme components\n- `@mui/system` - Base theme system utilities\n- `date-fns` - Utils to parse date and time\n- `react` - Core\n- `next` - Core\n- `stylis` - Styling\n- `stylis-plugin-rtl` - Styling\n\n## Optional dependencies\n\n- `@auth0/auth0-spa-js` - Handle Auth0 authentication\n- `@fullcalendar/core` - Calendar\n- `@fullcalendar/daygrid` - Calendar\n- `@fullcalendar/interaction` - Calendar\n- `@fullcalendar/list` - Calendar\n- `@fullcalendar/react` - Calendar\n- `@fullcalendar/timegrid` - Calendar\n- `@fullcalendar/timeline` - Calendar\n- `@react-pdf/renderer` - Render invoice\n- `@reduxjs/toolkit` - Utilities for Redux\n- `apexcharts` - Create charts\n- `aws-amplify` - Handle Amplify authentication\n- `draft-js` - Text editor core library\n- `firebase` - Handle Firebase authentication\n- `formik` - Handle form and input events\n- `gray-matter` - Parse docs markdown files\n- `i18next` - Internationalization framework\n- `lodash` - Library for merge and debounce utilities\n- `nprogress` - Display page loading progress bar\n- `numeral` - Utility to format numbers\n- `prop-types` - Add prop type schema for components\n- `react-apexcharts` - Chart components built over apexcharts library\n- `react-beautiful-dnd` - Enable drag and drop functionality for Kanban\n- `react-draft-wysiwyg` - Editor components built over draft-js library\n- `react-dropzone` - Drop zone functionality for FileDropzone component\n- `react-hot-toast` - Display and manage notifications\n- `react-i18next` - React wrapper over i18next library\n- `react-markdown` - Parse markdown in html elements\n- `react-modal-image` - Open an image in a modal with fullscreen options\n- `simplebar` - Replace browser scrollbar with custom component\n- `simplebar-react` - Simplebar React wrapper\n- `react-quill` - Text editor alternative\n- `react-redux` - React components for Redux\n- `react-syntax-highlighter` - Highlight markdown code\n- `redux-devtools-extension` - Display Redux State and Actions in devtools\n- `redux-thunk` - Middleware to enable Redux async actions\n- `redux` - State manager for Calendar, Chat, Kanban, and Mail apps\n- `yup` - Validation library\n","slug":"dependencies","title":"Dependencies"}},"__N_SSG":true} \ No newline at end of file diff --git a/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/deployment.json b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/deployment.json new file mode 100644 index 0000000..ff4119f --- /dev/null +++ b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/deployment.json @@ -0,0 +1 @@ +{"pageProps":{"article":{"content":"\n# Deployment\n\n## Node.js Server\n\nNext.js can be deployed to any hosting provider that supports Node.js. Make sure your `package.json` \nhas the `\"build\"` and `\"start\"` scripts:\n\n```json\n{\n \"scripts\": {\n \"dev\": \"next\",\n \"build\": \"next build\",\n \"start\": \"next start\"\n }\n}\n```\n\n`next build` builds the production application in the `.next` folder. After building, `next start` \nstarts a Node.js server that supports hybrid pages, serving both statically generated and \nserver-side rendered pages.\n\n## Static HTML Export\n\n`next export` allows you to export your app to static HTML, which can be run standalone without the \nneed of a Node.js server.\n\nThe exported app supports almost every feature of Next.js, including dynamic routes, prefetching, \npreloading and dynamic imports.\n\n`next export` works by prerendering all pages to HTML. For dynamic routes, your page can export a \n`getStaticPaths` function to let the exporter know which HTML pages to generate for that route.\n\nBy default, `next export` will generate an `out` directory, which can be served by any static \nhosting service or CDN.\n\nThe choice of your server software isn’t important either. Since the output of the export command \nis completely platform-agnostic, there’s no need to explicitly use Node.\n\n### Vercel Deployment\n\nThe easiest way to deploy Next.js to production is to use the `Vercel` platform from the creators of \nNext.js. `Vercel` is a cloud platform for static sites, hybrid apps, and Serverless Functions. Read \nmore about it from [official docs](https://nextjs.org/docs/deployment)\n\n### Netlify Deployment\n\nNetlify lets you link a GitHub, GitLab, or Bitbucket repository to a site for continuous deployment. \nEach time you push to your Git provider, Netlify runs a build with your tool of choice and deploys \nthe result to their CDN. Read more about it from \n[official docs](https://docs.netlify.com/configure-builds/get-started)\n\n### Firebase Hosting\n\nUsing the Firebase CLI, you deploy files from local directories on your computer to your Hosting\nserver. Beyond serving static content, you can use Cloud Functions for Firebase or Cloud Run to\nserve dynamic content and host microservices on your sites. Read more about it\nfrom [official docs](https://firebase.google.com/docs/hosting).\n","slug":"deployment","title":"Deployment"}},"__N_SSG":true} \ No newline at end of file diff --git a/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/environment-variables.json b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/environment-variables.json new file mode 100644 index 0000000..89012f0 --- /dev/null +++ b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/environment-variables.json @@ -0,0 +1 @@ +{"pageProps":{"article":{"content":"\n# Environment Variables\n\nBy default, Next.js compiler looks for `.env` file in projects root folder and reads\nits content. In the project files you'll find a file `.env.example` that contains all the\nenvironment variables that were used in the app environment. **Not all are required.**\n\n## Loading Environment Variables\n\nNext.js has built-in support for loading environment variables from `.env` file into `process.env`.\n\nAn example `.env`:\n\n```shell\nDB_HOST=localhost\nDB_USER=myuser\nDB_PASS=mypassword\n```\n\nThis loads `process.env.DB_HOST`, `process.env.DB_USER`, and `process.env.DB_PASS` into the Node.js \nenvironment automatically allowing you to use them in Next.js data fetching methods and API routes.\n\nFor example, using `getStaticProps`:\n\n```js\n// pages/index.js\nexport async function getStaticProps() {\n const db = await myDB.connect({\n host: process.env.DB_HOST,\n username: process.env.DB_USER,\n password: process.env.DB_PASS,\n });\n // ...\n}\n```\n\n## Exposing Environment Variables to the Browser\n\nBy default environment variables are only available in the Node.js environment, meaning they won't\nbe exposed to the browser.\n\nIn order to expose a variable to the browser you have to prefix the variable with `NEXT_PUBLIC_`. \nFor example:\n\n```shell\nNEXT_PUBLIC_ANALYTICS_ID=abcdefghijk\n```\n\n> WARNING: Do not store any secrets (such as private API keys or passwords) in the public variables!\n> These environment variables are embedded into the build, meaning anyone can view them by \n> inspecting your app's files.\n\n## Private Variables\n\nHaving access to the `NODE_ENV` is also useful for performing actions conditionally:\n\n```js\nif (process.env.NODE_ENV !== 'production') {\n analytics.disable();\n}\n```\n\nRead more about environment\nvariables [here](https://create-react-app.dev/docs/adding-custom-environment-variables).\n","slug":"environment-variables","title":"Environment Variables"}},"__N_SSG":true} \ No newline at end of file diff --git a/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/further-support.json b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/further-support.json new file mode 100644 index 0000000..5e6d299 --- /dev/null +++ b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/further-support.json @@ -0,0 +1 @@ +{"pageProps":{"article":{"content":"\n# Further Support\n\nThis documentation covers only broad use cases and relies on you or your developers having existing\nand pretty extensive previous knowledge of the libraries in use, as well as web technologies. Should\nthis not be your scenario, please keep in mind our team offers special training and exclusive for\npay support, and based on your project size and our availability, we can take custom requests at a\nfee. For more details please get in contact with our team of experts on\n[https://devias.io/contact](https://devias.io/contact).\n","slug":"further-support","title":"Further Support"}},"__N_SSG":true} \ No newline at end of file diff --git a/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/getting-started.json b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/getting-started.json new file mode 100644 index 0000000..2c7d802 --- /dev/null +++ b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/getting-started.json @@ -0,0 +1 @@ +{"pageProps":{"article":{"content":"\n# Getting Started\n\nBefore proceeding, you'll need to have the last stable [NodeJS](https://nodejs.org/en/)\nand [npm](https://www.npmjs.com)\ninstalled on your machine.\n\nYou can use [nvm](https://github.com/creationix/nvm#installation) (macOS/Linux) or\n[nvm-windows](https://github.com/coreybutler/nvm-windows#node-version-manager-nvm-for-windows) to\nswitch Node versions between different projects.\n\n## Install dependencies\n\nOpen the project folder and install its dependencies. You can use any package manager you\nwant: [Yarn](https://yarnpkg.com)\nor [npm](https://www.npmjs.com). There might be other package managers that were not listed here.\n\n```shell\ncd project-folder\nnpm install\n```\n\n## Start development server\n\nOnce the installation is done, you can now run your app by running `npm run dev` or `yarn dev`.\n\n```shell\nnpm run dev\n```\n\nYou will see something similar to:\n\n```shell\nready - started server on 0.0.0.0:3000, url: http://localhost:3000\ninfo - automatically enabled Fast Refresh for 1 custom loader\nevent - compiled successfully in 4.7s (1535 modules)\n```\n\nThis runs the app in development mode. Open [localhost:3000](http://localhost:3000) to view it in\nthe browser.\n\nWhile in development mode, the page will automatically reload if you make changes to the code.\nShould you have any, you will see the build errors and lint warnings in the console.\n\nThe app uses `ESLint`, so you will get detailed warnings and errors as well as best practice hints.\n\n## Build project files\n\n```shell\nnpm run build\n```\n\nor `yarn build`\n\nBuilds the app for production to the build folder. It correctly bundles React in production mode and\noptimizes the build for the best performance.\n\nThe build is minified, and the filenames include hashes.\n\nIf you have made your necessary changes, by this time, your app should ready to be deployed.\n\n> Please keep in mind that this project **_does not_** handle any backend logic nor databases; it is just a frontend you can use\n> it with any backend you want. This means that you will have to build such a backend or use any existing one you might\n> already have.\n","slug":"getting-started","title":"Getting Started"}},"__N_SSG":true} \ No newline at end of file diff --git a/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/guest-guard.json b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/guest-guard.json new file mode 100644 index 0000000..af62688 --- /dev/null +++ b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/guest-guard.json @@ -0,0 +1 @@ +{"pageProps":{"article":{"content":"\n# Guest Guard\n\nThere are some situations when you want to make a route visible exclusively for users that are not\nauthenticated, such as\n`/authentication/register`, `/authentication/login`, etc. \n\nFor such situations, the app provides you with a sample `GuestGuard` component that can be used to \nmake redirect the user to a certain route (currently `/dashboard`). Should you want to modify said \nroute you can do so by modifying the `GuestGuard` component. There was no need to make a more complex \nlogic for this GuestGuard component, as the business logic needed for your specific app might \nneed a different approach regardless.\n\nTo be able to prevent the entire page render, the app provides a simple `hoc` utility that wraps the\npage with the GuestGuard.\n\n## Example\n\n```jsx\n// src/pages/authentication/login.js\nimport { withGuestGuard } from '../../hocs/with-guest-guard';\n\nconst Login = () => {\n return (\n
\n content\n
\n );\n};\n\nexport default withGuestGuard(Login);\n```\n\n## How it works\n\nIt connects with the authentication provider (Amplify, Auth0, Firebase, or JWT, depending on your\nsetup) and extracts the required data to detect whether it can render the children passed as props,\notherwise it redirects the user to the `/dashboard` route.\n","slug":"guest-guard","title":"Guest Guard"}},"__N_SSG":true} \ No newline at end of file diff --git a/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/internationalization.json b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/internationalization.json new file mode 100644 index 0000000..95e208f --- /dev/null +++ b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/internationalization.json @@ -0,0 +1 @@ +{"pageProps":{"article":{"content":"\n# Internationalization\n\nSupporting multiple languages may represent an important feature for your app. To have this enabled\nthe app uses\n`i18next` framework. Read more about it [here](https://www.i18next.com/).\n\n## How it works\n\nYou might need to change all instances of inline text in any components to be wrapped with the `t()`\nfunction as presented below.\n\nThe library needs a configuration and initialization file, in this case, `src/i18n.js` file.\n\nFirst step is to declare the app translations as resources.\n\n```js\nconst resources = {\n en: {\n translation: {\n 'Welcome to React': 'Welcome to React and react-i18next'\n }\n },\n fr: {\n translation: {\n 'Welcome to React': 'Bienvenue à React et react-i18next'\n }\n },\n es: {\n translation: {\n 'Welcome to React': 'Bienvenido a React and react-i18next'\n }\n },\n // ...\n};\n```\n\nThese translations need to be passed in the `i18n.init()` function to make them available\ninside `App` components tree using the `useTranslation` hook.\n\n```jsx\n// src/pages/index.js\nimport { useTranslation } from 'react-i18next';\n\nconst Home = () => {\n const { t } = useTranslation();\n\n return (\n

\n {t('Welcome to React')}\n

\n );\n}\n```\n\nFor all configuration options, please follow the\n[official documentation](https://www.i18next.com/overview/configuration-options).\n\n## Removing internationalization support\n\n1. Remove `import './i18n` line from `App` component.\n2. Remove `i18n.js` configuration file from `src` folder.\n3. Remove `LanguagePopover` component since it connects with the library.\n3. Uninstall `i18next` and `react-i18next` dependencies.\n","slug":"internationalization","title":"Internationalization"}},"__N_SSG":true} \ No newline at end of file diff --git a/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/redux.json b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/redux.json new file mode 100644 index 0000000..1333af7 --- /dev/null +++ b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/redux.json @@ -0,0 +1 @@ +{"pageProps":{"article":{"content":"\n# Redux\n\nRedux is more robust alternative for state management, that offers more helpful features out of the\nbox. Follow the\n[official documentation](https://redux.js.org/basics/usage-with-react) to understand the entire\nconcept behind it.\n\n## Usage\n\nThe app uses `Redux Toolkit` with hooks (Thunk method, not Sagas) to manage the state\nfor `Calendar`, `Chat`,\n`Kanban` and `Mail` apps.\n\nThis can be replaced with `Context API`, or any other system, in a matter of hours due the clean\nstructure of the project.\n\nThe app at hand uses Redux, but you can find Context API examples in the project. You can also opt\nfor\n[Recoil](https://recoiljs.org/), maintained by **Facebook**, a new alternative that allows you to\nsplit the state in multiple \"atoms\". An example is not included, but the ones from Facebook\ndocumentation should be simple enough to use in your project.\n\n## How to use\n\nThere are 2 main folders:\n\n1. `src/slices` where you can find the implementation of the reducer logic.\n2. `src/store` which exports a store and combines the reducers in one root reducer.\n\nIf you're new to Redux Toolkit, please read\ntheir [official documentation](https://redux-toolkit.js.org/usage/usage-guide)\nto understand the basics.\n\n## Example\n\nYou can take as an example the blog feature of this app where; should you want to implement Redux;\nyou can do it as follows:\n\n### Create a new slice\n\nCreate a new file in `src/slices`, and name it `blog.js`. Now open this new file with your favorite\nIDE, and import\n`createSlice` from `@reduxjs/toolkit` package to create the new slice.\n\n```js\nimport { createSlice } from '@reduxjs/toolkit';\n\nconst initialState = {\n articles: []\n};\n\nconst slice = createSlice({\n name: 'blog',\n initialState,\n reducers: {}\n});\n\nexport const { reducer } = slice;\n\nexport default slice;\n```\n\nIt is important to assign a name to the slice and an initial state.\n\n### Create a reducer action\n\nLet's get back to the newly created slice and add a `setArticles` action.\n\n```js\nconst slice = createSlice({\n name: 'blog',\n initialState,\n reducers: {\n setArticles(state, payload) {\n // You should get articles from the action payload. \n // For simplicity's sake let's use static data instead.\n\n state.articles = [\n {\n id: '1',\n title: 'My first article'\n }\n ];\n }\n }\n});\n```\n\n> Important: The state is a Proxy object, you cannot update it directly, and you have to update its keys instead.\n>\n> For example `state = { name: 'Alex' }` will break the state, but `state.user = { name: 'Alex' }` works as expected.\n\n### Create a thunk method\n\nThis allows you to dispatch multiple actions, extremely useful for async requests.\n\nIn the created slice file, create a `getPosts` method that dispatches the slice `setArticles`\naction.\n\n```js\nexport const getPosts = () => async (dispatch) => {\n // Here make an async request to your sever and extract the data from the server response\n // const response = await axios.get('/__fake-api__/blog/articles');\n // const { data } = reponse;\n\n const data = [\n {\n id: '1',\n title: 'My first article'\n }\n ];\n\n dispatch(slice.actions.setArticles(data));\n};\n```\n\nNow, that you have a method that dispatches an action, you can update the `setArticles` action to\nuse the data from the payload.\n\n```js\nconst slice = createSlice({\n name: 'blog',\n initialState,\n reducers: {\n setArticles(state, payload) {\n state.articles = payload.articles;\n }\n }\n});\n```\n\n### Combine the new slice in the root reducer\n\nIn the file `src/store/rootReducer.js` use the reducer from your newly created slice.\n\n```js\nimport {reducer as blogReducer} from 'src/slices/blog';\n\nconst rootReducer = combineReducers({\n // ...other reducers\n blog: blogReducer\n});\n```\n\n### Using the slice state\n\n```jsx\nimport { useSelector } from 'react-redux';\n\nconst Blog = () => {\n const { articles } = useSelector((state) => state.blog);\n\n return (\n
\n
\n {articles.map((article) => (\n
\n Article ID: {article.id}\n
\n ))}\n
\n
\n );\n};\n```\n\n> Please refrain from changing the state directly (without an action) in order to avoid chained re-renders.\n\n### Dispatching an action\n\nThis is the last step of the process. Execute the method `getPosts` to dispatch the slice action\nand update the slice state. Once the action sets the new state, the app will re-render your current\ncomponent, and the articles will be displayed.\n\n```jsx\nimport { useDispatch, useSelector } from 'react-redux';\nimport { getPosts } from 'src/slices/blog';\n\nconst Blog = () => {\n const dispatch = useDispatch();\n const { articles } = useSelector((state) => state.blog);\n\n const handleClick = () => {\n dispatch(getPosts());\n };\n\n return (\n
\n
\n {articles.map((article) => (\n
\n Article ID: {article.id}\n
\n ))}\n
\n \n
\n );\n};\n```\n","slug":"redux","title":"Redux"}},"__N_SSG":true} \ No newline at end of file diff --git a/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/role-based-guard.json b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/role-based-guard.json new file mode 100644 index 0000000..10f8683 --- /dev/null +++ b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/role-based-guard.json @@ -0,0 +1 @@ +{"pageProps":{"article":{"content":"\n# Role Based Guard\n\nMany apps have complex user interfaces and flows. Some might have a list of routes for specific user\nroles or rights, such as admin, editor, content manager, etc, or even display a completely different\ninterface for the same route. If that's the case for your project, you may want to check whether the\nuser is authenticated their Access Control List (ACL)\nThis depends a lot on your business, and your chosen ACL implementation / provider.\n\nGuarding is a concept that usually refers to route protection, but it can also be applied to\ncomponents, and instead of redirecting the user to another route, you can render a different\ncomponent.\n\n## How it can be implemented\n\nThis guard is not created as there's no real way to know the actual business case, the needs, or the\nstrategy used in your specific app. Meanwhile, there are some standardized ACL strategies, there are\nstill too many of them and picking one is not fathomable in any way.\n\nAs an effect you can find below a suggestion on how it _could_ be implemented, should you want it.\n\nIn situations where various rights determine bits of the same UI, you may want to change the\nredirection to either only display the functionality as disabled or simply not display it. The \nconditional rendering scenario is a much easier one.\n\n```jsx\nconst RoleBasedGuard = (props) => {\n const { children, permissions } = props;\n const { user } = useAuth();\n \n // Here check the user permissions\n const canView = true;\n \n if (!canView) {\n return null;\n }\n\n return <>{children};\n};\n\nconst Overview = () => {\n return (\n
\n \n
\n \n
\n
\n \n
\n );\n};\n```\n","slug":"role-based-guard","title":"Role Based Guard"}},"__N_SSG":true} \ No newline at end of file diff --git a/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/routing.json b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/routing.json new file mode 100644 index 0000000..deda8ea --- /dev/null +++ b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/routing.json @@ -0,0 +1 @@ +{"pageProps":{"article":{"content":"\n# Routing\n\nNext.js has a file-system based router built on the concept of pages.\n\nWhen a file is added to the `pages` directory it's automatically available as a route.\n\nThe files inside the `pages` directory can be used to define most common patterns.\n\n## Index routes\n\nThe router will automatically route files named index to the root of the directory.\n\n- `pages/index.js` → `/`\n- `pages/blog/index.js` → `/blog`\n\n## Nested routes\n\nThe router supports nested files. If you create a nested folder structure files will be automatically routed in the same way still.\n\n- `pages/blog/first-post.js` → `/blog/first-post`\n- `pages/dashboard/settings/username.js` → `/dashboard/settings/username`\n\n## Dynamic route segments\n\nDefining routes by using predefined paths is not always enough for complex applications. In Next.js\nyou can add brackets to a page ([param]) to create a dynamic route (a.k.a. url slugs, pretty urls, \nand others).\n\nTo match a dynamic segment you can use the bracket syntax. This allows you to match named parameters.\n\n- `pages/blog/[slug].js` → `/blog/:slug` (`/blog/hello-world`)\n- `pages/[username]/settings.js` → `/:username/settings` (`/foo/settings`)\n- `pages/post/[...all].js` → `/post/*` (`/post/2020/id/title`)\n","slug":"routing","title":"Routing"}},"__N_SSG":true} \ No newline at end of file diff --git a/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/rtl.json b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/rtl.json new file mode 100644 index 0000000..7758d85 --- /dev/null +++ b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/rtl.json @@ -0,0 +1 @@ +{"pageProps":{"article":{"content":"\n# RTL\n\nText direction is extremely important for cultures where \"right-to-left\" writing is used. The app\nhas this functionality implemented.\n\n## How it works\n\nThe wrapper component, `RTL`, is necessary to be above the app content in the tree. The component\nchanges the document direction, and appends a `stylis` plugin which converts all component styles to\nmirror the margins and paddings.\n\n```jsx\n// src/pages/_app.js\nconst App = (props) => {\n const { Component, pageProps } = props;\n \n return (\n \n \n \n );\n};\n```\n\n`direction` prop can be `\"ltr\"` or `\"rtl\"`. When using `\"ltr\"` the component simply renders the\nchildren, without affecting the styling.\n\n## Removing RTL support\n\nIf you do not need to support RTL, you can remove it by following the next steps.\n\n1. Remove `RTL` component from `src/components`.\n2. Remove `RTL` component import and usage from `App` component.\n2. Uninstall the `@emotion/cache` and`stylis-plugin-rtl` dependencies.\n","slug":"rtl","title":"RTL"}},"__N_SSG":true} \ No newline at end of file diff --git a/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/server-calls.json b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/server-calls.json new file mode 100644 index 0000000..837ba04 --- /dev/null +++ b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/server-calls.json @@ -0,0 +1 @@ +{"pageProps":{"article":{"content":"\n# Server Calls\n\nThe application simulates all server calls using in memory data storage. This can be easily modified\nto connect to any server.\n\nYou can use any library you like. Most apps use [Axios](https://github.com/axios/axios) since it\nallows you to create instances, attach interceptors, and many other features. Another good\nalternative could be [Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API).\n\n## Example of current implementation\n\n```jsx\nclass CustomerApi {\n getCustomers() {\n return Promise.resolve([\n {\n id: '238339KDC',\n name: 'John' \n }\n ]);\n }\n};\n\nconst customerApi = new CustomerApi();\n\nconst Customers = () => {\n const [customers, setCustomers] = useState(null);\n\n useEffect(() => {\n const getCustomers = async () => {\n const result = await customerApi.getCustomers();\n setCustomers(result);\n };\n\n getCustomers();\n }, []);\n\n return (\n
\n {/* render content */}\n
\n );\n};\n```\n\nThe `customerApi` is a singleton class instance that simply responds with a Promise. You can add as\nmany requests methods as you need, test request structure or even use as middleware between UI and\nserver request to process your input and output data.\n\n## Example with Fetch\n\n```jsx\nconst Customers = () => {\n const [customers, setCustomers] = useState(null);\n\n useEffect(() => {\n const getCustomers = async () => {\n const response = await fetch('/api/customers');\n const data = await response.json();\n setCustomers(data);\n };\n\n getCustomers();\n }, []);\n\n return (\n
\n {/* render content */}\n
\n );\n};\n```\n\n## Example with Axios\n\n```jsx\nimport axios from 'axios'; // You need to install it\n\nconst Customers = () => {\n const [customers, setCustomers] = useState(null);\n\n useEffect(() => {\n const getCustomers = async () => {\n const response = await axios.get('/api/customers');\n setCustomers(response.data);\n };\n\n getCustomers();\n }, []);\n\n return (\n
\n {/* render content */}\n
\n );\n};\n```\n\n## Axios Request interceptors\n\nBy using Axios you are able to\nintegrate [Axios Mock Adapter](https://github.com/ctimmerm/axios-mock-adapter) to simulate real\nserver calls. To archive that, you have to create an Axios instance and use it whenever you make a\nrequest call. Now you can extend your instance and add Axios Mock Adapter to listen for requests and\nreturn custom data.\n\n## Adding request interceptors\n\nIt takes ony a few seconds to add a new http request listener. The interceptor has a similar format\nto Express JS, for example:\n\n```js\nimport axios from 'axios'; // You need to install it\nimport AxiosMockAdapter from 'axios-mock-adapter'; // You need to install it\n\nexport const axiosInstance = axios.create();\n\naxiosInstance.interceptors.response.use(\n (response) => response,\n (error) => Promise.reject((error.response && error.response.data) || 'Something went wrong')\n);\n\nconst mock = new AxiosMockAdapter(axiosInstance, {delayResponse: 0});\n\nmock.onGet('/__fake-api__/invoices').reply(200, {\n invoices: [\n {id: 1, total: 32.43},\n {id: 2, total: 67.00}\n ]\n});\n```\n\nNow instead of importing axios from `axios` node module, import the exported `axiosInstance` to get\nthe customers' data.\n\n## Removing existing request interceptors\n\nThere are two ways:\n\n1. Simply use a new axios instance.\n2. Remove the mocked listeners.\n","slug":"server-calls","title":"Server Calls"}},"__N_SSG":true} \ No newline at end of file diff --git a/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/settings.json b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/settings.json new file mode 100644 index 0000000..7d830a6 --- /dev/null +++ b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/settings.json @@ -0,0 +1 @@ +{"pageProps":{"article":{"content":"\n# Settings\n\nIt is important for your customers to have some control over the app interface. To make that\npossible you need a way to let the app know which are the user preferences. In order to achieve it,\nthe app uses a context that can make its data available in the entire component tree for usage and\ncontrol.\n\nCurrently, the app allows you to control the `theme`, and you can choose between available options,\ntoggle `RTL`\n(right-to-left text direction). This is a simple implementation to give you an idea\non how can the configurations be made. It might be in your best interest to adjust it to your\nbusiness needs. You might want to have a specific app interface, and allow other setup options, or\nremove some of the existing ones.\n\n## How it works\n\n```jsx\n// src/pages/_app.js\nimport { SettingsProvider } from '../contexts/settings-context';\n\nconst App = (props) => {\n const { Component, pageProps } = props;\n \n return (\n \n \n \n );\n};\n```\n\nThe content of the `App` component is wrapped with the `SettingsProvider`, and by doing this its \ncontext data is made available inside the component tree.\n\n## How to use\n\nThere are two methods, using the hook or the context consumer.\n\n```jsx\n// src/pages/index.js\nimport { useSettings } from '../hooks/useSettings';\n\nconst Home = () => {\n const { settings } = useSettings();\n\n return (\n
\n Current theme: {settings.theme}\n
\n );\n};\n```\n\n```jsx\n// src/pages/index.js\nimport { SettingsConsumer } from '../contexts/settings-context';\n\nconst Home = () => {\n return (\n \n {({settings}) => (\n
\n Current theme: {settings.theme}\n
\n )}\n
\n );\n};\n```\n\n## Triggering the settings update\n\nIt can be implemented in any component within seconds.\n\n```jsx\n// src/pages/index.js\nimport { useSettings } from '../hooks/useSettings';\n\nconst Home = () => {\n const { settings, saveSettings } = useSettings();\n\n const handleSave = () => {\n saveSettings({\n ...settings,\n theme: 'dark'\n });\n };\n\n return (\n
\n \n
\n );\n};\n```\n\n## Store / restore user preferences\n\nThe SettingsContext on mount event, it extracts stored settings from `localStorage` (if available);\nif not, a default value is provided. This can be extended and, instead of using the localStorage,\nyou can use a server. This gives the user the possibility to have the same settings across multiple\ndevices.\n","slug":"settings","title":"Settings"}},"__N_SSG":true} \ No newline at end of file diff --git a/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/theming.json b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/theming.json new file mode 100644 index 0000000..a80eb2b --- /dev/null +++ b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/theming.json @@ -0,0 +1 @@ +{"pageProps":{"article":{"content":"\n# Theming\n\nMUI offers a utility function: `createTheme()` that creates a theme which can be passed to\nthe theme provider; otherwise the theme provider uses the default theme. The theme provider makes\nthe theme available in the component tree, and can be used via the `sx` prop, or inside styled\ncomponents using the MUI styled engine (`styled`).\n\n## Creating a theme\n\nThe app allows you to choose between multiple theme setups, thus a wrapper was created over\nthe `createTheme`. Currently, the function accepts a configuration object with the following keys:\n\n- `direction` [ 'ltr' | 'rtl' ] - Sets the text direction. If you need RTL support, please ensure\n you use `RTL` component.\n- `responsiveFontSizes` [ boolean ] - Adaptive font size for small devices.\n- `mode` [ 'light' | 'dark' ] - Select a specific theme configuration. You can add your own styling\n or adjust current options.\n\n```js\n// src/pages/index.js\nimport { ThemeProvider } from '@mui/material/styles';\nimport { createTheme } from '../theme';\n\nconst Home = () => {\n const theme = createTheme({\n direction: 'ltr',\n responsiveFontSizes: true, \n mode: 'dark'\n });\n\n return (\n \n
\n content\n
\n
\n );\n}\n```\n\n## Nested themes\n\nMultiple themes can be nested. The app implements this behaviour to display the components on\nlight/dark palette mode without changing the app global theme.\n\n```jsx\n// src/pages/index.js\nimport { ThemeProvider } from '@mui/material/styles';\nimport { createTheme } from '../theme';\n\nconst Home = () => {\n const theme = createTheme({\n direction: 'ltr',\n responsiveFontSizes: true,\n mode: 'dark'\n });\n\n const theme2 = createTheme({\n mode: 'light'\n });\n\n return (\n \n
\n
Main theme
\n \n
Inner theme
\n
\n
\n
\n );\n}\n```\n","slug":"theming","title":"Theming"}},"__N_SSG":true} \ No newline at end of file diff --git a/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/welcome.json b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/welcome.json new file mode 100644 index 0000000..62b0870 --- /dev/null +++ b/out/_next/data/54pR1GRelp3C75LWMwxPy/docs/welcome.json @@ -0,0 +1 @@ +{"pageProps":{"article":{"content":"\n# About the documentation\n\nWelcome to the documentation for Devias Material Kit Pro! This documentation will take you\nfrom [getting started](getting-started)\nwith our kit to customizing it and making it work for your use case.\n\n## Something Missing?\n\nIf you have ideas for more \"How To\" recipes that should be on this page, please, let us know or\ncontribute some!\n\n## Feedback\n\nWe are always happy for you to send your feedback\nat [support@deviasio.zendesk.com](mailto:support@deviasio.zendesk.com).\n","slug":"welcome","title":"Welcome"}},"__N_SSG":true} \ No newline at end of file diff --git a/out/_next/static/54pR1GRelp3C75LWMwxPy/_buildManifest.js b/out/_next/static/54pR1GRelp3C75LWMwxPy/_buildManifest.js new file mode 100644 index 0000000..7c9b4a3 --- /dev/null +++ b/out/_next/static/54pR1GRelp3C75LWMwxPy/_buildManifest.js @@ -0,0 +1 @@ +self.__BUILD_MANIFEST=function(s,a,e,c,t,d,o,r,i,b,h,n,u,p,g,f,k,m,j,l,w,y,_,I,v,B,F,q,z,A,D,E,L,M,N,S){return{__rewrites:{beforeFiles:[],afterFiles:[],fallback:[]},"/":[s,a,c,p,g,l,z,A,"static/chunks/pages/index-b79d7508be2e6c10.js"],"/401":[s,"static/chunks/pages/401-6e62a622bd86fec0.js"],"/404":[s,"static/chunks/pages/404-afd8d135bb8896f1.js"],"/500":[s,"static/chunks/pages/500-53e6991cd42c0022.js"],"/_error":["static/chunks/pages/_error-e18771d792fd8fe7.js"],"/authentication/authorize":["static/chunks/pages/authentication/authorize-48b5fa0aea37d4d1.js"],"/authentication/login":[s,a,c,p,g,l,z,A,"static/chunks/pages/authentication/login-694b72cf9eb0e6c4.js"],"/authentication/password-recovery":[s,a,c,p,g,l,"static/chunks/pages/authentication/password-recovery-bd59d78812be92a7.js"],"/authentication/password-reset":[s,a,c,p,g,l,"static/chunks/pages/authentication/password-reset-08671ba1cfc12d4f.js"],"/authentication/register":[s,a,c,p,g,l,"static/chunks/pages/authentication/register-9872a790eb7e8184.js"],"/authentication/verify-code":[s,a,c,p,g,l,"static/chunks/pages/authentication/verify-code-7c8dd181e82ece42.js"],"/blog":[s,a,c,t,v,D,"static/chunks/pages/blog-f46892003ee29462.js"],"/blog/new":[s,a,e,c,t,y,E,"static/chunks/pages/blog/new-b33cad28ae50d6f6.js"],"/blog/[postId]":[s,a,c,t,_,D,"static/chunks/668-b532f95d812bfbbc.js","static/chunks/pages/blog/[postId]-7ad731a824b73169.js"],"/browse":[s,e,d,t,j,"static/chunks/pages/browse-851d31b7ab20111b.js"],"/browse/buttons":[s,e,d,t,"static/chunks/7550-6516c1939aa792bf.js",j,"static/chunks/pages/browse/buttons-f6bb23cea56d2fd0.js"],"/browse/charts":[s,e,d,t,o,f,w,j,r,"static/chunks/pages/browse/charts-8ecd286b101f0410.js"],"/browse/colors":[s,e,d,t,j,"static/chunks/pages/browse/colors-618c99d665435ef7.js"],"/browse/data-display/detail-lists":[s,a,e,c,d,t,b,u,f,_,"static/chunks/9234-6a1ac89ec5a353fe.js",j,"static/chunks/pages/browse/data-display/detail-lists-7896d7e62c871d0d.js"],"/browse/data-display/quick-stats":[s,e,d,t,f,w,"static/chunks/8789-54ecdd4d68c6a5c9.js",j,"static/chunks/pages/browse/data-display/quick-stats-7be85d75660f5872.js"],"/browse/data-display/tables":[s,a,e,c,d,t,o,i,u,f,k,m,j,r,"static/chunks/pages/browse/data-display/tables-27b772d4d3130242.js"],"/browse/forms":[s,a,e,c,d,t,i,f,m,y,B,L,M,"static/chunks/9853-d1a218465f8e6387.js",j,"static/chunks/pages/browse/forms-a65d8e372cd70f92.js"],"/browse/inputs":[s,a,e,c,d,t,m,B,L,j,"static/chunks/pages/browse/inputs-697240a350c87a73.js"],"/browse/lists/grid-lists":[s,a,e,d,t,f,F,N,"static/chunks/3870-11e38da4407f36d3.js",j,"static/chunks/pages/browse/lists/grid-lists-c10944f9ba5936a9.js"],"/browse/lists/grouped-lists":[s,e,d,t,o,b,u,f,N,j,r,"static/chunks/pages/browse/lists/grouped-lists-ab322a393dd1cd94.js"],"/browse/modals":[s,a,e,c,d,t,i,y,"static/chunks/3371-5dfbc726ca364164.js",j,"static/chunks/pages/browse/modals-fa515d386edb6423.js"],"/browse/typography":[s,e,d,t,j,"static/chunks/pages/browse/typography-62eee01617cf7b4f.js"],"/checkout":[s,a,e,c,d,t,o,i,b,h,f,B,n,r,"static/chunks/pages/checkout-0f2238a82d19ba4f.js"],"/contact":[s,a,e,c,d,t,o,i,b,h,n,r,"static/chunks/pages/contact-f17d797204b601e5.js"],"/dashboard":[s,a,e,c,d,t,o,i,b,h,u,f,w,n,r,"static/chunks/pages/dashboard-669743c629ce10ea.js"],"/dashboard/account":[s,a,e,c,d,t,o,i,b,h,u,m,n,r,"static/chunks/pages/dashboard/account-bfbe31b3f3c189d4.js"],"/dashboard/analytics":[s,a,e,c,d,t,o,i,b,h,u,f,w,n,r,"static/chunks/pages/dashboard/analytics-e7a103f8933d7a8e.js"],"/dashboard/chat":[s,a,e,c,d,o,i,b,h,"static/chunks/387-df0d48d459e9834b.js",n,r,"static/chunks/pages/dashboard/chat-d01b3494a9d812b1.js"],"/dashboard/competencies":[s,a,e,c,d,t,o,i,b,h,u,f,k,m,n,I,r,"static/chunks/pages/dashboard/competencies-2d9902e078a1972e.js"],"/dashboard/competencies/groups":[s,a,e,c,d,t,o,i,b,h,u,k,n,r,"static/chunks/pages/dashboard/competencies/groups-739ca63ecc903d07.js"],"/dashboard/competencies/groups/add":[s,a,e,c,d,t,o,i,b,h,p,g,n,r,"static/chunks/pages/dashboard/competencies/groups/add-9cd82a667936cdb1.js"],"/dashboard/competencies/groups/edit":[s,a,e,c,d,t,o,i,b,h,p,g,n,r,"static/chunks/pages/dashboard/competencies/groups/edit-067a6ecf6e6b375c.js"],"/dashboard/competencies/parameters":[s,a,e,c,d,t,o,i,b,h,u,k,m,n,r,"static/chunks/pages/dashboard/competencies/parameters-7f4ab33e298a9226.js"],"/dashboard/competencies/parameters/add":[s,a,e,c,d,t,o,i,b,h,p,g,n,r,"static/chunks/pages/dashboard/competencies/parameters/add-309b0c85ae89dc7e.js"],"/dashboard/competencies/parameters/edit":[s,a,e,c,d,t,o,i,b,h,p,g,n,r,"static/chunks/pages/dashboard/competencies/parameters/edit-3e64f05ce378e3b4.js"],"/dashboard/competencies/suggestions":[s,a,e,c,d,t,o,i,b,h,u,k,m,n,r,"static/chunks/pages/dashboard/competencies/suggestions-e9b88fce767c4c1b.js"],"/dashboard/competencies/suggestions/add":[s,a,e,c,d,t,o,i,b,h,p,g,n,r,"static/chunks/pages/dashboard/competencies/suggestions/add-188de54c37ac4067.js"],"/dashboard/competencies/suggestions/edit":[s,a,e,c,d,t,o,i,b,h,p,g,n,r,"static/chunks/pages/dashboard/competencies/suggestions/edit-a595d8636681fa2e.js"],"/dashboard/competency/groups":[s,a,e,c,d,t,o,i,b,h,u,k,m,n,q,r,"static/chunks/pages/dashboard/competency/groups-53225b8bcc33ede6.js"],"/dashboard/competency/parameters":[s,a,e,c,d,t,o,i,b,h,u,k,m,n,q,r,"static/chunks/pages/dashboard/competency/parameters-6356bf4718f23a68.js"],"/dashboard/competency/suggestions":[s,a,e,c,d,t,o,i,b,h,u,k,m,n,q,r,"static/chunks/pages/dashboard/competency/suggestions-87f42c573fefdd45.js"],"/dashboard/customers":[s,a,e,c,d,t,o,i,b,h,u,f,k,m,n,I,r,"static/chunks/pages/dashboard/customers-0cd135b328fc4743.js"],"/dashboard/customers/add":[s,a,e,c,d,t,o,i,b,h,u,p,g,f,k,n,I,r,"static/chunks/pages/dashboard/customers/add-f25cad240c81651b.js"],"/dashboard/customers/edit":[s,a,e,c,d,t,o,i,b,h,u,p,g,f,k,n,I,r,"static/chunks/pages/dashboard/customers/edit-7ad92b49ce8ad1e4.js"],"/dashboard/customers/[customerId]":[s,a,e,c,d,t,o,i,b,h,u,k,m,v,n,r,"static/chunks/pages/dashboard/customers/[customerId]-b27556f8549e729e.js"],"/dashboard/customers/[customerId]/edit":[s,a,e,c,d,t,o,i,b,h,p,g,v,n,r,"static/chunks/pages/dashboard/customers/[customerId]/edit-15bcd37cc1e6c128.js"],"/dashboard/finance":[s,a,e,c,d,t,o,i,b,h,u,f,w,n,r,"static/chunks/pages/dashboard/finance-84677e8fedbf1178.js"],"/dashboard/logistics":[s,a,e,c,d,t,o,i,b,h,u,w,n,r,"static/chunks/pages/dashboard/logistics-3558e20b270541fd.js"],"/dashboard/mail":[s,a,e,c,d,o,i,b,h,y,_,n,r,"static/chunks/pages/dashboard/mail-c53a4fe0ae94fab2.js"],"/dashboard/pricing":[s,a,e,c,d,t,o,i,b,h,n,r,"static/chunks/pages/dashboard/pricing-707fa2ae9b4ca8e0.js"],"/dashboard/products":[s,a,e,c,d,t,o,i,b,h,u,f,k,M,n,r,"static/chunks/pages/dashboard/products-da8297efa2ddacdd.js"],"/dashboard/products/new":[s,a,e,c,d,t,o,i,b,h,p,g,y,E,n,r,"static/chunks/pages/dashboard/products/new-32906550550f4e90.js"],"/dashboard/sessions/schedule":[s,a,e,c,d,t,o,i,b,h,u,k,n,r,"static/chunks/pages/dashboard/sessions/schedule-0615686a431d6e32.js"],"/dashboard/social/feed":[s,a,e,c,d,o,i,b,h,F,n,S,r,"static/chunks/pages/dashboard/social/feed-01bc79bde1ac59b0.js"],"/dashboard/social/profile":[s,a,e,c,d,t,o,i,b,h,m,F,n,S,r,"static/chunks/pages/dashboard/social/profile-bad728938c71c6b7.js"],"/dashboard/teams/groups":[s,a,e,c,d,t,o,i,b,h,u,k,n,r,"static/chunks/pages/dashboard/teams/groups-ea97ec6998f73f4a.js"],"/dashboard/teams/groups/add":[s,a,e,c,d,t,o,i,b,h,p,g,n,r,"static/chunks/pages/dashboard/teams/groups/add-73a035a65c6126f8.js"],"/dashboard/teams/groups/edit":[s,a,e,c,d,t,o,i,b,h,p,g,n,r,"static/chunks/pages/dashboard/teams/groups/edit-a5f60ccb9390b21a.js"],"/dashboard/teams/members":[s,a,e,c,d,t,o,i,b,h,u,k,m,n,r,"static/chunks/pages/dashboard/teams/members-1eabab61ce56f47a.js"],"/dashboard/teams/members/add":[s,a,e,c,d,t,o,i,b,h,p,g,n,r,"static/chunks/pages/dashboard/teams/members/add-ce5195aa986cf790.js"],"/dashboard/teams/members/edit":[s,a,e,c,d,t,o,i,b,h,p,g,n,r,"static/chunks/pages/dashboard/teams/members/edit-a26d8b5290d80ca9.js"],"/docs/[slug]":[s,e,o,_,"static/chunks/991-3e2c2f1fbd3b1d28.js",r,"static/chunks/pages/docs/[slug]-f9d15d1f34c978fe.js"],sortedPages:["/","/401","/404","/500","/_app","/_error","/authentication/authorize","/authentication/login","/authentication/password-recovery","/authentication/password-reset","/authentication/register","/authentication/verify-code","/blog","/blog/new","/blog/[postId]","/browse","/browse/buttons","/browse/charts","/browse/colors","/browse/data-display/detail-lists","/browse/data-display/quick-stats","/browse/data-display/tables","/browse/forms","/browse/inputs","/browse/lists/grid-lists","/browse/lists/grouped-lists","/browse/modals","/browse/typography","/checkout","/contact","/dashboard","/dashboard/account","/dashboard/analytics","/dashboard/chat","/dashboard/competencies","/dashboard/competencies/groups","/dashboard/competencies/groups/add","/dashboard/competencies/groups/edit","/dashboard/competencies/parameters","/dashboard/competencies/parameters/add","/dashboard/competencies/parameters/edit","/dashboard/competencies/suggestions","/dashboard/competencies/suggestions/add","/dashboard/competencies/suggestions/edit","/dashboard/competency/groups","/dashboard/competency/parameters","/dashboard/competency/suggestions","/dashboard/customers","/dashboard/customers/add","/dashboard/customers/edit","/dashboard/customers/[customerId]","/dashboard/customers/[customerId]/edit","/dashboard/finance","/dashboard/logistics","/dashboard/mail","/dashboard/pricing","/dashboard/products","/dashboard/products/new","/dashboard/sessions/schedule","/dashboard/social/feed","/dashboard/social/profile","/dashboard/teams/groups","/dashboard/teams/groups/add","/dashboard/teams/groups/edit","/dashboard/teams/members","/dashboard/teams/members/add","/dashboard/teams/members/edit","/docs/[slug]"]}}("static/chunks/7760-627d25c84162375e.js","static/chunks/8576-d69b6b65f41ff83a.js","static/chunks/512-0ca373c6f974d223.js","static/chunks/7836-302ce12d9d44b745.js","static/chunks/539-a8026772a341a7c8.js","static/chunks/6049-c7cbbc006dd69479.js","static/chunks/3837-17d3bc632a9250f9.js","static/css/7070db173c6e3359.css","static/chunks/6755-83ab3abc6446ae18.js","static/chunks/1557-25d80846a52ff063.js","static/chunks/3958-935438b7d8a0a165.js","static/chunks/8863-fdc839f4b1afa0f1.js","static/chunks/100-30bc7bd933b06de8.js","static/chunks/939-a8fa4c88563e577a.js","static/chunks/551-1b31af80a7130441.js","static/chunks/2077-475a41ab12c57891.js","static/chunks/912-7e39e3b1f7a88fb8.js","static/chunks/4215-ef2da431a1cb9743.js","static/chunks/3134-2b59e83490201f34.js","static/chunks/6749-6e0b73b7ab591890.js","static/chunks/790-e50e617310104d37.js","static/css/43a3beee4ec19559.css","static/chunks/4740-9cffb7334321c729.js","static/chunks/6808-5dd225748396e1e4.js","static/chunks/1944-46c2cf8791ed3adb.js","static/chunks/6708-90d6f28625c6ea5b.js","static/chunks/1797-8421261ee9d24003.js","static/chunks/682-df0d0400cb5a891f.js","static/chunks/6281-1753f8d4a3ea2a69.js","static/chunks/8694-486e5f8ee0d99a68.js","static/chunks/857-5671a3bfcf03854c.js","static/chunks/7027-4d97e0d75733970b.js","static/chunks/5375-ab2c5bb6993ec359.js","static/chunks/9689-a49f689909c59a92.js","static/chunks/2681-308d7dbca173bcdd.js","static/chunks/4971-70340b672a7dfe07.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); \ No newline at end of file diff --git a/out/_next/static/54pR1GRelp3C75LWMwxPy/_ssgManifest.js b/out/_next/static/54pR1GRelp3C75LWMwxPy/_ssgManifest.js new file mode 100644 index 0000000..0b01d63 --- /dev/null +++ b/out/_next/static/54pR1GRelp3C75LWMwxPy/_ssgManifest.js @@ -0,0 +1 @@ +self.__SSG_MANIFEST=new Set(["\u002Fdocs\u002F[slug]"]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB() \ No newline at end of file diff --git a/out/_next/static/chunks/100-30bc7bd933b06de8.js b/out/_next/static/chunks/100-30bc7bd933b06de8.js new file mode 100644 index 0000000..861c7bb --- /dev/null +++ b/out/_next/static/chunks/100-30bc7bd933b06de8.js @@ -0,0 +1,2 @@ +"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[100],{49837:function(e,t,r){r.d(t,{Z:function(){return h}});var a=r(87462),o=r(63366),i=r(67294),n=r(86010),l=r(94780),d=r(81719),s=r(78884),c=r(70918),p=r(34867),u=r(1588);function v(e){return(0,p.Z)("MuiCard",e)}(0,u.Z)("MuiCard",["root"]);var g=r(85893);let Z=["className","raised"],f=e=>{let{classes:t}=e;return(0,l.Z)({root:["root"]},v,t)},y=(0,d.ZP)(c.Z,{name:"MuiCard",slot:"Root",overridesResolver:(e,t)=>t.root})(()=>({overflow:"hidden"})),m=i.forwardRef(function(e,t){let r=(0,s.Z)({props:e,name:"MuiCard"}),{className:i,raised:l=!1}=r,d=(0,o.Z)(r,Z),c=(0,a.Z)({},r,{raised:l}),p=f(c);return(0,g.jsx)(y,(0,a.Z)({className:(0,n.Z)(p.root,i),elevation:l?8:void 0,ref:t,ownerState:c},d))});var h=m},39807:function(e,t,r){r.d(t,{Z:function(){return x}});var a=r(87462),o=r(63366),i=r(67294),n=r(86010),l=r(94780),d=r(80858),s=r(78884),c=r(81719),p=r(34867),u=r(1588);function v(e){return(0,p.Z)("MuiTableBody",e)}(0,u.Z)("MuiTableBody",["root"]);var g=r(85893);let Z=["className","component"],f=e=>{let{classes:t}=e;return(0,l.Z)({root:["root"]},v,t)},y=(0,c.ZP)("tbody",{name:"MuiTableBody",slot:"Root",overridesResolver:(e,t)=>t.root})({display:"table-row-group"}),m={variant:"body"},h="tbody",b=i.forwardRef(function(e,t){let r=(0,s.Z)({props:e,name:"MuiTableBody"}),{className:i,component:l=h}=r,c=(0,o.Z)(r,Z),p=(0,a.Z)({},r,{component:l}),u=f(p);return(0,g.jsx)(d.Z.Provider,{value:m,children:(0,g.jsx)(y,(0,a.Z)({className:(0,n.Z)(u.root,i),as:l,ref:t,role:l===h?null:"rowgroup",ownerState:p},c))})});var x=b},5605:function(e,t,r){r.d(t,{Z:function(){return k}});var a=r(63366),o=r(87462),i=r(67294),n=r(86010),l=r(94780),d=r(41796),s=r(36622),c=r(21109),p=r(80858),u=r(78884),v=r(81719),g=r(34867),Z=r(1588);function f(e){return(0,g.Z)("MuiTableCell",e)}let y=(0,Z.Z)("MuiTableCell",["root","head","body","footer","sizeSmall","sizeMedium","paddingCheckbox","paddingNone","alignLeft","alignCenter","alignRight","alignJustify","stickyHeader"]);var m=r(85893);let h=["align","className","component","padding","scope","size","sortDirection","variant"],b=e=>{let{classes:t,variant:r,align:a,padding:o,size:i,stickyHeader:n}=e,d={root:["root",r,n&&"stickyHeader","inherit"!==a&&`align${(0,s.Z)(a)}`,"normal"!==o&&`padding${(0,s.Z)(o)}`,`size${(0,s.Z)(i)}`]};return(0,l.Z)(d,f,t)},x=(0,v.ZP)("td",{name:"MuiTableCell",slot:"Root",overridesResolver(e,t){let{ownerState:r}=e;return[t.root,t[r.variant],t[`size${(0,s.Z)(r.size)}`],"normal"!==r.padding&&t[`padding${(0,s.Z)(r.padding)}`],"inherit"!==r.align&&t[`align${(0,s.Z)(r.align)}`],r.stickyHeader&&t.stickyHeader]}})(({theme:e,ownerState:t})=>(0,o.Z)({},e.typography.body2,{display:"table-cell",verticalAlign:"inherit",borderBottom:e.vars?`1px solid ${e.vars.palette.TableCell.border}`:`1px solid + ${"light"===e.palette.mode?(0,d.$n)((0,d.Fq)(e.palette.divider,1),.88):(0,d._j)((0,d.Fq)(e.palette.divider,1),.68)}`,textAlign:"left",padding:16},"head"===t.variant&&{color:(e.vars||e).palette.text.primary,lineHeight:e.typography.pxToRem(24),fontWeight:e.typography.fontWeightMedium},"body"===t.variant&&{color:(e.vars||e).palette.text.primary},"footer"===t.variant&&{color:(e.vars||e).palette.text.secondary,lineHeight:e.typography.pxToRem(21),fontSize:e.typography.pxToRem(12)},"small"===t.size&&{padding:"6px 16px",[`&.${y.paddingCheckbox}`]:{width:24,padding:"0 12px 0 16px","& > *":{padding:0}}},"checkbox"===t.padding&&{width:48,padding:"0 0 0 4px"},"none"===t.padding&&{padding:0},"left"===t.align&&{textAlign:"left"},"center"===t.align&&{textAlign:"center"},"right"===t.align&&{textAlign:"right",flexDirection:"row-reverse"},"justify"===t.align&&{textAlign:"justify"},t.stickyHeader&&{position:"sticky",top:0,zIndex:2,backgroundColor:(e.vars||e).palette.background.default})),C=i.forwardRef(function(e,t){let r=(0,u.Z)({props:e,name:"MuiTableCell"}),{align:l="inherit",className:d,component:s,padding:v,scope:g,size:Z,sortDirection:f,variant:y}=r,C=(0,a.Z)(r,h),k=i.useContext(c.Z),w=i.useContext(p.Z),M=w&&"head"===w.variant,R;R=s||(M?"th":"td");let T=g;!T&&M&&(T="col");let $=y||w&&w.variant,H=(0,o.Z)({},r,{align:l,component:R,padding:v||(k&&k.padding?k.padding:"normal"),size:Z||(k&&k.size?k.size:"medium"),sortDirection:f,stickyHeader:"head"===$&&k&&k.stickyHeader,variant:$}),z=b(H),N=null;return f&&(N="asc"===f?"ascending":"descending"),(0,m.jsx)(x,(0,o.Z)({as:R,ref:t,className:(0,n.Z)(z.root,d),"aria-sort":N,scope:T,ownerState:H},C))});var k=C},69417:function(e,t,r){r.d(t,{Z:function(){return x}});var a=r(87462),o=r(63366),i=r(67294),n=r(86010),l=r(94780),d=r(41796),s=r(80858),c=r(78884),p=r(81719),u=r(34867),v=r(1588);function g(e){return(0,u.Z)("MuiTableRow",e)}let Z=(0,v.Z)("MuiTableRow",["root","selected","hover","head","footer"]);var f=r(85893);let y=["className","component","hover","selected"],m=e=>{let{classes:t,selected:r,hover:a,head:o,footer:i}=e;return(0,l.Z)({root:["root",r&&"selected",a&&"hover",o&&"head",i&&"footer"]},g,t)},h=(0,p.ZP)("tr",{name:"MuiTableRow",slot:"Root",overridesResolver(e,t){let{ownerState:r}=e;return[t.root,r.head&&t.head,r.footer&&t.footer]}})(({theme:e})=>({color:"inherit",display:"table-row",verticalAlign:"middle",outline:0,[`&.${Z.hover}:hover`]:{backgroundColor:(e.vars||e).palette.action.hover},[`&.${Z.selected}`]:{backgroundColor:e.vars?`rgba(${e.vars.palette.primary.mainChannel} / ${e.vars.palette.action.selectedOpacity})`:(0,d.Fq)(e.palette.primary.main,e.palette.action.selectedOpacity),"&:hover":{backgroundColor:e.vars?`rgba(${e.vars.palette.primary.mainChannel} / calc(${e.vars.palette.action.selectedOpacity} + ${e.vars.palette.action.hoverOpacity}))`:(0,d.Fq)(e.palette.primary.main,e.palette.action.selectedOpacity+e.palette.action.hoverOpacity)}}})),b=i.forwardRef(function(e,t){let r=(0,c.Z)({props:e,name:"MuiTableRow"}),{className:l,component:d="tr",hover:p=!1,selected:u=!1}=r,v=(0,o.Z)(r,y),g=i.useContext(s.Z),Z=(0,a.Z)({},r,{component:d,hover:p,selected:u,head:g&&"head"===g.variant,footer:g&&"footer"===g.variant}),b=m(Z);return(0,f.jsx)(h,(0,a.Z)({as:d,ref:t,className:(0,n.Z)(b.root,l),role:"tr"===d?null:"row",ownerState:Z},v))});var x=b},90244:function(e,t,r){r.d(t,{Z:function(){return b}});var a=r(63366),o=r(87462),i=r(67294),n=r(86010),l=r(94780),d=r(21109),s=r(78884),c=r(81719),p=r(34867),u=r(1588);function v(e){return(0,p.Z)("MuiTable",e)}(0,u.Z)("MuiTable",["root","stickyHeader"]);var g=r(85893);let Z=["className","component","padding","size","stickyHeader"],f=e=>{let{classes:t,stickyHeader:r}=e;return(0,l.Z)({root:["root",r&&"stickyHeader"]},v,t)},y=(0,c.ZP)("table",{name:"MuiTable",slot:"Root",overridesResolver(e,t){let{ownerState:r}=e;return[t.root,r.stickyHeader&&t.stickyHeader]}})(({theme:e,ownerState:t})=>(0,o.Z)({display:"table",width:"100%",borderCollapse:"collapse",borderSpacing:0,"& caption":(0,o.Z)({},e.typography.body2,{padding:e.spacing(2),color:(e.vars||e).palette.text.secondary,textAlign:"left",captionSide:"bottom"})},t.stickyHeader&&{borderCollapse:"separate"})),m="table",h=i.forwardRef(function(e,t){let r=(0,s.Z)({props:e,name:"MuiTable"}),{className:l,component:c=m,padding:p="normal",size:u="medium",stickyHeader:v=!1}=r,h=(0,a.Z)(r,Z),b=(0,o.Z)({},r,{component:c,padding:p,size:u,stickyHeader:v}),x=f(b),C=i.useMemo(()=>({padding:p,size:u,stickyHeader:v}),[p,u,v]);return(0,g.jsx)(d.Z.Provider,{value:C,children:(0,g.jsx)(y,(0,o.Z)({as:c,role:c===m?null:"table",ref:t,className:(0,n.Z)(x.root,l),ownerState:b},h))})});var b=h},21109:function(e,t,r){var a=r(67294);let o=a.createContext();t.Z=o},80858:function(e,t,r){var a=r(67294);let o=a.createContext();t.Z=o}}]); \ No newline at end of file diff --git a/out/_next/static/chunks/1167.4d7ff245a31cab4b.js b/out/_next/static/chunks/1167.4d7ff245a31cab4b.js new file mode 100644 index 0000000..ff92b5a --- /dev/null +++ b/out/_next/static/chunks/1167.4d7ff245a31cab4b.js @@ -0,0 +1 @@ +(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[1167],{18446:function(t,e,o){var n=o(90939);function i(t,e){return n(t,e)}t.exports=i},71167:function(t,e,o){"use strict";var n,i=this&&this.__extends||(n=function(t,e){return(n=Object.setPrototypeOf||({__proto__:[]})instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var o in e)e.hasOwnProperty(o)&&(t[o]=e[o])})(t,e)},function(t,e){function o(){this.constructor=t}n(t,e),t.prototype=null===e?Object.create(e):(o.prototype=e.prototype,new o)}),r=this&&this.__assign||function(){return(r=Object.assign||function(t){for(var e,o=1,n=arguments.length;o1)throw Error("The Quill editing area can only be composed of a single React element.");if(l.default.Children.count(t.children)&&(null===(e=l.default.Children.only(t.children))||void 0===e?void 0:e.type)==="textarea")throw Error("Quill does not support editing on a