Compare commits
215 Commits
Digital-ID
...
DID-14
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
200f4f58a7 | ||
|
|
86a6bf013d | ||
|
|
6afa08e5f5 | ||
|
|
3173ec9342 | ||
|
|
c8352e6537 | ||
|
|
9fbc6423d1 | ||
|
|
e4f691ab78 | ||
|
|
446276fadf | ||
|
|
1b574ac347 | ||
|
|
0c7db9cd30 | ||
|
|
fc977cc43a | ||
|
|
0a0151d1dd | ||
|
|
369f0e375c | ||
|
|
79ca03823c | ||
|
|
49f3ee17a0 | ||
|
|
841e82e233 | ||
|
|
2212ea7433 | ||
|
|
f257066d5a | ||
|
|
027bf0d405 | ||
|
|
663cfacf63 | ||
|
|
27ee899402 | ||
|
|
59dd4c9554 | ||
|
|
c659e17344 | ||
|
|
49d86ed74b | ||
|
|
b2d5df9533 | ||
|
|
0eea3d1ea3 | ||
|
|
9686e5245f | ||
|
|
1f306b2dce | ||
|
|
a86dd13e0e | ||
|
|
0e5d7477fc | ||
|
|
f395661480 | ||
|
|
4c334648cb | ||
|
|
344b2c7862 | ||
|
|
826f340e9a | ||
|
|
b4bccf2cba | ||
|
|
7bb1832d4d | ||
|
|
17ac1b04eb | ||
|
|
e4dc1e961e | ||
|
|
fa198054dd | ||
|
|
f31c895b8d | ||
|
|
b7be78cf76 | ||
|
|
6d92fde547 | ||
|
|
03bc841894 | ||
|
|
c24a1fa09d | ||
|
|
57e5dee442 | ||
|
|
188e79caf9 | ||
|
|
e9b21c5c02 | ||
|
|
75464d81f0 | ||
|
|
fcb7d40ca5 | ||
|
|
f27edb97bb | ||
|
|
b75a2349c2 | ||
|
|
37c9feffe1 | ||
|
|
fe6bcf8d0f | ||
|
|
d7488f8ca9 | ||
|
|
ffa92ded10 | ||
|
|
68e94201e0 | ||
|
|
020e45ddce | ||
|
|
8955d846e4 | ||
|
|
d5bc90c818 | ||
|
|
16a2ffca2d | ||
|
|
f932c0bc33 | ||
|
|
da268d7ecc | ||
|
|
736e8fc16b | ||
|
|
774955f131 | ||
|
|
5b20d71a0c | ||
|
|
9714b0add8 | ||
|
|
52eb2a75c1 | ||
|
|
3c77264fae | ||
|
|
429f36b6a6 | ||
|
|
11be69a79b | ||
|
|
911c13cb87 | ||
|
|
1e9830c8d4 | ||
|
|
a8a6355daa | ||
|
|
444c94690b | ||
|
|
67133c5414 | ||
|
|
f58a94bf24 | ||
|
|
9820692cd9 | ||
|
|
2eeb39abc9 | ||
|
|
5eb4ee16c0 | ||
|
|
bc364d1b85 | ||
|
|
8489bc375c | ||
|
|
b9f795c0e4 | ||
|
|
47dfcf347c | ||
|
|
e837f7cc89 | ||
|
|
7ad29e8fe0 | ||
|
|
0fb5764a70 | ||
|
|
5ebc965a2a | ||
|
|
138047fa10 | ||
|
|
a271da7bf9 | ||
|
|
79784cbcee | ||
|
|
596c44aac3 | ||
|
|
5d17137815 | ||
|
|
18bf373508 | ||
|
|
944c9989e9 | ||
|
|
202989f374 | ||
|
|
f21d10f830 | ||
|
|
c8604a56ac | ||
|
|
2d0ae35cc8 | ||
|
|
76f942b90f | ||
|
|
f0e0d9479d | ||
|
|
3403289e0a | ||
|
|
25fddec6e8 | ||
|
|
1d0cb45024 | ||
|
|
222850dfd9 | ||
|
|
8f225752cf | ||
|
|
038657751a | ||
|
|
29d7d6fdb8 | ||
|
|
e44dfee284 | ||
|
|
0f455f126d | ||
|
|
0d4f27660a | ||
|
|
9703371f28 | ||
|
|
16ca8a1df2 | ||
|
|
e883b190a7 | ||
|
|
85897a8efe | ||
|
|
5f85d1696a | ||
|
|
1c539e5255 | ||
|
|
bcfc018560 | ||
|
|
e175ca0295 | ||
|
|
bac246eac2 | ||
|
|
f65c99e86a | ||
|
|
63439b2da1 | ||
|
|
1d9368d200 | ||
|
|
3a4ed9daf9 | ||
|
|
54ccd3ed9f | ||
|
|
fe1105e9d6 | ||
|
|
95cc2ac1e0 | ||
|
|
b4516ef18e | ||
|
|
d617de75b5 | ||
|
|
83e5e39d3c | ||
|
|
f89d59e7df | ||
|
|
c944644db0 | ||
|
|
bfdddee46a | ||
|
|
0da68ddd63 | ||
|
|
f209ee5f5f | ||
|
|
9bef3d9311 | ||
|
|
632b98a81a | ||
|
|
eeaabeebf3 | ||
|
|
81f5ec2741 | ||
|
|
3fcda54070 | ||
|
|
49aff14a80 | ||
|
|
da04efbf80 | ||
|
|
541c5988e9 | ||
|
|
cfa5af78c0 | ||
|
|
fc4d9fb897 | ||
|
|
ed5565eb17 | ||
|
|
99512491fa | ||
|
|
24a66478d6 | ||
|
|
9484b0bda9 | ||
|
|
885963be45 | ||
|
|
e144e50a40 | ||
|
|
16f9a52a41 | ||
|
|
5e74f2bc0b | ||
|
|
fa5ddbf64a | ||
|
|
c45b7c5e4d | ||
|
|
606223216f | ||
|
|
c41bed05fd | ||
|
|
b71dccbd0e | ||
|
|
264a908352 | ||
|
|
36eb756be0 | ||
|
|
f74293b1f4 | ||
|
|
095c5e236e | ||
|
|
f3dcbdab49 | ||
|
|
3236f2ae94 | ||
|
|
0d127aa5fa | ||
|
|
ac18be77a7 | ||
|
|
568543bba5 | ||
|
|
3b62d188c1 | ||
|
|
de11c6be0f | ||
|
|
5b1ff31e01 | ||
|
|
03bb781b5a | ||
|
|
981d62b849 | ||
|
|
883f173c12 | ||
|
|
709f668697 | ||
|
|
3e5ef4f128 | ||
|
|
d86c118b21 | ||
|
|
4179cd703d | ||
|
|
20221b497b | ||
|
|
9bdbd396e8 | ||
|
|
c7d797b2af | ||
|
|
bc71ea6cb9 | ||
|
|
8dd57625fd | ||
|
|
ec700318ae | ||
|
|
bcd7f89dee | ||
|
|
0de76771ac | ||
|
|
3cd337d589 | ||
|
|
3f3a56c305 | ||
|
|
b40b59af3f | ||
|
|
b98c4db02d | ||
|
|
a5a046f911 | ||
|
|
d31a2f09d5 | ||
|
|
5fca3bdc4e | ||
|
|
e6142b1402 | ||
|
|
df6419bfff | ||
|
|
99d235f5e7 | ||
|
|
180961ec20 | ||
|
|
c4c7b10b99 | ||
|
|
79bed4e69d | ||
|
|
56e2691af5 | ||
|
|
13136d2712 | ||
|
|
5f1e8c55ff | ||
|
|
b4ad092228 | ||
|
|
13839cf67c | ||
|
|
fbafb94b2b | ||
|
|
60194da89b | ||
|
|
6580c211ff | ||
|
|
c44516a2f7 | ||
|
|
1ab53990a1 | ||
|
|
7ff6d08fc8 | ||
|
|
4bdaa28fff | ||
|
|
59d96222d6 | ||
|
|
3730bbee86 | ||
|
|
fa3ee41fbd | ||
|
|
b85163cda8 | ||
|
|
234c68ec53 | ||
|
|
6d47aa7411 |
64
.github/workflows/docker-image.yml
vendored
Normal file
64
.github/workflows/docker-image.yml
vendored
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
name: Build and deploy
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'master'
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
paths-ignore:
|
||||||
|
- '.github/**'
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- 'master'
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
paths-ignore:
|
||||||
|
- '.github/**'
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
logLevel:
|
||||||
|
description: 'Log level'
|
||||||
|
required: true
|
||||||
|
default: 'warning'
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- info
|
||||||
|
- warning
|
||||||
|
- debug
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: self-hosted
|
||||||
|
steps:
|
||||||
|
- name: Get branch data
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v1
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build and push image
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
with:
|
||||||
|
push: true
|
||||||
|
tags: kandrusyak/blockchain-ui:master
|
||||||
|
deploy:
|
||||||
|
needs: build
|
||||||
|
name: Deploy to host
|
||||||
|
runs-on: self-hosted
|
||||||
|
steps:
|
||||||
|
- name: Get branch data
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Deploying changes
|
||||||
|
uses: appleboy/ssh-action@master
|
||||||
|
with:
|
||||||
|
host: ${{ secrets.SSH_HOST }}
|
||||||
|
username: ${{ secrets.SSH_USERNAME }}
|
||||||
|
password: ${{ secrets.SSH_PASSWORD }}
|
||||||
|
script: |
|
||||||
|
docker login -u ${{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
./update.sh
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
# dependencies
|
# dependencies
|
||||||
/node_modules
|
/node_modules
|
||||||
|
.idea
|
||||||
17
Dockerfile
Normal file
17
Dockerfile
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
FROM node:16-alpine AS builder
|
||||||
|
|
||||||
|
RUN apk --update add --no-cache curl git python3 alpine-sdk bash autoconf libtool automake
|
||||||
|
|
||||||
|
WORKDIR /front
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN npm install
|
||||||
|
RUN npm run build:prod
|
||||||
|
|
||||||
|
FROM nginx:1.21.6-alpine as runner
|
||||||
|
|
||||||
|
COPY ./deploy/nginx.conf /etc/nginx/nginx.conf
|
||||||
|
COPY --from=builder /front/build /var/www/html
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
26
README.md
26
README.md
@@ -1,26 +0,0 @@
|
|||||||
# Mosaic React
|
|
||||||
|
|
||||||
React landing page template designed by Cruip.
|
|
||||||
|
|
||||||
## Project setup
|
|
||||||
```
|
|
||||||
npm install
|
|
||||||
```
|
|
||||||
|
|
||||||
### Compiles and hot-reloads for development
|
|
||||||
```
|
|
||||||
npm run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
### Compiles and minifies for production
|
|
||||||
```
|
|
||||||
npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
### Customize configuration
|
|
||||||
See [Configuration Reference](https://vitejs.dev/guide/).
|
|
||||||
|
|
||||||
## Support notes
|
|
||||||
We are shipping our templates with a very basic React configuration to let you quickly get into the development process, but we don't discourage you from using any other configuration or framework built on the top of React. So, please note that any request dealing with React (e.g. extra features, customisations, et cetera) is to be considered out of the support scope.
|
|
||||||
|
|
||||||
For more information about what support covers, please see our (FAQs)[https://cruip.com/faq/].
|
|
||||||
33
deploy/nginx.conf
Normal file
33
deploy/nginx.conf
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
worker_processes 1;
|
||||||
|
error_log /var/log/nginx/error.log warn;
|
||||||
|
pid /var/run/nginx.pid;
|
||||||
|
events {
|
||||||
|
worker_connections 1024;
|
||||||
|
}
|
||||||
|
http {
|
||||||
|
include mime.types;
|
||||||
|
default_type application/octet-stream;
|
||||||
|
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||||
|
'$status $body_bytes_sent "$http_referer" '
|
||||||
|
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||||
|
access_log /var/log/nginx/access.log main;
|
||||||
|
sendfile on;
|
||||||
|
keepalive_timeout 65;
|
||||||
|
gzip_static on;
|
||||||
|
server {
|
||||||
|
listen 8080;
|
||||||
|
server_name localhost;
|
||||||
|
charset utf-8;
|
||||||
|
location / {
|
||||||
|
root /var/www/html;
|
||||||
|
try_files $uri /index.html;
|
||||||
|
etag on;
|
||||||
|
expires max;
|
||||||
|
add_header Cache-Control public;
|
||||||
|
location = /index.html {
|
||||||
|
expires 0;
|
||||||
|
add_header Cache-Control "no-cache, public, must-revalidate, proxy-revalidate";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
index.html
21
index.html
@@ -1,21 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<title>Vite App</title>
|
|
||||||
</head>
|
|
||||||
<body class="font-inter antialiased bg-slate-100 text-slate-600">
|
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
||||||
<script>
|
|
||||||
if (localStorage.getItem('sidebar-expanded') == 'true') {
|
|
||||||
document.querySelector('body').classList.add('sidebar-expanded');
|
|
||||||
} else {
|
|
||||||
document.querySelector('body').classList.remove('sidebar-expanded');
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<div id="root"></div>
|
|
||||||
<script type="module" src="/src/main.jsx"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
13790
package-lock.json
generated
13790
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
51
package.json
51
package.json
@@ -2,27 +2,62 @@
|
|||||||
"name": "mosaic-react",
|
"name": "mosaic-react",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "webpack-dev-server --https",
|
||||||
"build": "vite build",
|
"build:dev": "webpack --mode development --progress",
|
||||||
"preview": "vite preview"
|
"build:prod": "webpack --mode production --progress"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@liskhq/lisk-client": "^5.2.2",
|
||||||
"@tailwindcss/forms": "^0.4.0",
|
"@tailwindcss/forms": "^0.4.0",
|
||||||
|
"buffer": "^6.0.3",
|
||||||
"chart.js": "^3.5.0",
|
"chart.js": "^3.5.0",
|
||||||
"chartjs-adapter-moment": "^1.0.0",
|
"chartjs-adapter-moment": "^1.0.0",
|
||||||
|
"crypto-browserify": "^3.12.0",
|
||||||
|
"mobx": "^6.6.0",
|
||||||
|
"mobx-react-lite": "^3.4.0",
|
||||||
"moment": "^2.29.1",
|
"moment": "^2.29.1",
|
||||||
|
"net": "^1.0.2",
|
||||||
|
"os-browserify": "^0.3.0",
|
||||||
|
"path-browserify": "^1.0.1",
|
||||||
|
"process": "^0.11.10",
|
||||||
|
"querystring-es3": "^0.2.1",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-flatpickr": "^3.10.7",
|
"react-flatpickr": "^3.10.7",
|
||||||
|
"react-loader-spinner": "^5.2.0",
|
||||||
"react-router-dom": "^6.2.1",
|
"react-router-dom": "^6.2.1",
|
||||||
"react-transition-group": "^4.4.1"
|
"react-transition-group": "^4.4.1",
|
||||||
|
"stream-browserify": "^3.0.0",
|
||||||
|
"url": "^0.11.0",
|
||||||
|
"util": "^0.12.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-react": "^1.0.7",
|
"@babel/core": "^7.18.5",
|
||||||
"autoprefixer": "^10.4.2",
|
"@babel/preset-env": "^7.18.2",
|
||||||
|
"@babel/preset-react": "^7.17.12",
|
||||||
|
"autoprefixer": "^10.4.5",
|
||||||
|
"babel-loader": "^8.2.5",
|
||||||
|
"css-loader": "^6.7.1",
|
||||||
|
"file-loader": "^6.2.0",
|
||||||
|
"html-loader": "^3.1.2",
|
||||||
|
"html-webpack-plugin": "^5.5.0",
|
||||||
"postcss": "^8.4.5",
|
"postcss": "^8.4.5",
|
||||||
"sass": "^1.49.0",
|
"postcss-loader": "^7.0.0",
|
||||||
|
"sass": "^1.52.3",
|
||||||
|
"sass-loader": "^13.0.0",
|
||||||
|
"style-loader": "^3.3.1",
|
||||||
"tailwindcss": "^3.0.18",
|
"tailwindcss": "^3.0.18",
|
||||||
"vite": "^2.7.2"
|
"webpack": "^5.73.0",
|
||||||
|
"webpack-cli": "^4.10.0",
|
||||||
|
"webpack-dev-server": "^4.9.2"
|
||||||
|
},
|
||||||
|
"babel": {
|
||||||
|
"presets": [
|
||||||
|
"@babel/env",
|
||||||
|
"@babel/react"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"browser": {
|
||||||
|
"fs": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import tailwind from 'tailwindcss'
|
const tailwind = require('tailwindcss')
|
||||||
import autoprefixer from 'autoprefixer'
|
const autoprefixer = require('autoprefixer')
|
||||||
import tailwindConfig from './src/css/tailwind.config.js'
|
const tailwindConfig = require('./src/tailwind.config.js')
|
||||||
|
|
||||||
export default {
|
module.exports = {
|
||||||
plugins: [tailwind(tailwindConfig), autoprefixer],
|
plugins: [tailwind(tailwindConfig), autoprefixer],
|
||||||
}
|
}
|
||||||
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
11
public/index.html
Normal file
11
public/index.html
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>React App</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
158
src/App.jsx
158
src/App.jsx
@@ -2,87 +2,33 @@ import React, { useEffect } from 'react';
|
|||||||
import {
|
import {
|
||||||
Routes,
|
Routes,
|
||||||
Route,
|
Route,
|
||||||
useLocation
|
useLocation,
|
||||||
} from 'react-router-dom';
|
} from 'react-router-dom';
|
||||||
|
|
||||||
import './css/style.scss';
|
import './css/style.scss';
|
||||||
|
|
||||||
import './charts/ChartjsConfig';
|
|
||||||
|
|
||||||
// Import pages
|
// Import pages
|
||||||
import Dashboard from './pages/Dashboard';
|
|
||||||
import Analytics from './pages/Analytics';
|
|
||||||
import Fintech from './pages/Fintech';
|
|
||||||
import ProfileId from './pages/digitalId/ProfileId';
|
import ProfileId from './pages/digitalId/ProfileId';
|
||||||
import Validate from './pages/digitalId/Validate';
|
import Validate from './pages/digitalId/Validate';
|
||||||
import ValidationLog from './pages/digitalId/ValidationLog';
|
import ValidationLog from './pages/digitalId/ValidationLog';
|
||||||
import Verify from './pages/digitalId/Verify';
|
import Verify from './pages/digitalId/Verify';
|
||||||
import Customers from './pages/ecommerce/Customers';
|
import Onboarding1 from "./pages/Onboarding1";
|
||||||
import Orders from './pages/ecommerce/Orders';
|
import Onboarding2 from "./pages/Onboarding2";
|
||||||
import Invoices from './pages/ecommerce/Invoices';
|
import Onboarding3 from "./pages/Onboarding3";
|
||||||
import Shop from './pages/ecommerce/Shop';
|
import Onboarding4 from "./pages/Onboarding4";
|
||||||
import Shop2 from './pages/ecommerce/Shop2';
|
import SharedData from "./pages/SharedData";
|
||||||
import Product from './pages/ecommerce/Product';
|
import ResetPassword from "./pages/ResetPassword";
|
||||||
import Cart from './pages/ecommerce/Cart';
|
import SignIn from "./pages/SignIn";
|
||||||
import Cart2 from './pages/ecommerce/Cart2';
|
import {LoadingOverlay} from './components/LoadingOverlay';
|
||||||
import Cart3 from './pages/ecommerce/Cart3';
|
import {store} from './store/store';
|
||||||
import Pay from './pages/ecommerce/Pay';
|
import {observer} from 'mobx-react-lite';
|
||||||
import Campaigns from './pages/Campaigns';
|
|
||||||
import UsersTabs from './pages/community/UsersTabs';
|
|
||||||
import UsersTiles from './pages/community/UsersTiles';
|
|
||||||
import Profile from './pages/community/Profile';
|
|
||||||
import Feed from './pages/community/Feed';
|
|
||||||
import Forum from './pages/community/Forum';
|
|
||||||
import ForumPost from './pages/community/ForumPost';
|
|
||||||
import Meetups from './pages/community/Meetups';
|
|
||||||
import MeetupsPost from './pages/community/MeetupsPost';
|
|
||||||
import CreditCards from './pages/finance/CreditCards';
|
|
||||||
import Transactions from './pages/finance/Transactions';
|
|
||||||
import TransactionDetails from './pages/finance/TransactionDetails';
|
|
||||||
import JobListing from './pages/job/JobListing';
|
|
||||||
import JobPost from './pages/job/JobPost';
|
|
||||||
import CompanyProfile from './pages/job/CompanyProfile';
|
|
||||||
import Messages from './pages/Messages';
|
|
||||||
import TasksKanban from './pages/tasks/TasksKanban';
|
|
||||||
import TasksList from './pages/tasks/TasksList';
|
|
||||||
import Inbox from './pages/Inbox';
|
|
||||||
import Calendar from './pages/Calendar';
|
|
||||||
import Account from './pages/settings/Account';
|
|
||||||
import Notifications from './pages/settings/Notifications';
|
|
||||||
import Apps from './pages/settings/Apps';
|
|
||||||
import Plans from './pages/settings/Plans';
|
|
||||||
import Billing from './pages/settings/Billing';
|
|
||||||
import Feedback from './pages/settings/Feedback';
|
|
||||||
import Changelog from './pages/utility/Changelog';
|
|
||||||
import Roadmap from './pages/utility/Roadmap';
|
|
||||||
import Faqs from './pages/utility/Faqs';
|
|
||||||
import EmptyState from './pages/utility/EmptyState';
|
|
||||||
import PageNotFound from './pages/utility/PageNotFound';
|
|
||||||
import KnowledgeBase from './pages/utility/KnowledgeBase';
|
|
||||||
import Signin from './pages/Signin';
|
|
||||||
import Signup from './pages/Signup';
|
|
||||||
import ResetPassword from './pages/ResetPassword';
|
|
||||||
import Onboarding01 from './pages/Onboarding01';
|
|
||||||
import Onboarding02 from './pages/Onboarding02';
|
|
||||||
import Onboarding03 from './pages/Onboarding03';
|
|
||||||
import Onboarding04 from './pages/Onboarding04';
|
|
||||||
import ButtonPage from './pages/component/ButtonPage';
|
|
||||||
import FormPage from './pages/component/FormPage';
|
|
||||||
import DropdownPage from './pages/component/DropdownPage';
|
|
||||||
import AlertPage from './pages/component/AlertPage';
|
|
||||||
import ModalPage from './pages/component/ModalPage';
|
|
||||||
import PaginationPage from './pages/component/PaginationPage';
|
|
||||||
import TabsPage from './pages/component/TabsPage';
|
|
||||||
import BreadcrumbPage from './pages/component/BreadcrumbPage';
|
|
||||||
import BadgePage from './pages/component/BadgePage';
|
|
||||||
import AvatarPage from './pages/component/AvatarPage';
|
|
||||||
import TooltipPage from './pages/component/TooltipPage';
|
|
||||||
import AccordionPage from './pages/component/AccordionPage';
|
|
||||||
import IconsPage from './pages/component/IconsPage';
|
|
||||||
|
|
||||||
function App() {
|
const App = observer(() => {
|
||||||
|
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
useEffect(()=> {
|
||||||
|
localStorage.setItem('svgAvatar', '')
|
||||||
|
},[])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.querySelector('html').style.scrollBehavior = 'auto'
|
document.querySelector('html').style.scrollBehavior = 'auto'
|
||||||
@@ -92,80 +38,22 @@ function App() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{ store.loading && <LoadingOverlay /> }
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route exact path="/" element={<Dashboard />} />
|
<Route exact path="/" element={<Onboarding1 />} />
|
||||||
<Route path="/dashboard/analytics" element={<Analytics />} />
|
|
||||||
<Route path="/dashboard/fintech" element={<Fintech />} />
|
|
||||||
<Route path="/digitalId/profile-id" element={<ProfileId />} />
|
<Route path="/digitalId/profile-id" element={<ProfileId />} />
|
||||||
<Route path="/digitalId/validate" element={<Validate />} />
|
<Route path="/digitalId/validate" element={<Validate />} />
|
||||||
<Route path="/digitalId/validation-log" element={<ValidationLog />} />
|
<Route path="/digitalId/validation-log" element={<ValidationLog />} />
|
||||||
<Route path="/digitalId/verify" element={<Verify />} />
|
<Route path="/digitalId/verify" element={<Verify />} />
|
||||||
<Route path="/ecommerce/customers" element={<Customers />} />
|
<Route path="/onboarding-2" element={<Onboarding2 />} />
|
||||||
<Route path="/ecommerce/orders" element={<Orders />} />
|
<Route path="/onboarding-3" element={<Onboarding3 />} />
|
||||||
<Route path="/ecommerce/invoices" element={<Invoices />} />
|
<Route path="/onboarding-4" element={<Onboarding4 />} />
|
||||||
<Route path="/ecommerce/shop" element={<Shop />} />
|
<Route path="/shared-data" element={<SharedData />} />
|
||||||
<Route path="/ecommerce/shop-2" element={<Shop2 />} />
|
|
||||||
<Route path="/ecommerce/product" element={<Product />} />
|
|
||||||
<Route path="/ecommerce/cart" element={<Cart />} />
|
|
||||||
<Route path="/ecommerce/cart-2" element={<Cart2 />} />
|
|
||||||
<Route path="/ecommerce/cart-3" element={<Cart3 />} />
|
|
||||||
<Route path="/ecommerce/pay" element={<Pay />} />
|
|
||||||
<Route path="/campaigns" element={<Campaigns />} />
|
|
||||||
<Route path="/community/users-tabs" element={<UsersTabs />} />
|
|
||||||
<Route path="/community/users-tiles" element={<UsersTiles />} />
|
|
||||||
<Route path="/community/profile" element={<Profile />} />
|
|
||||||
<Route path="/community/feed" element={<Feed />} />
|
|
||||||
<Route path="/community/forum" element={<Forum />} />
|
|
||||||
<Route path="/community/forum-post" element={<ForumPost />} />
|
|
||||||
<Route path="/community/meetups" element={<Meetups />} />
|
|
||||||
<Route path="/community/meetups-post" element={<MeetupsPost />} />
|
|
||||||
<Route path="/finance/cards" element={<CreditCards />} />
|
|
||||||
<Route path="/finance/transactions" element={<Transactions />} />
|
|
||||||
<Route path="/finance/transaction-details" element={<TransactionDetails />} />
|
|
||||||
<Route path="/job/job-listing" element={<JobListing />} />
|
|
||||||
<Route path="/job/job-post" element={<JobPost />} />
|
|
||||||
<Route path="/job/company-profile" element={<CompanyProfile />} />
|
|
||||||
<Route path="/messages" element={<Messages />} />
|
|
||||||
<Route path="/tasks/kanban" element={<TasksKanban />} />
|
|
||||||
<Route path="/tasks/list" element={<TasksList />} />
|
|
||||||
<Route path="/inbox" element={<Inbox />} />
|
|
||||||
<Route path="/calendar" element={<Calendar />} />
|
|
||||||
<Route path="/settings/account" element={<Account />} />
|
|
||||||
<Route path="/settings/notifications" element={<Notifications />} />
|
|
||||||
<Route path="/settings/apps" element={<Apps />} />
|
|
||||||
<Route path="/settings/plans" element={<Plans />} />
|
|
||||||
<Route path="/settings/billing" element={<Billing />} />
|
|
||||||
<Route path="/settings/feedback" element={<Feedback />} />
|
|
||||||
<Route path="/utility/changelog" element={<Changelog />} />
|
|
||||||
<Route path="/utility/roadmap" element={<Roadmap />} />
|
|
||||||
<Route path="/utility/faqs" element={<Faqs />} />
|
|
||||||
<Route path="/utility/empty-state" element={<EmptyState />} />
|
|
||||||
<Route path="/utility/404" element={<PageNotFound />} />
|
|
||||||
<Route path="/utility/knowledge-base" element={<KnowledgeBase />} />
|
|
||||||
<Route path="/signin" element={<Signin />} />
|
|
||||||
<Route path="/signup" element={<Signup />} />
|
|
||||||
<Route path="/reset-password" element={<ResetPassword />} />
|
<Route path="/reset-password" element={<ResetPassword />} />
|
||||||
<Route path="/onboarding-01" element={<Onboarding01 />} />
|
<Route path="/signIn" element={<SignIn />} />
|
||||||
<Route path="/onboarding-02" element={<Onboarding02 />} />
|
|
||||||
<Route path="/onboarding-03" element={<Onboarding03 />} />
|
|
||||||
<Route path="/onboarding-04" element={<Onboarding04 />} />
|
|
||||||
<Route path="/component/button" element={<ButtonPage />} />
|
|
||||||
<Route path="/component/form" element={<FormPage />} />
|
|
||||||
<Route path="/component/dropdown" element={<DropdownPage />} />
|
|
||||||
<Route path="/component/alert" element={<AlertPage />} />
|
|
||||||
<Route path="/component/modal" element={<ModalPage />} />
|
|
||||||
<Route path="/component/pagination" element={<PaginationPage />} />
|
|
||||||
<Route path="/component/tabs" element={<TabsPage />} />
|
|
||||||
<Route path="/component/breadcrumb" element={<BreadcrumbPage />} />
|
|
||||||
<Route path="/component/badge" element={<BadgePage />} />
|
|
||||||
<Route path="/component/avatar" element={<AvatarPage />} />
|
|
||||||
<Route path="/component/tooltip" element={<TooltipPage />} />
|
|
||||||
<Route path="/component/accordion" element={<AccordionPage />} />
|
|
||||||
<Route path="/component/icons" element={<IconsPage />} />
|
|
||||||
<Route path="*" element={<PageNotFound />} />
|
|
||||||
</Routes>
|
</Routes>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
})
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|||||||
3
src/api/node.js
Normal file
3
src/api/node.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import {fetchWrapper} from '../shared/fetchWrapper';
|
||||||
|
|
||||||
|
export const getNodeInfo = (headers) => fetchWrapper.get('node/info/', headers)
|
||||||
@@ -1,162 +0,0 @@
|
|||||||
import React, { useRef, useEffect } from 'react';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Chart, BarController, BarElement, LinearScale, TimeScale, Tooltip, Legend,
|
|
||||||
} from 'chart.js';
|
|
||||||
import 'chartjs-adapter-moment';
|
|
||||||
|
|
||||||
// Import utilities
|
|
||||||
import { tailwindConfig, formatValue } from '../utils/Utils';
|
|
||||||
|
|
||||||
Chart.register(BarController, BarElement, LinearScale, TimeScale, Tooltip, Legend);
|
|
||||||
|
|
||||||
function BarChart01({
|
|
||||||
data,
|
|
||||||
width,
|
|
||||||
height
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const canvas = useRef(null);
|
|
||||||
const legend = useRef(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const ctx = canvas.current;
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const chart = new Chart(ctx, {
|
|
||||||
type: 'bar',
|
|
||||||
data: data,
|
|
||||||
options: {
|
|
||||||
layout: {
|
|
||||||
padding: {
|
|
||||||
top: 12,
|
|
||||||
bottom: 16,
|
|
||||||
left: 20,
|
|
||||||
right: 20,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
grid: {
|
|
||||||
drawBorder: false,
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
maxTicksLimit: 5,
|
|
||||||
callback: (value) => formatValue(value),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
x: {
|
|
||||||
type: 'time',
|
|
||||||
time: {
|
|
||||||
parser: 'MM-DD-YYYY',
|
|
||||||
unit: 'month',
|
|
||||||
displayFormats: {
|
|
||||||
month: 'MMM YY',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
display: false,
|
|
||||||
drawBorder: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
legend: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
callbacks: {
|
|
||||||
title: () => false, // Disable tooltip title
|
|
||||||
label: (context) => formatValue(context.parsed.y),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
interaction: {
|
|
||||||
intersect: false,
|
|
||||||
mode: 'nearest',
|
|
||||||
},
|
|
||||||
animation: {
|
|
||||||
duration: 500,
|
|
||||||
},
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
resizeDelay: 200,
|
|
||||||
},
|
|
||||||
plugins: [{
|
|
||||||
id: 'htmlLegend',
|
|
||||||
afterUpdate(c, args, options) {
|
|
||||||
const ul = legend.current;
|
|
||||||
if (!ul) return;
|
|
||||||
// Remove old legend items
|
|
||||||
while (ul.firstChild) {
|
|
||||||
ul.firstChild.remove();
|
|
||||||
}
|
|
||||||
// Reuse the built-in legendItems generator
|
|
||||||
const items = c.options.plugins.legend.labels.generateLabels(c);
|
|
||||||
items.forEach((item) => {
|
|
||||||
const li = document.createElement('li');
|
|
||||||
li.style.marginRight = tailwindConfig().theme.margin[4];
|
|
||||||
// Button element
|
|
||||||
const button = document.createElement('button');
|
|
||||||
button.style.display = 'inline-flex';
|
|
||||||
button.style.alignItems = 'center';
|
|
||||||
button.style.opacity = item.hidden ? '.3' : '';
|
|
||||||
button.onclick = () => {
|
|
||||||
c.setDatasetVisibility(item.datasetIndex, !c.isDatasetVisible(item.datasetIndex));
|
|
||||||
c.update();
|
|
||||||
};
|
|
||||||
// Color box
|
|
||||||
const box = document.createElement('span');
|
|
||||||
box.style.display = 'block';
|
|
||||||
box.style.width = tailwindConfig().theme.width[3];
|
|
||||||
box.style.height = tailwindConfig().theme.height[3];
|
|
||||||
box.style.borderRadius = tailwindConfig().theme.borderRadius.full;
|
|
||||||
box.style.marginRight = tailwindConfig().theme.margin[2];
|
|
||||||
box.style.borderWidth = '3px';
|
|
||||||
box.style.borderColor = item.fillStyle;
|
|
||||||
box.style.pointerEvents = 'none';
|
|
||||||
// Label
|
|
||||||
const labelContainer = document.createElement('span');
|
|
||||||
labelContainer.style.display = 'flex';
|
|
||||||
labelContainer.style.alignItems = 'center';
|
|
||||||
const value = document.createElement('span');
|
|
||||||
value.style.color = tailwindConfig().theme.colors.slate[800];
|
|
||||||
value.style.fontSize = tailwindConfig().theme.fontSize['3xl'][0];
|
|
||||||
value.style.lineHeight = tailwindConfig().theme.fontSize['3xl'][1].lineHeight;
|
|
||||||
value.style.fontWeight = tailwindConfig().theme.fontWeight.bold;
|
|
||||||
value.style.marginRight = tailwindConfig().theme.margin[2];
|
|
||||||
value.style.pointerEvents = 'none';
|
|
||||||
const label = document.createElement('span');
|
|
||||||
label.style.color = tailwindConfig().theme.colors.slate[500];
|
|
||||||
label.style.fontSize = tailwindConfig().theme.fontSize.sm[0];
|
|
||||||
label.style.lineHeight = tailwindConfig().theme.fontSize.sm[1].lineHeight;
|
|
||||||
const theValue = c.data.datasets[item.datasetIndex].data.reduce((a, b) => a + b, 0);
|
|
||||||
const valueText = document.createTextNode(formatValue(theValue));
|
|
||||||
const labelText = document.createTextNode(item.text);
|
|
||||||
value.appendChild(valueText);
|
|
||||||
label.appendChild(labelText);
|
|
||||||
li.appendChild(button);
|
|
||||||
button.appendChild(box);
|
|
||||||
button.appendChild(labelContainer);
|
|
||||||
labelContainer.appendChild(value);
|
|
||||||
labelContainer.appendChild(label);
|
|
||||||
ul.appendChild(li);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
});
|
|
||||||
return () => chart.destroy();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<React.Fragment>
|
|
||||||
<div className="px-5 py-3">
|
|
||||||
<ul ref={legend} className="flex flex-wrap"></ul>
|
|
||||||
</div>
|
|
||||||
<div className="grow">
|
|
||||||
<canvas ref={canvas} width={width} height={height}></canvas>
|
|
||||||
</div>
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default BarChart01;
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
import React, { useRef, useEffect } from 'react';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Chart, BarController, BarElement, LinearScale, TimeScale, Tooltip, Legend,
|
|
||||||
} from 'chart.js';
|
|
||||||
import 'chartjs-adapter-moment';
|
|
||||||
|
|
||||||
// Import utilities
|
|
||||||
import { formatValue } from '../utils/Utils';
|
|
||||||
|
|
||||||
Chart.register(BarController, BarElement, LinearScale, TimeScale, Tooltip, Legend);
|
|
||||||
|
|
||||||
function BarChart02({
|
|
||||||
data,
|
|
||||||
width,
|
|
||||||
height
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const canvas = useRef(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const ctx = canvas.current;
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const chart = new Chart(ctx, {
|
|
||||||
type: 'bar',
|
|
||||||
data: data,
|
|
||||||
options: {
|
|
||||||
layout: {
|
|
||||||
padding: {
|
|
||||||
top: 12,
|
|
||||||
bottom: 16,
|
|
||||||
left: 20,
|
|
||||||
right: 20,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
stacked: true,
|
|
||||||
grid: {
|
|
||||||
drawBorder: false,
|
|
||||||
},
|
|
||||||
beginAtZero: true,
|
|
||||||
ticks: {
|
|
||||||
maxTicksLimit: 5,
|
|
||||||
callback: (value) => formatValue(value),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
x: {
|
|
||||||
stacked: true,
|
|
||||||
type: 'time',
|
|
||||||
time: {
|
|
||||||
parser: 'MM-DD-YYYY',
|
|
||||||
unit: 'month',
|
|
||||||
displayFormats: {
|
|
||||||
month: 'MMM YY',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
display: false,
|
|
||||||
drawBorder: false,
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
autoSkipPadding: 48,
|
|
||||||
maxRotation: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
legend: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
callbacks: {
|
|
||||||
title: () => false, // Disable tooltip title
|
|
||||||
label: (context) => formatValue(context.parsed.y),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
interaction: {
|
|
||||||
intersect: false,
|
|
||||||
mode: 'nearest',
|
|
||||||
},
|
|
||||||
animation: {
|
|
||||||
duration: 200,
|
|
||||||
},
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
resizeDelay: 200,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return () => chart.destroy();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<canvas ref={canvas} width={width} height={height}></canvas>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default BarChart02;
|
|
||||||
@@ -1,156 +0,0 @@
|
|||||||
import React, { useRef, useEffect } from 'react';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Chart, BarController, BarElement, LinearScale, TimeScale, Tooltip, Legend,
|
|
||||||
} from 'chart.js';
|
|
||||||
import 'chartjs-adapter-moment';
|
|
||||||
|
|
||||||
// Import utilities
|
|
||||||
import { tailwindConfig, formatThousands } from '../utils/Utils';
|
|
||||||
|
|
||||||
Chart.register(BarController, BarElement, LinearScale, TimeScale, Tooltip, Legend);
|
|
||||||
|
|
||||||
function BarChart03({
|
|
||||||
data,
|
|
||||||
width,
|
|
||||||
height
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const canvas = useRef(null);
|
|
||||||
const legend = useRef(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const ctx = canvas.current;
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const chart = new Chart(ctx, {
|
|
||||||
type: 'bar',
|
|
||||||
data: data,
|
|
||||||
options: {
|
|
||||||
layout: {
|
|
||||||
padding: {
|
|
||||||
top: 12,
|
|
||||||
bottom: 16,
|
|
||||||
left: 20,
|
|
||||||
right: 20,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
stacked: true,
|
|
||||||
grid: {
|
|
||||||
drawBorder: false,
|
|
||||||
},
|
|
||||||
beginAtZero: true,
|
|
||||||
ticks: {
|
|
||||||
maxTicksLimit: 5,
|
|
||||||
callback: (value) => formatThousands(value),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
x: {
|
|
||||||
stacked: true,
|
|
||||||
type: 'time',
|
|
||||||
time: {
|
|
||||||
parser: 'MM-DD-YYYY',
|
|
||||||
unit: 'month',
|
|
||||||
displayFormats: {
|
|
||||||
month: 'MMM',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
display: false,
|
|
||||||
drawBorder: false,
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
autoSkipPadding: 48,
|
|
||||||
maxRotation: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
legend: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
callbacks: {
|
|
||||||
title: () => false, // Disable tooltip title
|
|
||||||
label: (context) => formatThousands(context.parsed.y),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
interaction: {
|
|
||||||
intersect: false,
|
|
||||||
mode: 'nearest',
|
|
||||||
},
|
|
||||||
animation: {
|
|
||||||
duration: 500,
|
|
||||||
},
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
resizeDelay: 200,
|
|
||||||
},
|
|
||||||
plugins: [{
|
|
||||||
id: 'htmlLegend',
|
|
||||||
afterUpdate(c, args, options) {
|
|
||||||
const ul = legend.current
|
|
||||||
if (!ul) return
|
|
||||||
// Remove old legend items
|
|
||||||
while (ul.firstChild) {
|
|
||||||
ul.firstChild.remove()
|
|
||||||
}
|
|
||||||
// Reuse the built-in legendItems generator
|
|
||||||
const items = c.options.plugins.legend.labels.generateLabels(c)
|
|
||||||
items.forEach((item) => {
|
|
||||||
const li = document.createElement('li')
|
|
||||||
li.style.marginRight = tailwindConfig().theme.margin[3];
|
|
||||||
// Button element
|
|
||||||
const button = document.createElement('button')
|
|
||||||
button.style.display = 'inline-flex';
|
|
||||||
button.style.alignItems = 'center';
|
|
||||||
button.style.opacity = item.hidden ? '.3' : '';
|
|
||||||
button.onclick = () => {
|
|
||||||
c.setDatasetVisibility(item.datasetIndex, !c.isDatasetVisible(item.datasetIndex))
|
|
||||||
c.update()
|
|
||||||
};
|
|
||||||
// Color box
|
|
||||||
const box = document.createElement('span')
|
|
||||||
box.style.display = 'block';
|
|
||||||
box.style.width = tailwindConfig().theme.width[3];
|
|
||||||
box.style.height = tailwindConfig().theme.height[3];
|
|
||||||
box.style.borderRadius = tailwindConfig().theme.borderRadius.full;
|
|
||||||
box.style.marginRight = tailwindConfig().theme.margin[2];
|
|
||||||
box.style.borderWidth = '3px';
|
|
||||||
box.style.borderColor = item.fillStyle;
|
|
||||||
box.style.pointerEvents = 'none';
|
|
||||||
// Label
|
|
||||||
const label = document.createElement('span')
|
|
||||||
label.style.color = tailwindConfig().theme.colors.slate[500];
|
|
||||||
label.style.fontSize = tailwindConfig().theme.fontSize.sm[0];
|
|
||||||
label.style.lineHeight = tailwindConfig().theme.fontSize.sm[1].lineHeight;
|
|
||||||
const labelText = document.createTextNode(item.text)
|
|
||||||
label.appendChild(labelText)
|
|
||||||
li.appendChild(button)
|
|
||||||
button.appendChild(box)
|
|
||||||
button.appendChild(label)
|
|
||||||
ul.appendChild(li)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
});
|
|
||||||
return () => chart.destroy();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<React.Fragment>
|
|
||||||
<div className="px-5 py-4">
|
|
||||||
<div className="grow mb-1">
|
|
||||||
<ul ref={legend} className="flex flex-wrap"></ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="grow">
|
|
||||||
<canvas ref={canvas} width={width} height={height}></canvas>
|
|
||||||
</div>
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default BarChart03;
|
|
||||||
@@ -1,149 +0,0 @@
|
|||||||
import React, { useRef, useEffect } from 'react';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Chart, BarController, BarElement, LinearScale, TimeScale, Tooltip, Legend,
|
|
||||||
} from 'chart.js';
|
|
||||||
import 'chartjs-adapter-moment';
|
|
||||||
|
|
||||||
// Import utilities
|
|
||||||
import { tailwindConfig, formatThousands } from '../utils/Utils';
|
|
||||||
|
|
||||||
Chart.register(BarController, BarElement, LinearScale, TimeScale, Tooltip, Legend);
|
|
||||||
|
|
||||||
function BarChart04({
|
|
||||||
data,
|
|
||||||
width,
|
|
||||||
height
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const canvas = useRef(null);
|
|
||||||
const legend = useRef(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const ctx = canvas.current;
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const chart = new Chart(ctx, {
|
|
||||||
type: 'bar',
|
|
||||||
data: data,
|
|
||||||
options: {
|
|
||||||
indexAxis: 'y',
|
|
||||||
layout: {
|
|
||||||
padding: {
|
|
||||||
top: 12,
|
|
||||||
bottom: 16,
|
|
||||||
left: 20,
|
|
||||||
right: 20,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
type: 'time',
|
|
||||||
time: {
|
|
||||||
parser: 'MM-DD-YYYY',
|
|
||||||
unit: 'month',
|
|
||||||
displayFormats: {
|
|
||||||
month: 'MMM',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
display: false,
|
|
||||||
drawBorder: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
x: {
|
|
||||||
grid: {
|
|
||||||
drawBorder: false,
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
maxTicksLimit: 3,
|
|
||||||
align: 'end',
|
|
||||||
callback: (value) => formatThousands(value),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
legend: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
callbacks: {
|
|
||||||
title: () => false, // Disable tooltip title
|
|
||||||
label: (context) => formatThousands(context.parsed.x),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
interaction: {
|
|
||||||
intersect: false,
|
|
||||||
mode: 'nearest',
|
|
||||||
},
|
|
||||||
animation: {
|
|
||||||
duration: 500,
|
|
||||||
},
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
resizeDelay: 200,
|
|
||||||
},
|
|
||||||
plugins: [{
|
|
||||||
id: 'htmlLegend',
|
|
||||||
afterUpdate(c, args, options) {
|
|
||||||
const ul = legend.current
|
|
||||||
if (!ul) return
|
|
||||||
// Remove old legend items
|
|
||||||
while (ul.firstChild) {
|
|
||||||
ul.firstChild.remove()
|
|
||||||
}
|
|
||||||
// Reuse the built-in legendItems generator
|
|
||||||
const items = c.options.plugins.legend.labels.generateLabels(c)
|
|
||||||
items.forEach((item) => {
|
|
||||||
const li = document.createElement('li')
|
|
||||||
li.style.marginRight = tailwindConfig().theme.margin[4]
|
|
||||||
// Button element
|
|
||||||
const button = document.createElement('button')
|
|
||||||
button.style.display = 'inline-flex'
|
|
||||||
button.style.alignItems = 'center'
|
|
||||||
button.style.opacity = item.hidden ? '.3' : ''
|
|
||||||
button.onclick = () => {
|
|
||||||
c.setDatasetVisibility(item.datasetIndex, !c.isDatasetVisible(item.datasetIndex))
|
|
||||||
c.update()
|
|
||||||
}
|
|
||||||
// Color box
|
|
||||||
const box = document.createElement('span')
|
|
||||||
box.style.display = 'block'
|
|
||||||
box.style.width = tailwindConfig().theme.width[3]
|
|
||||||
box.style.height = tailwindConfig().theme.height[3]
|
|
||||||
box.style.borderRadius = tailwindConfig().theme.borderRadius.full
|
|
||||||
box.style.marginRight = tailwindConfig().theme.margin[2]
|
|
||||||
box.style.borderWidth = '3px'
|
|
||||||
box.style.borderColor = item.fillStyle
|
|
||||||
box.style.pointerEvents = 'none'
|
|
||||||
// Label
|
|
||||||
const label = document.createElement('span')
|
|
||||||
label.style.color = tailwindConfig().theme.colors.slate[500]
|
|
||||||
label.style.fontSize = tailwindConfig().theme.fontSize.sm[0]
|
|
||||||
label.style.lineHeight = tailwindConfig().theme.fontSize.sm[1].lineHeight
|
|
||||||
const labelText = document.createTextNode(item.text)
|
|
||||||
label.appendChild(labelText)
|
|
||||||
li.appendChild(button)
|
|
||||||
button.appendChild(box)
|
|
||||||
button.appendChild(label)
|
|
||||||
ul.appendChild(li)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
});
|
|
||||||
return () => chart.destroy();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<React.Fragment>
|
|
||||||
<div className="px-5 py-4">
|
|
||||||
<ul ref={legend} className="flex flex-wrap"></ul>
|
|
||||||
</div>
|
|
||||||
<div className="grow">
|
|
||||||
<canvas ref={canvas} width={width} height={height}></canvas>
|
|
||||||
</div>
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default BarChart04;
|
|
||||||
@@ -1,157 +0,0 @@
|
|||||||
import React, { useRef, useEffect } from 'react';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Chart, BarController, BarElement, LinearScale, TimeScale, Tooltip, Legend,
|
|
||||||
} from 'chart.js';
|
|
||||||
import 'chartjs-adapter-moment';
|
|
||||||
|
|
||||||
// Import utilities
|
|
||||||
import { tailwindConfig, formatValue } from '../utils/Utils';
|
|
||||||
|
|
||||||
Chart.register(BarController, BarElement, LinearScale, TimeScale, Tooltip, Legend);
|
|
||||||
|
|
||||||
function BarChart05({
|
|
||||||
data,
|
|
||||||
width,
|
|
||||||
height
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const canvas = useRef(null);
|
|
||||||
const legend = useRef(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const ctx = canvas.current;
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const chart = new Chart(ctx, {
|
|
||||||
type: 'bar',
|
|
||||||
data: data,
|
|
||||||
options: {
|
|
||||||
layout: {
|
|
||||||
padding: {
|
|
||||||
top: 12,
|
|
||||||
bottom: 16,
|
|
||||||
left: 20,
|
|
||||||
right: 20,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
grid: {
|
|
||||||
drawBorder: false,
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
maxTicksLimit: 5,
|
|
||||||
callback: (value) => formatValue(value),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
x: {
|
|
||||||
type: 'time',
|
|
||||||
time: {
|
|
||||||
parser: 'MM-DD-YYYY',
|
|
||||||
unit: 'month',
|
|
||||||
displayFormats: {
|
|
||||||
month: 'MMM YY',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
display: false,
|
|
||||||
drawBorder: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
legend: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
callbacks: {
|
|
||||||
title: () => false, // Disable tooltip title
|
|
||||||
label: (context) => formatValue(context.parsed.y),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
interaction: {
|
|
||||||
intersect: false,
|
|
||||||
mode: 'nearest',
|
|
||||||
},
|
|
||||||
animation: {
|
|
||||||
duration: 500,
|
|
||||||
},
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
resizeDelay: 200,
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
{
|
|
||||||
id: 'htmlLegend',
|
|
||||||
afterUpdate(c, args, options) {
|
|
||||||
const ul = legend.current;
|
|
||||||
if (!ul) return;
|
|
||||||
// Remove old legend items
|
|
||||||
while (ul.firstChild) {
|
|
||||||
ul.firstChild.remove();
|
|
||||||
}
|
|
||||||
// Reuse the built-in legendItems generator
|
|
||||||
const items = c.options.plugins.legend.labels.generateLabels(c);
|
|
||||||
items.forEach((item) => {
|
|
||||||
const li = document.createElement('li');
|
|
||||||
li.style.marginRight = tailwindConfig().theme.margin[4];
|
|
||||||
// Button element
|
|
||||||
const button = document.createElement('button');
|
|
||||||
button.style.display = 'inline-flex';
|
|
||||||
button.style.alignItems = 'center';
|
|
||||||
button.style.opacity = item.hidden ? '.3' : '';
|
|
||||||
button.onclick = () => {
|
|
||||||
c.setDatasetVisibility(item.datasetIndex, !c.isDatasetVisible(item.datasetIndex));
|
|
||||||
c.update();
|
|
||||||
};
|
|
||||||
// Color box
|
|
||||||
const box = document.createElement('span');
|
|
||||||
box.style.display = 'block';
|
|
||||||
box.style.width = tailwindConfig().theme.width[3];
|
|
||||||
box.style.height = tailwindConfig().theme.height[3];
|
|
||||||
box.style.borderRadius = tailwindConfig().theme.borderRadius.full;
|
|
||||||
box.style.marginRight = tailwindConfig().theme.margin[2];
|
|
||||||
box.style.borderWidth = '3px';
|
|
||||||
box.style.borderColor = item.fillStyle;
|
|
||||||
box.style.pointerEvents = 'none';
|
|
||||||
// Label
|
|
||||||
const label = document.createElement('span');
|
|
||||||
label.style.color = tailwindConfig().theme.colors.slate[500];
|
|
||||||
label.style.fontSize = tailwindConfig().theme.fontSize.sm[0];
|
|
||||||
label.style.lineHeight = tailwindConfig().theme.fontSize.sm[1].lineHeight;
|
|
||||||
const labelText = document.createTextNode(item.text);
|
|
||||||
label.appendChild(labelText);
|
|
||||||
li.appendChild(button);
|
|
||||||
button.appendChild(box);
|
|
||||||
button.appendChild(label);
|
|
||||||
ul.appendChild(li);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
return () => chart.destroy();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<React.Fragment>
|
|
||||||
<div className="px-5 py-3">
|
|
||||||
<div className="flex flex-wrap justify-between items-center">
|
|
||||||
<div className="flex items-center">
|
|
||||||
<div className="text-3xl font-bold text-slate-800 mr-2">$1,347.09</div>
|
|
||||||
<div className="text-sm">Net</div>
|
|
||||||
</div>
|
|
||||||
<div className="grow ml-2">
|
|
||||||
<ul ref={legend} className="flex flex-wrap justify-end"></ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="grow">
|
|
||||||
<canvas ref={canvas} width={width} height={height}></canvas>
|
|
||||||
</div>
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default BarChart05;
|
|
||||||
@@ -1,164 +0,0 @@
|
|||||||
import React, { useRef, useEffect } from 'react';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Chart, BarController, BarElement, LinearScale, CategoryScale, Tooltip, Legend,
|
|
||||||
} from 'chart.js';
|
|
||||||
import 'chartjs-adapter-moment';
|
|
||||||
|
|
||||||
// Import utilities
|
|
||||||
import { tailwindConfig, formatValue } from '../utils/Utils';
|
|
||||||
|
|
||||||
// Import images
|
|
||||||
import revolutIcon from '../images/company-icon-01.svg';
|
|
||||||
import hsbcIcon from '../images/company-icon-02.svg';
|
|
||||||
import qontoIcon from '../images/company-icon-03.svg';
|
|
||||||
import n26Icon from '../images/company-icon-04.svg';
|
|
||||||
|
|
||||||
Chart.register(BarController, BarElement, LinearScale, CategoryScale, Tooltip, Legend);
|
|
||||||
const images = [revolutIcon, hsbcIcon, qontoIcon, n26Icon];
|
|
||||||
|
|
||||||
function BarChart06({
|
|
||||||
data,
|
|
||||||
width,
|
|
||||||
height
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const canvas = useRef(null);
|
|
||||||
const legend = useRef(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const ctx = canvas.current;
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const chart = new Chart(ctx, {
|
|
||||||
type: 'bar',
|
|
||||||
data: data,
|
|
||||||
options: {
|
|
||||||
indexAxis: 'y',
|
|
||||||
layout: {
|
|
||||||
padding: {
|
|
||||||
top: 12,
|
|
||||||
bottom: 16,
|
|
||||||
left: 72,
|
|
||||||
right: 20,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
grid: {
|
|
||||||
display: false,
|
|
||||||
drawBorder: false,
|
|
||||||
drawTicks: false,
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
x: {
|
|
||||||
grid: {
|
|
||||||
drawBorder: false,
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
maxTicksLimit: 3,
|
|
||||||
align: 'end',
|
|
||||||
callback: (value) => formatValue(value),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
legend: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
callbacks: {
|
|
||||||
title: () => false, // Disable tooltip title
|
|
||||||
label: (context) => formatValue(context.parsed.x),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
interaction: {
|
|
||||||
intersect: false,
|
|
||||||
mode: 'nearest',
|
|
||||||
},
|
|
||||||
animation: {
|
|
||||||
duration: 500,
|
|
||||||
},
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
resizeDelay: 200,
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
{
|
|
||||||
id: 'htmlLegend',
|
|
||||||
afterUpdate(c, args, options) {
|
|
||||||
const ul = legend.current;
|
|
||||||
if (!ul) return;
|
|
||||||
// Remove old legend items
|
|
||||||
while (ul.firstChild) {
|
|
||||||
ul.firstChild.remove();
|
|
||||||
}
|
|
||||||
// Reuse the built-in legendItems generator
|
|
||||||
const items = c.options.plugins.legend.labels.generateLabels(c);
|
|
||||||
items.forEach((item) => {
|
|
||||||
const li = document.createElement('li');
|
|
||||||
li.style.marginRight = tailwindConfig().theme.margin[4];
|
|
||||||
// Button element
|
|
||||||
const button = document.createElement('button');
|
|
||||||
button.style.display = 'inline-flex';
|
|
||||||
button.style.alignItems = 'center';
|
|
||||||
button.style.opacity = item.hidden ? '.3' : '';
|
|
||||||
button.onclick = () => {
|
|
||||||
c.setDatasetVisibility(item.datasetIndex, !c.isDatasetVisible(item.datasetIndex));
|
|
||||||
c.update();
|
|
||||||
};
|
|
||||||
// Color box
|
|
||||||
const box = document.createElement('span');
|
|
||||||
box.style.display = 'block';
|
|
||||||
box.style.width = tailwindConfig().theme.width[3];
|
|
||||||
box.style.height = tailwindConfig().theme.height[3];
|
|
||||||
box.style.borderRadius = tailwindConfig().theme.borderRadius.full;
|
|
||||||
box.style.marginRight = tailwindConfig().theme.margin[2];
|
|
||||||
box.style.borderWidth = '3px';
|
|
||||||
box.style.borderColor = item.fillStyle;
|
|
||||||
box.style.pointerEvents = 'none';
|
|
||||||
// Label
|
|
||||||
const label = document.createElement('span');
|
|
||||||
label.style.color = tailwindConfig().theme.colors.slate[500];
|
|
||||||
label.style.fontSize = tailwindConfig().theme.fontSize.sm[0];
|
|
||||||
label.style.lineHeight = tailwindConfig().theme.fontSize.sm[1].lineHeight;
|
|
||||||
const labelText = document.createTextNode(item.text);
|
|
||||||
label.appendChild(labelText);
|
|
||||||
li.appendChild(button);
|
|
||||||
button.appendChild(box);
|
|
||||||
button.appendChild(label);
|
|
||||||
ul.appendChild(li);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
afterDraw(c) {
|
|
||||||
const xAxis = c.scales.x;
|
|
||||||
const yAxis = c.scales.y;
|
|
||||||
yAxis.ticks.forEach((value, index) => {
|
|
||||||
const y = yAxis.getPixelForTick(index);
|
|
||||||
const image = new Image();
|
|
||||||
image.src = images[index];
|
|
||||||
c.ctx.drawImage(image, xAxis.left - 52, y - 18);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
return () => chart.destroy();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<React.Fragment>
|
|
||||||
<div className="px-5 py-4">
|
|
||||||
<ul ref={legend} className="flex flex-wrap"></ul>
|
|
||||||
</div>
|
|
||||||
<div className="grow">
|
|
||||||
<canvas ref={canvas} width={width} height={height}></canvas>
|
|
||||||
</div>
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default BarChart06;
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
// Import Chart.js
|
|
||||||
import { Chart, Tooltip } from 'chart.js';
|
|
||||||
// Import Tailwind config
|
|
||||||
import { tailwindConfig } from '../utils/Utils';
|
|
||||||
|
|
||||||
Chart.register(Tooltip);
|
|
||||||
|
|
||||||
// Define Chart.js default settings
|
|
||||||
Chart.defaults.font.family = '"Inter", sans-serif';
|
|
||||||
Chart.defaults.font.weight = '500';
|
|
||||||
Chart.defaults.color = tailwindConfig().theme.colors.slate[400];
|
|
||||||
Chart.defaults.scale.grid.color = tailwindConfig().theme.colors.slate[100];
|
|
||||||
Chart.defaults.plugins.tooltip.titleColor = tailwindConfig().theme.colors.slate[800];
|
|
||||||
Chart.defaults.plugins.tooltip.bodyColor = tailwindConfig().theme.colors.slate[800];
|
|
||||||
Chart.defaults.plugins.tooltip.backgroundColor = tailwindConfig().theme.colors.white;
|
|
||||||
Chart.defaults.plugins.tooltip.borderWidth = 1;
|
|
||||||
Chart.defaults.plugins.tooltip.borderColor = tailwindConfig().theme.colors.slate[200];
|
|
||||||
Chart.defaults.plugins.tooltip.displayColors = false;
|
|
||||||
Chart.defaults.plugins.tooltip.mode = 'nearest';
|
|
||||||
Chart.defaults.plugins.tooltip.intersect = false;
|
|
||||||
Chart.defaults.plugins.tooltip.position = 'nearest';
|
|
||||||
Chart.defaults.plugins.tooltip.caretSize = 0;
|
|
||||||
Chart.defaults.plugins.tooltip.caretPadding = 20;
|
|
||||||
Chart.defaults.plugins.tooltip.cornerRadius = 4;
|
|
||||||
Chart.defaults.plugins.tooltip.padding = 8;
|
|
||||||
|
|
||||||
// Register Chart.js plugin to add a bg option for chart area
|
|
||||||
Chart.register({
|
|
||||||
id: 'chartAreaPlugin',
|
|
||||||
// eslint-disable-next-line object-shorthand
|
|
||||||
beforeDraw: (chart) => {
|
|
||||||
if (chart.config.options.chartArea && chart.config.options.chartArea.backgroundColor) {
|
|
||||||
const ctx = chart.canvas.getContext('2d');
|
|
||||||
const { chartArea } = chart;
|
|
||||||
ctx.save();
|
|
||||||
ctx.fillStyle = chart.config.options.chartArea.backgroundColor;
|
|
||||||
// eslint-disable-next-line max-len
|
|
||||||
ctx.fillRect(chartArea.left, chartArea.top, chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);
|
|
||||||
ctx.restore();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
import React, { useRef, useEffect } from 'react';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Chart, DoughnutController, ArcElement, TimeScale, Tooltip,
|
|
||||||
} from 'chart.js';
|
|
||||||
import 'chartjs-adapter-moment';
|
|
||||||
|
|
||||||
// Import utilities
|
|
||||||
import { tailwindConfig } from '../utils/Utils';
|
|
||||||
|
|
||||||
Chart.register(DoughnutController, ArcElement, TimeScale, Tooltip);
|
|
||||||
|
|
||||||
function DoughnutChart({
|
|
||||||
data,
|
|
||||||
width,
|
|
||||||
height
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const canvas = useRef(null);
|
|
||||||
const legend = useRef(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const ctx = canvas.current;
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const chart = new Chart(ctx, {
|
|
||||||
type: 'doughnut',
|
|
||||||
data: data,
|
|
||||||
options: {
|
|
||||||
cutout: '80%',
|
|
||||||
layout: {
|
|
||||||
padding: 24,
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
legend: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
interaction: {
|
|
||||||
intersect: false,
|
|
||||||
mode: 'nearest',
|
|
||||||
},
|
|
||||||
animation: {
|
|
||||||
duration: 500,
|
|
||||||
},
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
resizeDelay: 200,
|
|
||||||
},
|
|
||||||
plugins: [{
|
|
||||||
id: 'htmlLegend',
|
|
||||||
afterUpdate(c, args, options) {
|
|
||||||
const ul = legend.current;
|
|
||||||
if (!ul) return;
|
|
||||||
// Remove old legend items
|
|
||||||
while (ul.firstChild) {
|
|
||||||
ul.firstChild.remove();
|
|
||||||
}
|
|
||||||
// Reuse the built-in legendItems generator
|
|
||||||
const items = c.options.plugins.legend.labels.generateLabels(c);
|
|
||||||
items.forEach((item) => {
|
|
||||||
const li = document.createElement('li');
|
|
||||||
li.style.margin = tailwindConfig().theme.margin[1];
|
|
||||||
// Button element
|
|
||||||
const button = document.createElement('button');
|
|
||||||
button.classList.add('btn-xs');
|
|
||||||
button.style.backgroundColor = tailwindConfig().theme.colors.white;
|
|
||||||
button.style.borderWidth = tailwindConfig().theme.borderWidth[1];
|
|
||||||
button.style.borderColor = tailwindConfig().theme.colors.slate[200];
|
|
||||||
button.style.color = tailwindConfig().theme.colors.slate[500];
|
|
||||||
button.style.boxShadow = tailwindConfig().theme.boxShadow.md;
|
|
||||||
button.style.opacity = item.hidden ? '.3' : '';
|
|
||||||
button.onclick = () => {
|
|
||||||
c.toggleDataVisibility(item.index, !item.index);
|
|
||||||
c.update();
|
|
||||||
};
|
|
||||||
// Color box
|
|
||||||
const box = document.createElement('span');
|
|
||||||
box.style.display = 'block';
|
|
||||||
box.style.width = tailwindConfig().theme.width[2];
|
|
||||||
box.style.height = tailwindConfig().theme.height[2];
|
|
||||||
box.style.backgroundColor = item.fillStyle;
|
|
||||||
box.style.borderRadius = tailwindConfig().theme.borderRadius.sm;
|
|
||||||
box.style.marginRight = tailwindConfig().theme.margin[1];
|
|
||||||
box.style.pointerEvents = 'none';
|
|
||||||
// Label
|
|
||||||
const label = document.createElement('span');
|
|
||||||
label.style.display = 'flex';
|
|
||||||
label.style.alignItems = 'center';
|
|
||||||
const labelText = document.createTextNode(item.text);
|
|
||||||
label.appendChild(labelText);
|
|
||||||
li.appendChild(button);
|
|
||||||
button.appendChild(box);
|
|
||||||
button.appendChild(label);
|
|
||||||
ul.appendChild(li);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
});
|
|
||||||
return () => chart.destroy();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="grow flex flex-col justify-center">
|
|
||||||
<div>
|
|
||||||
<canvas ref={canvas} width={width} height={height}></canvas>
|
|
||||||
</div>
|
|
||||||
<div className="px-5 pt-2 pb-6">
|
|
||||||
<ul ref={legend} className="flex flex-wrap justify-center -m-1"></ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DoughnutChart;
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
import React, { useRef, useEffect } from 'react';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Chart, LineController, LineElement, Filler, PointElement, LinearScale, TimeScale, Tooltip,
|
|
||||||
} from 'chart.js';
|
|
||||||
import 'chartjs-adapter-moment';
|
|
||||||
|
|
||||||
// Import utilities
|
|
||||||
import { tailwindConfig, formatValue } from '../utils/Utils';
|
|
||||||
|
|
||||||
Chart.register(LineController, LineElement, Filler, PointElement, LinearScale, TimeScale, Tooltip);
|
|
||||||
|
|
||||||
function LineChart01({
|
|
||||||
data,
|
|
||||||
width,
|
|
||||||
height
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const canvas = useRef(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const ctx = canvas.current;
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const chart = new Chart(ctx, {
|
|
||||||
type: 'line',
|
|
||||||
data: data,
|
|
||||||
options: {
|
|
||||||
chartArea: {
|
|
||||||
backgroundColor: tailwindConfig().theme.colors.slate[50],
|
|
||||||
},
|
|
||||||
layout: {
|
|
||||||
padding: 20,
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
display: false,
|
|
||||||
beginAtZero: true,
|
|
||||||
},
|
|
||||||
x: {
|
|
||||||
type: 'time',
|
|
||||||
time: {
|
|
||||||
parser: 'MM-DD-YYYY',
|
|
||||||
unit: 'month',
|
|
||||||
},
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
tooltip: {
|
|
||||||
callbacks: {
|
|
||||||
title: () => false, // Disable tooltip title
|
|
||||||
label: (context) => formatValue(context.parsed.y),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
interaction: {
|
|
||||||
intersect: false,
|
|
||||||
mode: 'nearest',
|
|
||||||
},
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
resizeDelay: 200,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return () => chart.destroy();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<canvas ref={canvas} width={width} height={height}></canvas>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default LineChart01;
|
|
||||||
@@ -1,153 +0,0 @@
|
|||||||
import React, { useRef, useEffect } from 'react';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Chart, LineController, LineElement, Filler, PointElement, LinearScale, TimeScale, Tooltip,
|
|
||||||
} from 'chart.js';
|
|
||||||
import 'chartjs-adapter-moment';
|
|
||||||
|
|
||||||
// Import utilities
|
|
||||||
import { tailwindConfig, formatValue } from '../utils/Utils';
|
|
||||||
|
|
||||||
Chart.register(LineController, LineElement, Filler, PointElement, LinearScale, TimeScale, Tooltip);
|
|
||||||
|
|
||||||
function LineChart02({
|
|
||||||
data,
|
|
||||||
width,
|
|
||||||
height
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const canvas = useRef(null);
|
|
||||||
const legend = useRef(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const ctx = canvas.current;
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const chart = new Chart(ctx, {
|
|
||||||
type: 'line',
|
|
||||||
data: data,
|
|
||||||
options: {
|
|
||||||
layout: {
|
|
||||||
padding: 20,
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
grid: {
|
|
||||||
drawBorder: false,
|
|
||||||
beginAtZero: true,
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
maxTicksLimit: 5,
|
|
||||||
callback: (value) => formatValue(value),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
x: {
|
|
||||||
type: 'time',
|
|
||||||
time: {
|
|
||||||
parser: 'MM-DD-YYYY',
|
|
||||||
unit: 'month',
|
|
||||||
displayFormats: {
|
|
||||||
month: 'MMM YY',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
display: false,
|
|
||||||
drawBorder: false,
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
autoSkipPadding: 48,
|
|
||||||
maxRotation: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
legend: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
callbacks: {
|
|
||||||
title: () => false, // Disable tooltip title
|
|
||||||
label: (context) => formatValue(context.parsed.y),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
interaction: {
|
|
||||||
intersect: false,
|
|
||||||
mode: 'nearest',
|
|
||||||
},
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
resizeDelay: 200,
|
|
||||||
},
|
|
||||||
plugins: [{
|
|
||||||
id: 'htmlLegend',
|
|
||||||
afterUpdate(c, args, options) {
|
|
||||||
const ul = legend.current;
|
|
||||||
if (!ul) return;
|
|
||||||
// Remove old legend items
|
|
||||||
while (ul.firstChild) {
|
|
||||||
ul.firstChild.remove();
|
|
||||||
}
|
|
||||||
// Reuse the built-in legendItems generator
|
|
||||||
const items = c.options.plugins.legend.labels.generateLabels(c);
|
|
||||||
items.slice(0, 2).forEach((item) => {
|
|
||||||
const li = document.createElement('li');
|
|
||||||
li.style.marginLeft = tailwindConfig().theme.margin[3];
|
|
||||||
// Button element
|
|
||||||
const button = document.createElement('button');
|
|
||||||
button.style.display = 'inline-flex';
|
|
||||||
button.style.alignItems = 'center';
|
|
||||||
button.style.opacity = item.hidden ? '.3' : '';
|
|
||||||
button.onclick = () => {
|
|
||||||
c.setDatasetVisibility(item.datasetIndex, !c.isDatasetVisible(item.datasetIndex));
|
|
||||||
c.update();
|
|
||||||
};
|
|
||||||
// Color box
|
|
||||||
const box = document.createElement('span');
|
|
||||||
box.style.display = 'block';
|
|
||||||
box.style.width = tailwindConfig().theme.width[3];
|
|
||||||
box.style.height = tailwindConfig().theme.height[3];
|
|
||||||
box.style.borderRadius = tailwindConfig().theme.borderRadius.full;
|
|
||||||
box.style.marginRight = tailwindConfig().theme.margin[2];
|
|
||||||
box.style.borderWidth = '3px';
|
|
||||||
box.style.borderColor = c.data.datasets[item.datasetIndex].borderColor;
|
|
||||||
box.style.pointerEvents = 'none';
|
|
||||||
// Label
|
|
||||||
const label = document.createElement('span');
|
|
||||||
label.style.color = tailwindConfig().theme.colors.slate[500];
|
|
||||||
label.style.fontSize = tailwindConfig().theme.fontSize.sm[0];
|
|
||||||
label.style.lineHeight = tailwindConfig().theme.fontSize.sm[1].lineHeight;
|
|
||||||
const labelText = document.createTextNode(item.text);
|
|
||||||
label.appendChild(labelText);
|
|
||||||
li.appendChild(button);
|
|
||||||
button.appendChild(box);
|
|
||||||
button.appendChild(label);
|
|
||||||
ul.appendChild(li);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
});
|
|
||||||
return () => chart.destroy();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<React.Fragment>
|
|
||||||
<div className="px-5 py-3">
|
|
||||||
<div className="flex flex-wrap justify-between items-end">
|
|
||||||
<div className="flex items-start">
|
|
||||||
<div className="text-3xl font-bold text-slate-800 mr-2">$1,482</div>
|
|
||||||
<div className="text-sm font-semibold text-white px-1.5 bg-amber-500 rounded-full">-22%</div>
|
|
||||||
</div>
|
|
||||||
<div className="grow ml-2 mb-1">
|
|
||||||
<ul ref={legend} className="flex flex-wrap justify-end"></ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/* Chart built with Chart.js 3 */}
|
|
||||||
<div className="grow">
|
|
||||||
<canvas ref={canvas} width={width} height={height}></canvas>
|
|
||||||
</div>
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default LineChart02;
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
import React, { useRef, useEffect } from 'react';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Chart, LineController, LineElement, Filler, PointElement, LinearScale, TimeScale, Tooltip,
|
|
||||||
} from 'chart.js';
|
|
||||||
import 'chartjs-adapter-moment';
|
|
||||||
|
|
||||||
// Import utilities
|
|
||||||
import { formatThousands } from '../utils/Utils';
|
|
||||||
|
|
||||||
Chart.register(LineController, LineElement, Filler, PointElement, LinearScale, TimeScale, Tooltip);
|
|
||||||
|
|
||||||
function LineChart03({
|
|
||||||
data,
|
|
||||||
width,
|
|
||||||
height
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const canvas = useRef(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const ctx = canvas.current;
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const chart = new Chart(ctx, {
|
|
||||||
type: 'line',
|
|
||||||
data: data,
|
|
||||||
options: {
|
|
||||||
layout: {
|
|
||||||
padding: 20,
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
beginAtZero: true,
|
|
||||||
grid: {
|
|
||||||
drawBorder: false,
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
callback: (value) => formatThousands(value),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
x: {
|
|
||||||
type: 'time',
|
|
||||||
time: {
|
|
||||||
parser: 'MM-DD-YYYY',
|
|
||||||
unit: 'month',
|
|
||||||
displayFormats: {
|
|
||||||
month: 'MMM YY',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
display: false,
|
|
||||||
drawBorder: false,
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
autoSkipPadding: 48,
|
|
||||||
maxRotation: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
legend: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
callbacks: {
|
|
||||||
title: () => false, // Disable tooltip title
|
|
||||||
label: (context) => formatThousands(context.parsed.y),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
interaction: {
|
|
||||||
intersect: false,
|
|
||||||
mode: 'nearest',
|
|
||||||
},
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
resizeDelay: 200,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return () => chart.destroy();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<canvas ref={canvas} width={width} height={height}></canvas>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default LineChart03;
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
import React, { useRef, useEffect } from 'react';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Chart, LineController, LineElement, Filler, PointElement, LinearScale, TimeScale, Tooltip,
|
|
||||||
} from 'chart.js';
|
|
||||||
import 'chartjs-adapter-moment';
|
|
||||||
|
|
||||||
// Import utilities
|
|
||||||
import { tailwindConfig, formatThousands } from '../utils/Utils';
|
|
||||||
|
|
||||||
Chart.register(LineController, LineElement, Filler, PointElement, LinearScale, TimeScale, Tooltip);
|
|
||||||
|
|
||||||
function LineChart04({
|
|
||||||
data,
|
|
||||||
width,
|
|
||||||
height
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const canvas = useRef(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const ctx = canvas.current;
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const chart = new Chart(ctx, {
|
|
||||||
type: 'line',
|
|
||||||
data: data,
|
|
||||||
options: {
|
|
||||||
chartArea: {
|
|
||||||
backgroundColor: tailwindConfig().theme.colors.slate[50],
|
|
||||||
},
|
|
||||||
layout: {
|
|
||||||
padding: {
|
|
||||||
left: 20,
|
|
||||||
right: 20,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
display: false,
|
|
||||||
beginAtZero: true,
|
|
||||||
},
|
|
||||||
x: {
|
|
||||||
type: 'time',
|
|
||||||
time: {
|
|
||||||
parser: 'MM-DD-YYYY',
|
|
||||||
unit: 'month',
|
|
||||||
},
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
tooltip: {
|
|
||||||
callbacks: {
|
|
||||||
title: () => false, // Disable tooltip title
|
|
||||||
label: (context) => formatThousands(context.parsed.y),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
interaction: {
|
|
||||||
intersect: false,
|
|
||||||
mode: 'nearest',
|
|
||||||
},
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return () => chart.destroy();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<canvas ref={canvas} width={width} height={height}></canvas>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default LineChart04;
|
|
||||||
@@ -1,157 +0,0 @@
|
|||||||
import React, { useRef, useEffect } from 'react';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Chart, LineController, LineElement, Filler, PointElement, LinearScale, TimeScale, Tooltip,
|
|
||||||
} from 'chart.js';
|
|
||||||
import 'chartjs-adapter-moment';
|
|
||||||
|
|
||||||
// Import utilities
|
|
||||||
import { tailwindConfig } from '../utils/Utils';
|
|
||||||
|
|
||||||
Chart.register(LineController, LineElement, Filler, PointElement, LinearScale, TimeScale, Tooltip);
|
|
||||||
|
|
||||||
function LineChart05({
|
|
||||||
data,
|
|
||||||
width,
|
|
||||||
height
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const canvas = useRef(null);
|
|
||||||
const legend = useRef(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const ctx = canvas.current;
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const chart = new Chart(ctx, {
|
|
||||||
type: 'line',
|
|
||||||
data: data,
|
|
||||||
options: {
|
|
||||||
layout: {
|
|
||||||
padding: 20,
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
beginAtZero: true,
|
|
||||||
grid: {
|
|
||||||
drawBorder: false,
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
maxTicksLimit: 7,
|
|
||||||
callback: (value) => `${value}%`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
x: {
|
|
||||||
type: 'time',
|
|
||||||
time: {
|
|
||||||
parser: 'MM-DD-YYYY',
|
|
||||||
unit: 'month',
|
|
||||||
displayFormats: {
|
|
||||||
month: 'MMM YY',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
display: false,
|
|
||||||
drawBorder: false,
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
autoSkipPadding: 48,
|
|
||||||
maxRotation: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
legend: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
callbacks: {
|
|
||||||
title: () => false, // Disable tooltip title
|
|
||||||
label: (context) => `${context.parsed.y}%`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
interaction: {
|
|
||||||
intersect: false,
|
|
||||||
mode: 'nearest',
|
|
||||||
},
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
resizeDelay: 200,
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
{
|
|
||||||
id: 'htmlLegend',
|
|
||||||
afterUpdate(c, args, options) {
|
|
||||||
const ul = legend.current;
|
|
||||||
if (!ul) return;
|
|
||||||
// Remove old legend items
|
|
||||||
while (ul.firstChild) {
|
|
||||||
ul.firstChild.remove();
|
|
||||||
}
|
|
||||||
// Reuse the built-in legendItems generator
|
|
||||||
const items = c.options.plugins.legend.labels.generateLabels(c);
|
|
||||||
items.forEach((item) => {
|
|
||||||
const li = document.createElement('li');
|
|
||||||
li.style.marginLeft = tailwindConfig().theme.margin[3];
|
|
||||||
// Button element
|
|
||||||
const button = document.createElement('button');
|
|
||||||
button.style.display = 'inline-flex';
|
|
||||||
button.style.alignItems = 'center';
|
|
||||||
button.style.opacity = item.hidden ? '.3' : '';
|
|
||||||
button.onclick = () => {
|
|
||||||
c.setDatasetVisibility(item.datasetIndex, !c.isDatasetVisible(item.datasetIndex));
|
|
||||||
c.update();
|
|
||||||
};
|
|
||||||
// Color box
|
|
||||||
const box = document.createElement('span');
|
|
||||||
box.style.display = 'block';
|
|
||||||
box.style.width = tailwindConfig().theme.width[3];
|
|
||||||
box.style.height = tailwindConfig().theme.height[3];
|
|
||||||
box.style.borderRadius = tailwindConfig().theme.borderRadius.full;
|
|
||||||
box.style.marginRight = tailwindConfig().theme.margin[2];
|
|
||||||
box.style.borderWidth = '3px';
|
|
||||||
box.style.borderColor = c.data.datasets[item.datasetIndex].borderColor;
|
|
||||||
box.style.pointerEvents = 'none';
|
|
||||||
// Label
|
|
||||||
const label = document.createElement('span');
|
|
||||||
label.style.color = tailwindConfig().theme.colors.slate[500];
|
|
||||||
label.style.fontSize = tailwindConfig().theme.fontSize.sm[0];
|
|
||||||
label.style.lineHeight = tailwindConfig().theme.fontSize.sm[1].lineHeight;
|
|
||||||
const labelText = document.createTextNode(item.text);
|
|
||||||
label.appendChild(labelText);
|
|
||||||
li.appendChild(button);
|
|
||||||
button.appendChild(box);
|
|
||||||
button.appendChild(label);
|
|
||||||
ul.appendChild(li);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
return () => chart.destroy();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<React.Fragment>
|
|
||||||
<div className="px-5 py-3">
|
|
||||||
<div className="flex flex-wrap justify-between items-end">
|
|
||||||
<div className="flex items-center">
|
|
||||||
<div className="text-3xl font-bold text-slate-800 mr-2">244.7%</div>
|
|
||||||
<div className="text-sm">
|
|
||||||
<span className="font-medium text-slate-800">17.4%</span> AVG
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="grow ml-2 mb-1">
|
|
||||||
<ul ref={legend} className="flex flex-wrap justify-end" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/* Chart built with Chart.js 3 */}
|
|
||||||
<div className="grow">
|
|
||||||
<canvas ref={canvas} width={width} height={height}></canvas>
|
|
||||||
</div>
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default LineChart05;
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
import React, { useRef, useEffect } from 'react';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Chart, LineController, LineElement, Filler, PointElement, LinearScale, TimeScale, Tooltip,
|
|
||||||
} from 'chart.js';
|
|
||||||
import 'chartjs-adapter-moment';
|
|
||||||
|
|
||||||
// Import utilities
|
|
||||||
import { formatValue } from '../utils/Utils';
|
|
||||||
|
|
||||||
Chart.register(LineController, LineElement, Filler, PointElement, LinearScale, TimeScale, Tooltip);
|
|
||||||
|
|
||||||
function LineChart06({
|
|
||||||
data,
|
|
||||||
width,
|
|
||||||
height
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const canvas = useRef(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const ctx = canvas.current;
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const chart = new Chart(ctx, {
|
|
||||||
type: 'line',
|
|
||||||
data: data,
|
|
||||||
options: {
|
|
||||||
layout: {
|
|
||||||
padding: {
|
|
||||||
top: 12,
|
|
||||||
bottom: 16,
|
|
||||||
left: 20,
|
|
||||||
right: 20,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
beginAtZero: true,
|
|
||||||
grid: {
|
|
||||||
drawBorder: false,
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
maxTicksLimit: 7,
|
|
||||||
callback: (value) => formatValue(value),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
x: {
|
|
||||||
type: 'time',
|
|
||||||
time: {
|
|
||||||
parser: 'MM-DD-YYYY',
|
|
||||||
unit: 'month',
|
|
||||||
displayFormats: {
|
|
||||||
month: 'MMM YY',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
display: false,
|
|
||||||
drawBorder: false,
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
autoSkipPadding: 48,
|
|
||||||
maxRotation: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
tooltip: {
|
|
||||||
callbacks: {
|
|
||||||
title: () => false, // Disable tooltip title
|
|
||||||
label: (context) => formatValue(context.parsed.y),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
interaction: {
|
|
||||||
intersect: false,
|
|
||||||
mode: 'nearest',
|
|
||||||
},
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
resizeDelay: 200,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return () => chart.destroy();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<canvas ref={canvas} width={width} height={height}></canvas>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default LineChart06;
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
import React, { useRef, useEffect } from 'react';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Chart, LineController, LineElement, Filler, PointElement, LinearScale, CategoryScale, Tooltip,
|
|
||||||
} from 'chart.js';
|
|
||||||
import 'chartjs-adapter-moment';
|
|
||||||
|
|
||||||
// Import utilities
|
|
||||||
import { formatValue } from '../utils/Utils';
|
|
||||||
|
|
||||||
Chart.register(LineController, LineElement, Filler, PointElement, LinearScale, CategoryScale, Tooltip);
|
|
||||||
|
|
||||||
function LineChart07({
|
|
||||||
data,
|
|
||||||
width,
|
|
||||||
height
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const canvas = useRef(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const ctx = canvas.current;
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const chart = new Chart(ctx, {
|
|
||||||
type: 'line',
|
|
||||||
data: data,
|
|
||||||
options: {
|
|
||||||
layout: {
|
|
||||||
padding: {
|
|
||||||
top: 12,
|
|
||||||
bottom: 16,
|
|
||||||
left: 20,
|
|
||||||
right: 20,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
beginAtZero: true,
|
|
||||||
grid: {
|
|
||||||
drawBorder: false,
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
maxTicksLimit: 7,
|
|
||||||
callback: (value) => formatValue(value),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
x: {
|
|
||||||
grid: {
|
|
||||||
display: false,
|
|
||||||
drawBorder: false,
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
autoSkipPadding: 48,
|
|
||||||
maxRotation: 0,
|
|
||||||
align: 'end',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
tooltip: {
|
|
||||||
callbacks: {
|
|
||||||
title: () => false, // Disable tooltip title
|
|
||||||
label: (context) => formatValue(context.parsed.y),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
interaction: {
|
|
||||||
intersect: false,
|
|
||||||
mode: 'nearest',
|
|
||||||
},
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return () => chart.destroy();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<canvas ref={canvas} width={width} height={height}></canvas>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default LineChart07;
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
import React, { useRef, useEffect } from 'react';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Chart, LineController, LineElement, Filler, PointElement, LinearScale, TimeScale, Tooltip,
|
|
||||||
} from 'chart.js';
|
|
||||||
import 'chartjs-adapter-moment';
|
|
||||||
|
|
||||||
// Import utilities
|
|
||||||
import { formatValue } from '../utils/Utils';
|
|
||||||
|
|
||||||
Chart.register(LineController, LineElement, Filler, PointElement, LinearScale, TimeScale, Tooltip);
|
|
||||||
|
|
||||||
function LineChart08({
|
|
||||||
data,
|
|
||||||
width,
|
|
||||||
height
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const canvas = useRef(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const ctx = canvas.current;
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const chart = new Chart(ctx, {
|
|
||||||
type: 'line',
|
|
||||||
data: data,
|
|
||||||
options: {
|
|
||||||
layout: {
|
|
||||||
padding: {
|
|
||||||
top: 16,
|
|
||||||
bottom: 16,
|
|
||||||
left: 20,
|
|
||||||
right: 20,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
beginAtZero: true,
|
|
||||||
grid: {
|
|
||||||
drawBorder: false,
|
|
||||||
drawTicks: false,
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
maxTicksLimit: 2,
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
x: {
|
|
||||||
type: 'time',
|
|
||||||
time: {
|
|
||||||
parser: 'MM-DD-YYYY',
|
|
||||||
unit: 'month',
|
|
||||||
},
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
tooltip: {
|
|
||||||
callbacks: {
|
|
||||||
title: () => false, // Disable tooltip title
|
|
||||||
label: (context) => formatValue(context.parsed.y),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
interaction: {
|
|
||||||
intersect: false,
|
|
||||||
mode: 'nearest',
|
|
||||||
},
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return () => chart.destroy();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<canvas ref={canvas} width={width} height={height}></canvas>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default LineChart08;
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
import React, { useRef, useEffect } from 'react';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Chart, LineController, LineElement, Filler, PointElement, LinearScale, TimeScale, Tooltip,
|
|
||||||
} from 'chart.js';
|
|
||||||
import 'chartjs-adapter-moment';
|
|
||||||
|
|
||||||
// Import utilities
|
|
||||||
import { formatValue } from '../utils/Utils';
|
|
||||||
|
|
||||||
Chart.register(LineController, LineElement, Filler, PointElement, LinearScale, TimeScale, Tooltip);
|
|
||||||
|
|
||||||
function LineChart09({
|
|
||||||
data,
|
|
||||||
width,
|
|
||||||
height
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const canvas = useRef(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const ctx = canvas.current;
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const chart = new Chart(ctx, {
|
|
||||||
type: 'line',
|
|
||||||
data: data,
|
|
||||||
options: {
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
display: false,
|
|
||||||
beginAtZero: true,
|
|
||||||
},
|
|
||||||
x: {
|
|
||||||
type: 'time',
|
|
||||||
time: {
|
|
||||||
parser: 'MM-DD-YYYY',
|
|
||||||
unit: 'month',
|
|
||||||
},
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
tooltip: {
|
|
||||||
callbacks: {
|
|
||||||
title: () => false, // Disable tooltip title
|
|
||||||
label: (context) => formatValue(context.parsed.y),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
interaction: {
|
|
||||||
intersect: false,
|
|
||||||
mode: 'nearest',
|
|
||||||
},
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return () => chart.destroy();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<canvas ref={canvas} width={width} height={height}></canvas>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default LineChart09;
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
import React, { useRef, useEffect } from 'react';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Chart, PieController, ArcElement, TimeScale, Tooltip,
|
|
||||||
} from 'chart.js';
|
|
||||||
import 'chartjs-adapter-moment';
|
|
||||||
|
|
||||||
// Import utilities
|
|
||||||
import { tailwindConfig } from '../utils/Utils';
|
|
||||||
|
|
||||||
Chart.register(PieController, ArcElement, TimeScale, Tooltip);
|
|
||||||
|
|
||||||
function PieChart({
|
|
||||||
data,
|
|
||||||
width,
|
|
||||||
height
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const canvas = useRef(null);
|
|
||||||
const legend = useRef(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const ctx = canvas.current;
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const chart = new Chart(ctx, {
|
|
||||||
type: 'pie',
|
|
||||||
data: data,
|
|
||||||
options: {
|
|
||||||
layout: {
|
|
||||||
padding: {
|
|
||||||
top: 4,
|
|
||||||
bottom: 4,
|
|
||||||
left: 24,
|
|
||||||
right: 24,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
legend: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
interaction: {
|
|
||||||
intersect: false,
|
|
||||||
mode: 'nearest',
|
|
||||||
},
|
|
||||||
animation: {
|
|
||||||
duration: 200,
|
|
||||||
},
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
{
|
|
||||||
id: 'htmlLegend',
|
|
||||||
afterUpdate(c, args, options) {
|
|
||||||
const ul = legend.current;
|
|
||||||
if (!ul) return;
|
|
||||||
// Remove old legend items
|
|
||||||
while (ul.firstChild) {
|
|
||||||
ul.firstChild.remove();
|
|
||||||
}
|
|
||||||
// Reuse the built-in legendItems generator
|
|
||||||
const items = c.options.plugins.legend.labels.generateLabels(c);
|
|
||||||
items.forEach((item) => {
|
|
||||||
const li = document.createElement('li');
|
|
||||||
li.style.margin = tailwindConfig().theme.margin[1.5];
|
|
||||||
// Button element
|
|
||||||
const button = document.createElement('button');
|
|
||||||
button.style.display = 'inline-flex';
|
|
||||||
button.style.alignItems = 'center';
|
|
||||||
button.style.opacity = item.hidden ? '.3' : '';
|
|
||||||
button.onclick = () => {
|
|
||||||
c.toggleDataVisibility(item.index, !item.index);
|
|
||||||
c.update();
|
|
||||||
};
|
|
||||||
// Color box
|
|
||||||
const box = document.createElement('span');
|
|
||||||
box.style.display = 'block';
|
|
||||||
box.style.width = tailwindConfig().theme.width[3];
|
|
||||||
box.style.height = tailwindConfig().theme.height[3];
|
|
||||||
box.style.borderRadius = tailwindConfig().theme.borderRadius.full;
|
|
||||||
box.style.marginRight = tailwindConfig().theme.margin[1.5];
|
|
||||||
box.style.borderWidth = '3px';
|
|
||||||
box.style.borderColor = item.fillStyle;
|
|
||||||
box.style.pointerEvents = 'none';
|
|
||||||
// Label
|
|
||||||
const label = document.createElement('span');
|
|
||||||
label.style.color = tailwindConfig().theme.colors.slate[500];
|
|
||||||
label.style.fontSize = tailwindConfig().theme.fontSize.sm[0];
|
|
||||||
label.style.lineHeight = tailwindConfig().theme.fontSize.sm[1].lineHeight;
|
|
||||||
const labelText = document.createTextNode(item.text);
|
|
||||||
label.appendChild(labelText);
|
|
||||||
li.appendChild(button);
|
|
||||||
button.appendChild(box);
|
|
||||||
button.appendChild(label);
|
|
||||||
ul.appendChild(li);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
return () => chart.destroy();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="grow flex flex-col justify-center">
|
|
||||||
<div>
|
|
||||||
<canvas ref={canvas} width={width} height={height}></canvas>
|
|
||||||
</div>
|
|
||||||
<div className="px-5 py-4">
|
|
||||||
<ul ref={legend} className="flex flex-wrap justify-center -m-1" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default PieChart;
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
import React, { useRef, useEffect } from 'react';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Chart, PolarAreaController, RadialLinearScale, Tooltip, Legend,
|
|
||||||
} from 'chart.js';
|
|
||||||
import 'chartjs-adapter-moment';
|
|
||||||
|
|
||||||
// Import utilities
|
|
||||||
import { tailwindConfig } from '../utils/Utils';
|
|
||||||
|
|
||||||
Chart.register(PolarAreaController, RadialLinearScale, Tooltip, Legend);
|
|
||||||
|
|
||||||
function PolarChart({
|
|
||||||
data,
|
|
||||||
width,
|
|
||||||
height
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const canvas = useRef(null);
|
|
||||||
const legend = useRef(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const ctx = canvas.current;
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const chart = new Chart(ctx, {
|
|
||||||
type: 'polarArea',
|
|
||||||
data: data,
|
|
||||||
options: {
|
|
||||||
layout: {
|
|
||||||
padding: 24,
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
legend: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
interaction: {
|
|
||||||
intersect: false,
|
|
||||||
mode: 'nearest',
|
|
||||||
},
|
|
||||||
animation: {
|
|
||||||
duration: 500,
|
|
||||||
},
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
resizeDelay: 200,
|
|
||||||
},
|
|
||||||
plugins: [{
|
|
||||||
id: 'htmlLegend',
|
|
||||||
afterUpdate(c, args, options) {
|
|
||||||
const ul = legend.current
|
|
||||||
if (!ul) return
|
|
||||||
// Remove old legend items
|
|
||||||
while (ul.firstChild) {
|
|
||||||
ul.firstChild.remove()
|
|
||||||
}
|
|
||||||
// Reuse the built-in legendItems generator
|
|
||||||
const items = c.options.plugins.legend.labels.generateLabels(c)
|
|
||||||
items.forEach((item) => {
|
|
||||||
const li = document.createElement('li')
|
|
||||||
li.style.margin = tailwindConfig().theme.margin[1]
|
|
||||||
// Button element
|
|
||||||
const button = document.createElement('button')
|
|
||||||
button.classList.add('btn-xs')
|
|
||||||
button.style.backgroundColor = tailwindConfig().theme.colors.white
|
|
||||||
button.style.borderWidth = tailwindConfig().theme.borderWidth[1]
|
|
||||||
button.style.borderColor = tailwindConfig().theme.colors.slate[200]
|
|
||||||
button.style.color = tailwindConfig().theme.colors.slate[500]
|
|
||||||
button.style.boxShadow = tailwindConfig().theme.boxShadow.md
|
|
||||||
button.style.opacity = item.hidden ? '.3' : ''
|
|
||||||
button.onclick = () => {
|
|
||||||
c.toggleDataVisibility(item.index, !item.index)
|
|
||||||
c.update()
|
|
||||||
}
|
|
||||||
// Color box
|
|
||||||
const box = document.createElement('span')
|
|
||||||
box.style.display = 'block'
|
|
||||||
box.style.width = tailwindConfig().theme.width[2]
|
|
||||||
box.style.height = tailwindConfig().theme.height[2]
|
|
||||||
box.style.backgroundColor = item.fillStyle
|
|
||||||
box.style.borderRadius = tailwindConfig().theme.borderRadius.sm
|
|
||||||
box.style.marginRight = tailwindConfig().theme.margin[1]
|
|
||||||
box.style.pointerEvents = 'none'
|
|
||||||
// Label
|
|
||||||
const label = document.createElement('span')
|
|
||||||
label.style.display = 'flex'
|
|
||||||
label.style.alignItems = 'center'
|
|
||||||
const labelText = document.createTextNode(item.text)
|
|
||||||
label.appendChild(labelText)
|
|
||||||
li.appendChild(button)
|
|
||||||
button.appendChild(box)
|
|
||||||
button.appendChild(label)
|
|
||||||
ul.appendChild(li)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
});
|
|
||||||
return () => chart.destroy();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="grow flex flex-col justify-center">
|
|
||||||
<div>
|
|
||||||
<canvas ref={canvas} width={width} height={height}></canvas>
|
|
||||||
</div>
|
|
||||||
<div className="px-5 pt-2 pb-6">
|
|
||||||
<ul ref={legend} className="flex flex-wrap justify-center -m-1"></ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default PolarChart;
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
import React, { useRef, useEffect } from 'react';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Chart, LineController, LineElement, Filler, PointElement, LinearScale, TimeScale, Tooltip,
|
|
||||||
} from 'chart.js';
|
|
||||||
import 'chartjs-adapter-moment';
|
|
||||||
|
|
||||||
// Import utilities
|
|
||||||
import { tailwindConfig, formatValue } from '../utils/Utils';
|
|
||||||
|
|
||||||
Chart.register(LineController, LineElement, Filler, PointElement, LinearScale, TimeScale, Tooltip);
|
|
||||||
|
|
||||||
function RealtimeChart({
|
|
||||||
data,
|
|
||||||
width,
|
|
||||||
height
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const canvas = useRef(null);
|
|
||||||
const chartValue = useRef(null);
|
|
||||||
const chartDeviation = useRef(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const ctx = canvas.current;
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const chart = new Chart(ctx, {
|
|
||||||
type: 'line',
|
|
||||||
data: data,
|
|
||||||
options: {
|
|
||||||
layout: {
|
|
||||||
padding: 20,
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
grid: {
|
|
||||||
drawBorder: false,
|
|
||||||
},
|
|
||||||
suggestedMin: 30,
|
|
||||||
suggestedMax: 80,
|
|
||||||
ticks: {
|
|
||||||
maxTicksLimit: 5,
|
|
||||||
callback: (value) => formatValue(value),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
x: {
|
|
||||||
type: 'time',
|
|
||||||
time: {
|
|
||||||
parser: 'hh:mm:ss',
|
|
||||||
unit: 'second',
|
|
||||||
tooltipFormat: 'MMM DD, H:mm:ss a',
|
|
||||||
displayFormats: {
|
|
||||||
second: 'H:mm:ss',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
display: false,
|
|
||||||
drawBorder: false,
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
autoSkipPadding: 48,
|
|
||||||
maxRotation: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
legend: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
titleFont: {
|
|
||||||
weight: '600',
|
|
||||||
},
|
|
||||||
callbacks: {
|
|
||||||
label: (context) => formatValue(context.parsed.y),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
interaction: {
|
|
||||||
intersect: false,
|
|
||||||
mode: 'nearest',
|
|
||||||
},
|
|
||||||
animation: false,
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
resizeDelay: 200,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return () => chart.destroy();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [data]);
|
|
||||||
|
|
||||||
// Update header values
|
|
||||||
useEffect(() => {
|
|
||||||
const currentValue = data.datasets[0].data[data.datasets[0].data.length - 1];
|
|
||||||
const previousValue = data.datasets[0].data[data.datasets[0].data.length - 2];
|
|
||||||
const diff = ((currentValue - previousValue) / previousValue) * 100;
|
|
||||||
chartValue.current.innerHTML = data.datasets[0].data[data.datasets[0].data.length - 1];
|
|
||||||
if (diff < 0) {
|
|
||||||
chartDeviation.current.style.backgroundColor = tailwindConfig().theme.colors.yellow[500];
|
|
||||||
} else {
|
|
||||||
chartDeviation.current.style.backgroundColor = tailwindConfig().theme.colors.emerald[500];
|
|
||||||
}
|
|
||||||
chartDeviation.current.innerHTML = `${diff > 0 ? '+' : ''}${diff.toFixed(2)}%`;
|
|
||||||
}, [data]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<React.Fragment>
|
|
||||||
<div className="px-5 py-3">
|
|
||||||
<div className="flex items-start">
|
|
||||||
<div className="text-3xl font-bold text-slate-800 mr-2 tabular-nums">$<span ref={chartValue}>57.81</span></div>
|
|
||||||
<div ref={chartDeviation} className="text-sm font-semibold text-white px-1.5 rounded-full"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="grow">
|
|
||||||
<canvas ref={canvas} data={data} width={width} height={height}></canvas>
|
|
||||||
</div>
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default RealtimeChart;
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
|
|
||||||
function AccordionBasic(props) {
|
|
||||||
|
|
||||||
const [open, setOpen] = useState(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="px-5 py-4 rounded-sm border border-slate-200">
|
|
||||||
<button
|
|
||||||
className="flex items-center justify-between w-full group mb-1"
|
|
||||||
aria-expanded={open}
|
|
||||||
onClick={() => setOpen(!open)}
|
|
||||||
>
|
|
||||||
<div className="text-sm text-slate-800 font-medium">{props.title}</div>
|
|
||||||
<svg className={`w-8 h-8 shrink-0 fill-current text-slate-400 group-hover:text-slate-500 ml-3 ${open && 'rotate-180'}`} viewBox="0 0 32 32">
|
|
||||||
<path d="M16 20l-5.4-5.4 1.4-1.4 4 4 4-4 1.4 1.4z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<div className={`text-sm ${!open && 'hidden'}`}>
|
|
||||||
{props.children}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AccordionBasic;
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
|
|
||||||
function AccordionTableItem(props) {
|
|
||||||
|
|
||||||
const [open, setOpen] = useState(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<tbody className="text-sm">
|
|
||||||
<tr>
|
|
||||||
<td className="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
|
|
||||||
<div className="flex items-center text-slate-800">
|
|
||||||
<div className="w-10 h-10 shrink-0 flex items-center justify-center bg-slate-100 rounded-full mr-2 sm:mr-3">
|
|
||||||
<img className="rounded-full ml-1" src={props.image} width="40" height="40" alt={props.customer} />
|
|
||||||
</div>
|
|
||||||
<div className="font-medium text-slate-800">{props.customer}</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td className="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
|
|
||||||
<div className="text-left font-medium text-emerald-500">{props.total}</div>
|
|
||||||
</td>
|
|
||||||
<td className="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
|
|
||||||
<div className="inline-flex font-medium bg-amber-100 text-amber-600 rounded-full text-center px-2.5 py-0.5">{props.status}</div>
|
|
||||||
</td>
|
|
||||||
<td className="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
|
|
||||||
<div className="text-center">{props.items}</div>
|
|
||||||
</td>
|
|
||||||
<td className="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
|
|
||||||
<div className="text-left">{props.location}</div>
|
|
||||||
</td>
|
|
||||||
<td className="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
|
|
||||||
<div className="flex items-center">
|
|
||||||
<svg className="w-4 h-4 fill-current text-slate-400 shrink-0 mr-2" viewBox="0 0 16 16">
|
|
||||||
<path d="M4.3 4.5c1.9-1.9 5.1-1.9 7 0 .7.7 1.2 1.7 1.4 2.7l2-.3c-.2-1.5-.9-2.8-1.9-3.8C10.1.4 5.7.4 2.9 3.1L.7.9 0 7.3l6.4-.7-2.1-2.1zM15.6 8.7l-6.4.7 2.1 2.1c-1.9 1.9-5.1 1.9-7 0-.7-.7-1.2-1.7-1.4-2.7l-2 .3c.2 1.5.9 2.8 1.9 3.8 1.4 1.4 3.1 2 4.9 2 1.8 0 3.6-.7 4.9-2l2.2 2.2.8-6.4z" />
|
|
||||||
</svg>
|
|
||||||
<div>{props.type}</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td className="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap w-px">
|
|
||||||
<div className="flex items-center">
|
|
||||||
<button
|
|
||||||
className={`text-slate-400 hover:text-slate-500 transform ${open && 'rotate-180'}`}
|
|
||||||
aria-expanded={open}
|
|
||||||
onClick={() => setOpen(!open)}
|
|
||||||
aria-controls={`description-${props.id}`}
|
|
||||||
>
|
|
||||||
<span className="sr-only">Menu</span>
|
|
||||||
<svg className="w-8 h-8 fill-current" viewBox="0 0 32 32">
|
|
||||||
<path d="M16 20l-5.4-5.4 1.4-1.4 4 4 4-4 1.4 1.4z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{/*
|
|
||||||
Example of content revealing when clicking the button on the right side:
|
|
||||||
Note that you must set a "colSpan" attribute on the <td> element,
|
|
||||||
and it should match the number of columns in your table
|
|
||||||
*/}
|
|
||||||
<tr id={`description-${props.id}`} role="region" className={`${!open && 'hidden'}`}>
|
|
||||||
<td colSpan="10" className="px-2 first:pl-5 last:pr-5 py-3">
|
|
||||||
<div className="flex items-center bg-slate-50 p-3 -mt-3">
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current text-slate-400 mr-2">
|
|
||||||
<path d="M1 16h3c.3 0 .5-.1.7-.3l11-11c.4-.4.4-1 0-1.4l-3-3c-.4-.4-1-.4-1.4 0l-11 11c-.2.2-.3.4-.3.7v3c0 .6.4 1 1 1zm1-3.6l10-10L13.6 4l-10 10H2v-1.6z" />
|
|
||||||
</svg>
|
|
||||||
<div className="italic">{props.description}</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AccordionTableItem;
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
|
|
||||||
function AccordionTableRichItem(props) {
|
|
||||||
|
|
||||||
const [open, setOpen] = useState(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<tbody className="text-sm">
|
|
||||||
<tr>
|
|
||||||
<td className="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
|
|
||||||
<div className="flex items-center text-slate-800">
|
|
||||||
<div className="w-10 h-10 shrink-0 flex items-center justify-center bg-slate-100 rounded-full mr-2 sm:mr-3">
|
|
||||||
<img className="rounded-full ml-1" src={props.image} width="40" height="40" alt={props.customer} />
|
|
||||||
</div>
|
|
||||||
<div className="font-medium text-slate-800">{props.customer}</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td className="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
|
|
||||||
<div className="text-left">{props.email}</div>
|
|
||||||
</td>
|
|
||||||
<td className="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
|
|
||||||
<div className="text-left">{props.location}</div>
|
|
||||||
</td>
|
|
||||||
<td className="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
|
|
||||||
<div className="text-left">{props.date}</div>
|
|
||||||
</td>
|
|
||||||
<td className="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap">
|
|
||||||
<div className="text-left text-emerald-500 font-medium">{props.amount}</div>
|
|
||||||
</td>
|
|
||||||
<td className="px-2 first:pl-5 last:pr-5 py-3 whitespace-nowrap w-px">
|
|
||||||
<div className="flex items-center">
|
|
||||||
<button
|
|
||||||
className={`text-slate-400 hover:text-slate-500 transform ${open && 'rotate-180'}`}
|
|
||||||
aria-expanded={open}
|
|
||||||
onClick={() => setOpen(!open)}
|
|
||||||
aria-controls={`description-${props.id}`}
|
|
||||||
>
|
|
||||||
<span className="sr-only">Menu</span>
|
|
||||||
<svg className="w-8 h-8 fill-current" viewBox="0 0 32 32">
|
|
||||||
<path d="M16 20l-5.4-5.4 1.4-1.4 4 4 4-4 1.4 1.4z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{/*
|
|
||||||
Example of content revealing when clicking the button on the right side:
|
|
||||||
Note that you must set a "colSpan" attribute on the <td> element,
|
|
||||||
and it should match the number of columns in your table
|
|
||||||
*/}
|
|
||||||
<tr id={`description-${props.id}`} role="region" className={`${!open && 'hidden'}`}>
|
|
||||||
<td colSpan="10" className="px-2 first:pl-5 last:pr-5 py-3">
|
|
||||||
<div className="bg-slate-50 p-3 -mt-3">
|
|
||||||
<div className="text-sm mb-3">
|
|
||||||
<div className="font-medium text-slate-800 mb-1">{props.descriptionTitle}</div>
|
|
||||||
<div>{props.descriptionBody}</div>
|
|
||||||
</div>
|
|
||||||
<button className="btn-xs bg-indigo-500 hover:bg-indigo-600 text-white">Approve</button>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AccordionTableRichItem;
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
function Banner({
|
|
||||||
children,
|
|
||||||
className,
|
|
||||||
type,
|
|
||||||
open,
|
|
||||||
setOpen
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const typeIcon = (type) => {
|
|
||||||
switch (type) {
|
|
||||||
case 'warning':
|
|
||||||
return (
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current opacity-80 mt-[3px] mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm0 12c-.6 0-1-.4-1-1s.4-1 1-1 1 .4 1 1-.4 1-1 1zm1-3H7V4h2v5z" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
case 'error':
|
|
||||||
return (
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current opacity-80 mt-[3px] mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm3.5 10.1l-1.4 1.4L8 9.4l-2.1 2.1-1.4-1.4L6.6 8 4.5 5.9l1.4-1.4L8 6.6l2.1-2.1 1.4 1.4L9.4 8l2.1 2.1z" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
case 'success':
|
|
||||||
return (
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current opacity-80 mt-[3px] mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zM7 11.4L3.6 8 5 6.6l2 2 4-4L12.4 6 7 11.4z" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
return (
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current opacity-80 mt-[3px] mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm1 12H7V7h2v5zM8 6c-.6 0-1-.4-1-1s.4-1 1-1 1 .4 1 1-.4 1-1 1z" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const typeColor = (type) => {
|
|
||||||
switch (type) {
|
|
||||||
case 'warning':
|
|
||||||
return 'bg-amber-500';
|
|
||||||
case 'error':
|
|
||||||
return 'bg-rose-500';
|
|
||||||
case 'success':
|
|
||||||
return 'bg-emerald-500';
|
|
||||||
default:
|
|
||||||
return 'bg-indigo-500';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{open &&
|
|
||||||
<div className={className}>
|
|
||||||
<div className={`px-4 py-2 rounded-sm text-sm text-white ${typeColor(type)}`}>
|
|
||||||
<div className="flex w-full justify-between items-start">
|
|
||||||
<div className="flex">
|
|
||||||
{typeIcon(type)}
|
|
||||||
<div className="font-medium">
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button className="opacity-70 hover:opacity-80 ml-3 mt-[3px]" onClick={() => setOpen(false)}>
|
|
||||||
<div className="sr-only">Close</div>
|
|
||||||
<svg className="w-4 h-4 fill-current">
|
|
||||||
<path d="M7.95 6.536l4.242-4.243a1 1 0 111.415 1.414L9.364 7.95l4.243 4.242a1 1 0 11-1.415 1.415L7.95 9.364l-4.243 4.243a1 1 0 01-1.414-1.415L6.536 7.95 2.293 3.707a1 1 0 011.414-1.414L7.95 6.536z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Banner;
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
function Banner2({
|
|
||||||
children,
|
|
||||||
className,
|
|
||||||
type,
|
|
||||||
open,
|
|
||||||
setOpen
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const typeIcon = (type) => {
|
|
||||||
switch (type) {
|
|
||||||
case 'warning':
|
|
||||||
return (
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current opacity-80 mt-[3px] mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm0 12c-.6 0-1-.4-1-1s.4-1 1-1 1 .4 1 1-.4 1-1 1zm1-3H7V4h2v5z" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
case 'error':
|
|
||||||
return (
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current opacity-80 mt-[3px] mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm3.5 10.1l-1.4 1.4L8 9.4l-2.1 2.1-1.4-1.4L6.6 8 4.5 5.9l1.4-1.4L8 6.6l2.1-2.1 1.4 1.4L9.4 8l2.1 2.1z" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
case 'success':
|
|
||||||
return (
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current opacity-80 mt-[3px] mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zM7 11.4L3.6 8 5 6.6l2 2 4-4L12.4 6 7 11.4z" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
return (
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current opacity-80 mt-[3px] mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm1 12H7V7h2v5zM8 6c-.6 0-1-.4-1-1s.4-1 1-1 1 .4 1 1-.4 1-1 1z" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const typeColor = (type) => {
|
|
||||||
switch (type) {
|
|
||||||
case 'warning':
|
|
||||||
return 'bg-amber-100 border-amber-200 text-amber-600';
|
|
||||||
case 'error':
|
|
||||||
return 'bg-rose-100 border-rose-200 text-rose-600';
|
|
||||||
case 'success':
|
|
||||||
return 'bg-emerald-100 border-emerald-200 text-emerald-600';
|
|
||||||
default:
|
|
||||||
return 'bg-indigo-100 border-indigo-200 text-indigo-500';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{open &&
|
|
||||||
<div className={className}>
|
|
||||||
<div className={`px-4 py-2 rounded-sm text-sm border ${typeColor(type)}`}>
|
|
||||||
<div className="flex w-full justify-between items-start">
|
|
||||||
<div className="flex">
|
|
||||||
{typeIcon(type)}
|
|
||||||
<div>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button className="opacity-70 hover:opacity-80 ml-3 mt-[3px]" onClick={() => setOpen(false)}>
|
|
||||||
<div className="sr-only">Close</div>
|
|
||||||
<svg className="w-4 h-4 fill-current">
|
|
||||||
<path d="M7.95 6.536l4.242-4.243a1 1 0 111.415 1.414L9.364 7.95l4.243 4.242a1 1 0 11-1.415 1.415L7.95 9.364l-4.243 4.243a1 1 0 01-1.414-1.415L6.536 7.95 2.293 3.707a1 1 0 011.414-1.414L7.95 6.536z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Banner2;
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
import React, { useState, useRef, useEffect } from 'react';
|
|
||||||
import Transition from '../utils/Transition';
|
|
||||||
|
|
||||||
function DateSelect() {
|
|
||||||
|
|
||||||
const options = [
|
|
||||||
{
|
|
||||||
id: 0,
|
|
||||||
period: 'Today'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
period: 'Last 7 Days'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
period: 'Last Month'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
period: 'Last 12 Months'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
period: 'All Time'
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
const [dropdownOpen, setDropdownOpen] = useState(false);
|
|
||||||
const [selected, setSelected] = useState(2);
|
|
||||||
|
|
||||||
const trigger = useRef(null);
|
|
||||||
const dropdown = useRef(null);
|
|
||||||
|
|
||||||
// close on click outside
|
|
||||||
useEffect(() => {
|
|
||||||
const clickHandler = ({ target }) => {
|
|
||||||
if (!dropdown.current) return;
|
|
||||||
if (!dropdownOpen || dropdown.current.contains(target) || trigger.current.contains(target)) return;
|
|
||||||
setDropdownOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('click', clickHandler);
|
|
||||||
return () => document.removeEventListener('click', clickHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
// close if the esc key is pressed
|
|
||||||
useEffect(() => {
|
|
||||||
const keyHandler = ({ keyCode }) => {
|
|
||||||
if (!dropdownOpen || keyCode !== 27) return;
|
|
||||||
setDropdownOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('keydown', keyHandler);
|
|
||||||
return () => document.removeEventListener('keydown', keyHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="relative">
|
|
||||||
<button
|
|
||||||
ref={trigger}
|
|
||||||
className="btn justify-between min-w-44 bg-white border-slate-200 hover:border-slate-300 text-slate-500 hover:text-slate-600"
|
|
||||||
aria-label="Select date range"
|
|
||||||
aria-haspopup="true"
|
|
||||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
|
||||||
aria-expanded={dropdownOpen}
|
|
||||||
>
|
|
||||||
<span className="flex items-center">
|
|
||||||
<svg className="w-4 h-4 fill-current text-slate-500 shrink-0 mr-2" viewBox="0 0 16 16">
|
|
||||||
<path d="M15 2h-2V0h-2v2H9V0H7v2H5V0H3v2H1a1 1 0 00-1 1v12a1 1 0 001 1h14a1 1 0 001-1V3a1 1 0 00-1-1zm-1 12H2V6h12v8z" />
|
|
||||||
</svg>
|
|
||||||
<span>{options[selected].period}</span>
|
|
||||||
</span>
|
|
||||||
<svg className="shrink-0 ml-1 fill-current text-slate-400" width="11" height="7" viewBox="0 0 11 7">
|
|
||||||
<path d="M5.4 6.8L0 1.4 1.4 0l4 4 4-4 1.4 1.4z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<Transition
|
|
||||||
show={dropdownOpen}
|
|
||||||
tag="div"
|
|
||||||
className="z-10 absolute top-full right-0 w-full bg-white border border-slate-200 py-1.5 rounded shadow-lg overflow-hidden mt-1"
|
|
||||||
enter="transition ease-out duration-100 transform"
|
|
||||||
enterStart="opacity-0 -translate-y-2"
|
|
||||||
enterEnd="opacity-100 translate-y-0"
|
|
||||||
leave="transition ease-out duration-100"
|
|
||||||
leaveStart="opacity-100"
|
|
||||||
leaveEnd="opacity-0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
ref={dropdown}
|
|
||||||
className="font-medium text-sm text-slate-600"
|
|
||||||
onFocus={() => setDropdownOpen(true)}
|
|
||||||
onBlur={() => setDropdownOpen(false)}
|
|
||||||
>
|
|
||||||
{
|
|
||||||
options.map(option => {
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
key={option.id}
|
|
||||||
tabIndex="0"
|
|
||||||
className={`flex items-center w-full hover:bg-slate-50 py-1 px-3 cursor-pointer ${option.id === selected && 'text-indigo-500'}`}
|
|
||||||
onClick={() => { setSelected(option.id); setDropdownOpen(false); }}
|
|
||||||
>
|
|
||||||
<svg className={`shrink-0 mr-2 fill-current text-indigo-500 ${option.id !== selected && 'invisible'}`} width="12" height="9" viewBox="0 0 12 9">
|
|
||||||
<path d="M10.28.28L3.989 6.575 1.695 4.28A1 1 0 00.28 5.695l3 3a1 1 0 001.414 0l7-7A1 1 0 0010.28.28z" />
|
|
||||||
</svg>
|
|
||||||
<span>{option.period}</span>
|
|
||||||
</button>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</Transition>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DateSelect;
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import Flatpickr from 'react-flatpickr';
|
|
||||||
|
|
||||||
function Datepicker({
|
|
||||||
align
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const options = {
|
|
||||||
mode: 'range',
|
|
||||||
static: true,
|
|
||||||
monthSelectorType: 'static',
|
|
||||||
dateFormat: 'M j, Y',
|
|
||||||
defaultDate: [new Date().setDate(new Date().getDate() - 6), new Date()],
|
|
||||||
prevArrow: '<svg class="fill-current" width="7" height="11" viewBox="0 0 7 11"><path d="M5.4 10.8l1.4-1.4-4-4 4-4L5.4 0 0 5.4z" /></svg>',
|
|
||||||
nextArrow: '<svg class="fill-current" width="7" height="11" viewBox="0 0 7 11"><path d="M1.4 10.8L0 9.4l4-4-4-4L1.4 0l5.4 5.4z" /></svg>',
|
|
||||||
onReady: (selectedDates, dateStr, instance) => {
|
|
||||||
instance.element.value = dateStr.replace('to', '-');
|
|
||||||
const customClass = (align) ? align : '';
|
|
||||||
instance.calendarContainer.classList.add(`flatpickr-${customClass}`);
|
|
||||||
},
|
|
||||||
onChange: (selectedDates, dateStr, instance) => {
|
|
||||||
instance.element.value = dateStr.replace('to', '-');
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="relative">
|
|
||||||
<Flatpickr className="form-input pl-9 text-slate-500 hover:text-slate-600 font-medium focus:border-slate-300 w-60" options={options} />
|
|
||||||
<div className="absolute inset-0 right-auto flex items-center pointer-events-none">
|
|
||||||
<svg className="w-4 h-4 fill-current text-slate-500 ml-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M15 2h-2V0h-2v2H9V0H7v2H5V0H3v2H1a1 1 0 00-1 1v12a1 1 0 001 1h14a1 1 0 001-1V3a1 1 0 00-1-1zm-1 12H2V6h12v8z" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Datepicker;
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
import React, { useState, useRef, useEffect } from 'react';
|
|
||||||
import Transition from '../utils/Transition';
|
|
||||||
|
|
||||||
function DropdownClassic() {
|
|
||||||
|
|
||||||
const options = [
|
|
||||||
{
|
|
||||||
id: 0,
|
|
||||||
period: 'Today'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
period: 'Last 7 Days'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
period: 'Last Month'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
period: 'Last 12 Months'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
period: 'All Time'
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
const [dropdownOpen, setDropdownOpen] = useState(false);
|
|
||||||
const [selected, setSelected] = useState(2);
|
|
||||||
|
|
||||||
const trigger = useRef(null);
|
|
||||||
const dropdown = useRef(null);
|
|
||||||
|
|
||||||
// close on click outside
|
|
||||||
useEffect(() => {
|
|
||||||
const clickHandler = ({ target }) => {
|
|
||||||
if (!dropdown.current) return;
|
|
||||||
if (!dropdownOpen || dropdown.current.contains(target) || trigger.current.contains(target)) return;
|
|
||||||
setDropdownOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('click', clickHandler);
|
|
||||||
return () => document.removeEventListener('click', clickHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
// close if the esc key is pressed
|
|
||||||
useEffect(() => {
|
|
||||||
const keyHandler = ({ keyCode }) => {
|
|
||||||
if (!dropdownOpen || keyCode !== 27) return;
|
|
||||||
setDropdownOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('keydown', keyHandler);
|
|
||||||
return () => document.removeEventListener('keydown', keyHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="relative inline-flex">
|
|
||||||
<button
|
|
||||||
ref={trigger}
|
|
||||||
className="btn justify-between min-w-44 bg-white border-slate-200 hover:border-slate-300 text-slate-500 hover:text-slate-600"
|
|
||||||
aria-label="Select date range"
|
|
||||||
aria-haspopup="true"
|
|
||||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
|
||||||
aria-expanded={dropdownOpen}
|
|
||||||
>
|
|
||||||
<span className="flex items-center">
|
|
||||||
<span>{options[selected].period}</span>
|
|
||||||
</span>
|
|
||||||
<svg className="shrink-0 ml-1 fill-current text-slate-400" width="11" height="7" viewBox="0 0 11 7">
|
|
||||||
<path d="M5.4 6.8L0 1.4 1.4 0l4 4 4-4 1.4 1.4z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<Transition
|
|
||||||
show={dropdownOpen}
|
|
||||||
tag="div"
|
|
||||||
className="z-10 absolute top-full left-0 w-full bg-white border border-slate-200 py-1.5 rounded shadow-lg overflow-hidden mt-1"
|
|
||||||
enter="transition ease-out duration-100 transform"
|
|
||||||
enterStart="opacity-0 -translate-y-2"
|
|
||||||
enterEnd="opacity-100 translate-y-0"
|
|
||||||
leave="transition ease-out duration-100"
|
|
||||||
leaveStart="opacity-100"
|
|
||||||
leaveEnd="opacity-0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
ref={dropdown}
|
|
||||||
className="font-medium text-sm text-slate-600"
|
|
||||||
onFocus={() => setDropdownOpen(true)}
|
|
||||||
onBlur={() => setDropdownOpen(false)}
|
|
||||||
>
|
|
||||||
{
|
|
||||||
options.map(option => {
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
key={option.id}
|
|
||||||
tabIndex="0"
|
|
||||||
className={`flex items-center w-full hover:bg-slate-50 py-1 px-3 cursor-pointer ${option.id === selected && 'text-indigo-500'}`}
|
|
||||||
onClick={() => { setSelected(option.id); setDropdownOpen(false); }}
|
|
||||||
>
|
|
||||||
<svg className={`shrink-0 mr-2 fill-current text-indigo-500 ${option.id !== selected && 'invisible'}`} width="12" height="9" viewBox="0 0 12 9">
|
|
||||||
<path d="M10.28.28L3.989 6.575 1.695 4.28A1 1 0 00.28 5.695l3 3a1 1 0 001.414 0l7-7A1 1 0 0010.28.28z" />
|
|
||||||
</svg>
|
|
||||||
<span>{option.period}</span>
|
|
||||||
</button>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</Transition>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DropdownClassic;
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
import React, { useState, useRef, useEffect } from 'react';
|
|
||||||
import Transition from '../utils/Transition';
|
|
||||||
|
|
||||||
function DropdownEditMenu({
|
|
||||||
children,
|
|
||||||
align,
|
|
||||||
...rest
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const [dropdownOpen, setDropdownOpen] = useState(false);
|
|
||||||
|
|
||||||
const trigger = useRef(null);
|
|
||||||
const dropdown = useRef(null);
|
|
||||||
|
|
||||||
// close on click outside
|
|
||||||
useEffect(() => {
|
|
||||||
const clickHandler = ({ target }) => {
|
|
||||||
if (!dropdown.current) return;
|
|
||||||
if (!dropdownOpen || dropdown.current.contains(target) || trigger.current.contains(target)) return;
|
|
||||||
setDropdownOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('click', clickHandler);
|
|
||||||
return () => document.removeEventListener('click', clickHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
// close if the esc key is pressed
|
|
||||||
useEffect(() => {
|
|
||||||
const keyHandler = ({ keyCode }) => {
|
|
||||||
if (!dropdownOpen || keyCode !== 27) return;
|
|
||||||
setDropdownOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('keydown', keyHandler);
|
|
||||||
return () => document.removeEventListener('keydown', keyHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div {...rest}>
|
|
||||||
<button
|
|
||||||
ref={trigger}
|
|
||||||
className={`bg-white text-slate-400 hover:text-slate-500 rounded-full ${dropdownOpen && 'bg-slate-100 text-slate-500'}`}
|
|
||||||
aria-haspopup="true"
|
|
||||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
|
||||||
aria-expanded={dropdownOpen}
|
|
||||||
>
|
|
||||||
<span className="sr-only">Menu</span>
|
|
||||||
<svg className="w-8 h-8 fill-current" viewBox="0 0 32 32">
|
|
||||||
<circle cx="16" cy="16" r="2" />
|
|
||||||
<circle cx="10" cy="16" r="2" />
|
|
||||||
<circle cx="22" cy="16" r="2" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<Transition
|
|
||||||
show={dropdownOpen}
|
|
||||||
tag="div"
|
|
||||||
className={`origin-top-right z-10 absolute top-full min-w-36 bg-white border border-slate-200 py-1.5 rounded shadow-lg overflow-hidden mt-1 ${align === 'right' ? 'right-0' : 'left-0'}`}
|
|
||||||
enter="transition ease-out duration-200 transform"
|
|
||||||
enterStart="opacity-0 -translate-y-2"
|
|
||||||
enterEnd="opacity-100 translate-y-0"
|
|
||||||
leave="transition ease-out duration-200"
|
|
||||||
leaveStart="opacity-100"
|
|
||||||
leaveEnd="opacity-0"
|
|
||||||
>
|
|
||||||
<ul
|
|
||||||
ref={dropdown}
|
|
||||||
onFocus={() => setDropdownOpen(true)}
|
|
||||||
onBlur={() => setDropdownOpen(false)}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</ul>
|
|
||||||
</Transition>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DropdownEditMenu;
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
import React, { useState, useRef, useEffect } from 'react';
|
|
||||||
import Transition from '../utils/Transition';
|
|
||||||
|
|
||||||
function DropdownFilter({
|
|
||||||
align
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const [dropdownOpen, setDropdownOpen] = useState(false);
|
|
||||||
|
|
||||||
const trigger = useRef(null);
|
|
||||||
const dropdown = useRef(null);
|
|
||||||
|
|
||||||
// close on click outside
|
|
||||||
useEffect(() => {
|
|
||||||
const clickHandler = ({ target }) => {
|
|
||||||
if (!dropdown.current) return;
|
|
||||||
if (!dropdownOpen || dropdown.current.contains(target) || trigger.current.contains(target)) return;
|
|
||||||
setDropdownOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('click', clickHandler);
|
|
||||||
return () => document.removeEventListener('click', clickHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
// close if the esc key is pressed
|
|
||||||
useEffect(() => {
|
|
||||||
const keyHandler = ({ keyCode }) => {
|
|
||||||
if (!dropdownOpen || keyCode !== 27) return;
|
|
||||||
setDropdownOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('keydown', keyHandler);
|
|
||||||
return () => document.removeEventListener('keydown', keyHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="relative inline-flex">
|
|
||||||
<button
|
|
||||||
ref={trigger}
|
|
||||||
className="btn bg-white border-slate-200 hover:border-slate-300 text-slate-500 hover:text-slate-600"
|
|
||||||
aria-haspopup="true"
|
|
||||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
|
||||||
aria-expanded={dropdownOpen}
|
|
||||||
>
|
|
||||||
<span className="sr-only">Filter</span><wbr />
|
|
||||||
<svg className="w-4 h-4 fill-current" viewBox="0 0 16 16">
|
|
||||||
<path d="M9 15H7a1 1 0 010-2h2a1 1 0 010 2zM11 11H5a1 1 0 010-2h6a1 1 0 010 2zM13 7H3a1 1 0 010-2h10a1 1 0 010 2zM15 3H1a1 1 0 010-2h14a1 1 0 010 2z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<Transition
|
|
||||||
show={dropdownOpen}
|
|
||||||
tag="div"
|
|
||||||
className={`origin-top-right z-10 absolute top-full min-w-56 bg-white border border-slate-200 pt-1.5 rounded shadow-lg overflow-hidden mt-1 ${align === 'right' ? 'right-0' : 'left-0'}`}
|
|
||||||
enter="transition ease-out duration-200 transform"
|
|
||||||
enterStart="opacity-0 -translate-y-2"
|
|
||||||
enterEnd="opacity-100 translate-y-0"
|
|
||||||
leave="transition ease-out duration-200"
|
|
||||||
leaveStart="opacity-100"
|
|
||||||
leaveEnd="opacity-0"
|
|
||||||
>
|
|
||||||
<div ref={dropdown}>
|
|
||||||
<div className="text-xs font-semibold text-slate-400 uppercase pt-1.5 pb-2 px-4">Filters</div>
|
|
||||||
<ul className="mb-4">
|
|
||||||
<li className="py-1 px-3">
|
|
||||||
<label className="flex items-center">
|
|
||||||
<input type="checkbox" className="form-checkbox" />
|
|
||||||
<span className="text-sm font-medium ml-2">Direct VS Indirect</span>
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
<li className="py-1 px-3">
|
|
||||||
<label className="flex items-center">
|
|
||||||
<input type="checkbox" className="form-checkbox" />
|
|
||||||
<span className="text-sm font-medium ml-2">Real Time Value</span>
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
<li className="py-1 px-3">
|
|
||||||
<label className="flex items-center">
|
|
||||||
<input type="checkbox" className="form-checkbox" />
|
|
||||||
<span className="text-sm font-medium ml-2">Top Channels</span>
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
<li className="py-1 px-3">
|
|
||||||
<label className="flex items-center">
|
|
||||||
<input type="checkbox" className="form-checkbox" />
|
|
||||||
<span className="text-sm font-medium ml-2">Sales VS Refunds</span>
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
<li className="py-1 px-3">
|
|
||||||
<label className="flex items-center">
|
|
||||||
<input type="checkbox" className="form-checkbox" />
|
|
||||||
<span className="text-sm font-medium ml-2">Last Order</span>
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
<li className="py-1 px-3">
|
|
||||||
<label className="flex items-center">
|
|
||||||
<input type="checkbox" className="form-checkbox" />
|
|
||||||
<span className="text-sm font-medium ml-2">Total Spent</span>
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<div className="py-2 px-3 border-t border-slate-200 bg-slate-50">
|
|
||||||
<ul className="flex items-center justify-between">
|
|
||||||
<li>
|
|
||||||
<button className="btn-xs bg-white border-slate-200 hover:border-slate-300 text-slate-500 hover:text-slate-600">Clear</button>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<button className="btn-xs bg-indigo-500 hover:bg-indigo-600 text-white" onClick={() => setDropdownOpen(false)} onBlur={() => setDropdownOpen(false)}>Apply</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Transition>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DropdownFilter;
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
import React, { useState, useRef, useEffect } from 'react';
|
|
||||||
import Transition from '../utils/Transition';
|
|
||||||
|
|
||||||
function DropdownFull() {
|
|
||||||
|
|
||||||
const options = [
|
|
||||||
{
|
|
||||||
id: 0,
|
|
||||||
period: 'Most Popular'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
period: 'Newest'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
period: 'Lowest Price'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
period: 'Highest Price'
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
const [dropdownOpen, setDropdownOpen] = useState(false);
|
|
||||||
const [selected, setSelected] = useState(0);
|
|
||||||
|
|
||||||
const trigger = useRef(null);
|
|
||||||
const dropdown = useRef(null);
|
|
||||||
|
|
||||||
// close on click outside
|
|
||||||
useEffect(() => {
|
|
||||||
const clickHandler = ({ target }) => {
|
|
||||||
if (!dropdown.current) return;
|
|
||||||
if (!dropdownOpen || dropdown.current.contains(target) || trigger.current.contains(target)) return;
|
|
||||||
setDropdownOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('click', clickHandler);
|
|
||||||
return () => document.removeEventListener('click', clickHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
// close if the esc key is pressed
|
|
||||||
useEffect(() => {
|
|
||||||
const keyHandler = ({ keyCode }) => {
|
|
||||||
if (!dropdownOpen || keyCode !== 27) return;
|
|
||||||
setDropdownOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('keydown', keyHandler);
|
|
||||||
return () => document.removeEventListener('keydown', keyHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="relative inline-flex w-full">
|
|
||||||
<button
|
|
||||||
ref={trigger}
|
|
||||||
className="btn w-full justify-between min-w-44 bg-white border-slate-200 hover:border-slate-300 text-slate-500 hover:text-slate-600"
|
|
||||||
aria-label="Select date range"
|
|
||||||
aria-haspopup="true"
|
|
||||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
|
||||||
aria-expanded={dropdownOpen}
|
|
||||||
>
|
|
||||||
<span className="flex items-center">
|
|
||||||
<span>{options[selected].period}</span>
|
|
||||||
</span>
|
|
||||||
<svg className="shrink-0 ml-1 fill-current text-slate-400" width="11" height="7" viewBox="0 0 11 7">
|
|
||||||
<path d="M5.4 6.8L0 1.4 1.4 0l4 4 4-4 1.4 1.4z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<Transition
|
|
||||||
show={dropdownOpen}
|
|
||||||
tag="div"
|
|
||||||
className="z-10 absolute top-full left-0 w-full bg-white border border-slate-200 py-1.5 rounded shadow-lg overflow-hidden mt-1"
|
|
||||||
enter="transition ease-out duration-100 transform"
|
|
||||||
enterStart="opacity-0 -translate-y-2"
|
|
||||||
enterEnd="opacity-100 translate-y-0"
|
|
||||||
leave="transition ease-out duration-100"
|
|
||||||
leaveStart="opacity-100"
|
|
||||||
leaveEnd="opacity-0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
ref={dropdown}
|
|
||||||
className="font-medium text-sm text-slate-600 divide-y divide-slate-200"
|
|
||||||
onFocus={() => setDropdownOpen(true)}
|
|
||||||
onBlur={() => setDropdownOpen(false)}
|
|
||||||
>
|
|
||||||
{
|
|
||||||
options.map(option => {
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
key={option.id}
|
|
||||||
tabIndex="0"
|
|
||||||
className={`flex items-center justify-between w-full hover:bg-slate-50 py-2 px-3 cursor-pointer ${option.id === selected && 'text-indigo-500'}`}
|
|
||||||
onClick={() => { setSelected(option.id); setDropdownOpen(false); }}
|
|
||||||
>
|
|
||||||
<span>{option.period}</span>
|
|
||||||
<svg className={`shrink-0 mr-2 fill-current text-indigo-500 ${option.id !== selected && 'invisible'}`} width="12" height="9" viewBox="0 0 12 9">
|
|
||||||
<path d="M10.28.28L3.989 6.575 1.695 4.28A1 1 0 00.28 5.695l3 3a1 1 0 001.414 0l7-7A1 1 0 0010.28.28z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</Transition>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DropdownFull;
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
import React, { useState, useRef, useEffect } from 'react';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import Transition from '../utils/Transition';
|
|
||||||
|
|
||||||
function DropdownHelp({
|
|
||||||
align
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const [dropdownOpen, setDropdownOpen] = useState(false);
|
|
||||||
|
|
||||||
const trigger = useRef(null);
|
|
||||||
const dropdown = useRef(null);
|
|
||||||
|
|
||||||
// close on click outside
|
|
||||||
useEffect(() => {
|
|
||||||
const clickHandler = ({ target }) => {
|
|
||||||
if (!dropdown.current) return;
|
|
||||||
if (!dropdownOpen || dropdown.current.contains(target) || trigger.current.contains(target)) return;
|
|
||||||
setDropdownOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('click', clickHandler);
|
|
||||||
return () => document.removeEventListener('click', clickHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
// close if the esc key is pressed
|
|
||||||
useEffect(() => {
|
|
||||||
const keyHandler = ({ keyCode }) => {
|
|
||||||
if (!dropdownOpen || keyCode !== 27) return;
|
|
||||||
setDropdownOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('keydown', keyHandler);
|
|
||||||
return () => document.removeEventListener('keydown', keyHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="relative inline-flex">
|
|
||||||
<button
|
|
||||||
ref={trigger}
|
|
||||||
className={`w-8 h-8 flex items-center justify-center bg-slate-100 hover:bg-slate-200 transition duration-150 rounded-full ${dropdownOpen && 'bg-slate-200'}`}
|
|
||||||
aria-haspopup="true"
|
|
||||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
|
||||||
aria-expanded={dropdownOpen}
|
|
||||||
>
|
|
||||||
<span className="sr-only">Need help?</span>
|
|
||||||
<svg className="w-4 h-4" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path className="fill-current text-slate-500" d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm0 12c-.6 0-1-.4-1-1s.4-1 1-1 1 .4 1 1-.4 1-1 1zm1-3H7V4h2v5z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<Transition
|
|
||||||
className={`origin-top-right z-10 absolute top-full min-w-44 bg-white border border-slate-200 py-1.5 rounded shadow-lg overflow-hidden mt-1 ${align === 'right' ? 'right-0' : 'left-0'}`}
|
|
||||||
show={dropdownOpen}
|
|
||||||
enter="transition ease-out duration-200 transform"
|
|
||||||
enterStart="opacity-0 -translate-y-2"
|
|
||||||
enterEnd="opacity-100 translate-y-0"
|
|
||||||
leave="transition ease-out duration-200"
|
|
||||||
leaveStart="opacity-100"
|
|
||||||
leaveEnd="opacity-0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
ref={dropdown}
|
|
||||||
onFocus={() => setDropdownOpen(true)}
|
|
||||||
onBlur={() => setDropdownOpen(false)}
|
|
||||||
>
|
|
||||||
<div className="text-xs font-semibold text-slate-400 uppercase pt-1.5 pb-2 px-4">Need help?</div>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<Link
|
|
||||||
className="font-medium text-sm text-indigo-500 hover:text-indigo-600 flex items-center py-1 px-3"
|
|
||||||
to="#0"
|
|
||||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
|
||||||
>
|
|
||||||
<svg className="w-3 h-3 fill-current text-indigo-300 shrink-0 mr-2" viewBox="0 0 12 12">
|
|
||||||
<rect y="3" width="12" height="9" rx="1" />
|
|
||||||
<path d="M2 0h8v2H2z" />
|
|
||||||
</svg>
|
|
||||||
<span>Documentation</span>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Link
|
|
||||||
className="font-medium text-sm text-indigo-500 hover:text-indigo-600 flex items-center py-1 px-3"
|
|
||||||
to="#0"
|
|
||||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
|
||||||
>
|
|
||||||
<svg className="w-3 h-3 fill-current text-indigo-300 shrink-0 mr-2" viewBox="0 0 12 12">
|
|
||||||
<path d="M10.5 0h-9A1.5 1.5 0 000 1.5v9A1.5 1.5 0 001.5 12h9a1.5 1.5 0 001.5-1.5v-9A1.5 1.5 0 0010.5 0zM10 7L8.207 5.207l-3 3-1.414-1.414 3-3L5 2h5v5z" />
|
|
||||||
</svg>
|
|
||||||
<span>Support Site</span>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Link
|
|
||||||
className="font-medium text-sm text-indigo-500 hover:text-indigo-600 flex items-center py-1 px-3"
|
|
||||||
to="#0"
|
|
||||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
|
||||||
>
|
|
||||||
<svg className="w-3 h-3 fill-current text-indigo-300 shrink-0 mr-2" viewBox="0 0 12 12">
|
|
||||||
<path d="M11.854.146a.5.5 0 00-.525-.116l-11 4a.5.5 0 00-.015.934l4.8 1.921 1.921 4.8A.5.5 0 007.5 12h.008a.5.5 0 00.462-.329l4-11a.5.5 0 00-.116-.525z" />
|
|
||||||
</svg>
|
|
||||||
<span>Contact us</span>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</Transition>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DropdownHelp;
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
import React, { useState, useRef, useEffect } from 'react';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import Transition from '../utils/Transition';
|
|
||||||
|
|
||||||
function DropdownNotifications({
|
|
||||||
align
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const [dropdownOpen, setDropdownOpen] = useState(false);
|
|
||||||
|
|
||||||
const trigger = useRef(null);
|
|
||||||
const dropdown = useRef(null);
|
|
||||||
|
|
||||||
// close on click outside
|
|
||||||
useEffect(() => {
|
|
||||||
const clickHandler = ({ target }) => {
|
|
||||||
if (!dropdown.current) return;
|
|
||||||
if (!dropdownOpen || dropdown.current.contains(target) || trigger.current.contains(target)) return;
|
|
||||||
setDropdownOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('click', clickHandler);
|
|
||||||
return () => document.removeEventListener('click', clickHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
// close if the esc key is pressed
|
|
||||||
useEffect(() => {
|
|
||||||
const keyHandler = ({ keyCode }) => {
|
|
||||||
if (!dropdownOpen || keyCode !== 27) return;
|
|
||||||
setDropdownOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('keydown', keyHandler);
|
|
||||||
return () => document.removeEventListener('keydown', keyHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="relative inline-flex">
|
|
||||||
<button
|
|
||||||
ref={trigger}
|
|
||||||
className={`w-8 h-8 flex items-center justify-center bg-slate-100 hover:bg-slate-200 transition duration-150 rounded-full ${dropdownOpen && 'bg-slate-200'}`}
|
|
||||||
aria-haspopup="true"
|
|
||||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
|
||||||
aria-expanded={dropdownOpen}
|
|
||||||
>
|
|
||||||
<span className="sr-only">Notifications</span>
|
|
||||||
<svg className="w-4 h-4" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path className="fill-current text-slate-500" d="M6.5 0C2.91 0 0 2.462 0 5.5c0 1.075.37 2.074 1 2.922V12l2.699-1.542A7.454 7.454 0 006.5 11c3.59 0 6.5-2.462 6.5-5.5S10.09 0 6.5 0z" />
|
|
||||||
<path className="fill-current text-slate-400" d="M16 9.5c0-.987-.429-1.897-1.147-2.639C14.124 10.348 10.66 13 6.5 13c-.103 0-.202-.018-.305-.021C7.231 13.617 8.556 14 10 14c.449 0 .886-.04 1.307-.11L15 16v-4h-.012C15.627 11.285 16 10.425 16 9.5z" />
|
|
||||||
</svg>
|
|
||||||
<div className="absolute top-0 right-0 w-2.5 h-2.5 bg-rose-500 border-2 border-white rounded-full"></div>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<Transition
|
|
||||||
className={`origin-top-right z-10 absolute top-full -mr-48 sm:mr-0 min-w-80 bg-white border border-slate-200 py-1.5 rounded shadow-lg overflow-hidden mt-1 ${align === 'right' ? 'right-0' : 'left-0'}`}
|
|
||||||
show={dropdownOpen}
|
|
||||||
enter="transition ease-out duration-200 transform"
|
|
||||||
enterStart="opacity-0 -translate-y-2"
|
|
||||||
enterEnd="opacity-100 translate-y-0"
|
|
||||||
leave="transition ease-out duration-200"
|
|
||||||
leaveStart="opacity-100"
|
|
||||||
leaveEnd="opacity-0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
ref={dropdown}
|
|
||||||
onFocus={() => setDropdownOpen(true)}
|
|
||||||
onBlur={() => setDropdownOpen(false)}
|
|
||||||
>
|
|
||||||
<div className="text-xs font-semibold text-slate-400 uppercase pt-1.5 pb-2 px-4">Notifications</div>
|
|
||||||
<ul>
|
|
||||||
<li className="border-b border-slate-200 last:border-0">
|
|
||||||
<Link
|
|
||||||
className="block py-2 px-4 hover:bg-slate-50"
|
|
||||||
to="#0"
|
|
||||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
|
||||||
>
|
|
||||||
<span className="block text-sm mb-2">📣 <span className="font-medium text-slate-800">Edit your information in a swipe</span> Sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim.</span>
|
|
||||||
<span className="block text-xs font-medium text-slate-400">Feb 12, 2021</span>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
<li className="border-b border-slate-200 last:border-0">
|
|
||||||
<Link
|
|
||||||
className="block py-2 px-4 hover:bg-slate-50"
|
|
||||||
to="#0"
|
|
||||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
|
||||||
>
|
|
||||||
<span className="block text-sm mb-2">📣 <span className="font-medium text-slate-800">Edit your information in a swipe</span> Sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim.</span>
|
|
||||||
<span className="block text-xs font-medium text-slate-400">Feb 9, 2021</span>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
<li className="border-b border-slate-200 last:border-0">
|
|
||||||
<Link
|
|
||||||
className="block py-2 px-4 hover:bg-slate-50"
|
|
||||||
to="#0"
|
|
||||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
|
||||||
>
|
|
||||||
<span className="block text-sm mb-2">🚀<span className="font-medium text-slate-800">Say goodbye to paper receipts!</span> Sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim.</span>
|
|
||||||
<span className="block text-xs font-medium text-slate-400">Jan 24, 2020</span>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</Transition>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DropdownNotifications;
|
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
import React, { useState, useRef, useEffect } from 'react';
|
import React, { useState, useRef, useEffect } from 'react';
|
||||||
|
import {observer} from "mobx-react-lite";
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import Transition from '../utils/Transition';
|
import Transition from '../utils/Transition';
|
||||||
|
import {store} from "../store/store";
|
||||||
|
import {generateSvgAvatar} from "../images/GenerateOnboardingSvg/GenerateSvg";
|
||||||
import UserAvatar from '../images/user-avatar-32.png';
|
import UserAvatar from '../images/user-avatar-32.png';
|
||||||
|
|
||||||
function DropdownProfile({
|
const DropdownProfile = observer(({
|
||||||
align
|
align
|
||||||
}) {
|
})=>{
|
||||||
|
|
||||||
const [dropdownOpen, setDropdownOpen] = useState(false);
|
const [dropdownOpen, setDropdownOpen] = useState(false);
|
||||||
|
|
||||||
@@ -34,6 +36,11 @@ function DropdownProfile({
|
|||||||
return () => document.removeEventListener('keydown', keyHandler);
|
return () => document.removeEventListener('keydown', keyHandler);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const logOut = () => {
|
||||||
|
sessionStorage.removeItem('passPhrase')
|
||||||
|
store.fetchPassPhrase()
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative inline-flex">
|
<div className="relative inline-flex">
|
||||||
<button
|
<button
|
||||||
@@ -43,9 +50,9 @@ function DropdownProfile({
|
|||||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
onClick={() => setDropdownOpen(!dropdownOpen)}
|
||||||
aria-expanded={dropdownOpen}
|
aria-expanded={dropdownOpen}
|
||||||
>
|
>
|
||||||
<img className="w-8 h-8 rounded-full" src={UserAvatar} width="32" height="32" alt="User" />
|
<img className="w-8 h-8 rounded-full" src={generateSvgAvatar(store.pubKey) || UserAvatar} width="32" height="32" alt="User" />
|
||||||
<div className="flex items-center truncate">
|
<div className="flex items-center truncate">
|
||||||
<span className="truncate ml-2 text-sm font-medium group-hover:text-slate-800">Acme Inc.</span>
|
<span className="truncate ml-2 text-sm font-medium group-hover:text-slate-800">{store.accountName}</span>
|
||||||
<svg className="w-3 h-3 shrink-0 ml-1 fill-current text-slate-400" viewBox="0 0 12 12">
|
<svg className="w-3 h-3 shrink-0 ml-1 fill-current text-slate-400" viewBox="0 0 12 12">
|
||||||
<path d="M5.9 11.4L.5 6l1.4-1.4 4 4 4-4L11.3 6z" />
|
<path d="M5.9 11.4L.5 6l1.4-1.4 4 4 4-4L11.3 6z" />
|
||||||
</svg>
|
</svg>
|
||||||
@@ -68,24 +75,22 @@ function DropdownProfile({
|
|||||||
onBlur={() => setDropdownOpen(false)}
|
onBlur={() => setDropdownOpen(false)}
|
||||||
>
|
>
|
||||||
<div className="pt-0.5 pb-2 px-3 mb-1 border-b border-slate-200">
|
<div className="pt-0.5 pb-2 px-3 mb-1 border-b border-slate-200">
|
||||||
<div className="font-medium text-slate-800">Acme Inc.</div>
|
<div className="font-medium text-slate-800">{store.accountName}</div>
|
||||||
<div className="text-xs text-slate-500 italic">Administrator</div>
|
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<Link
|
<span
|
||||||
className="font-medium text-sm text-indigo-500 hover:text-indigo-600 flex items-center py-1 px-3"
|
className="cursor-pointer font-medium text-sm text-indigo-500 hover:text-indigo-600 flex items-center py-1 px-3"
|
||||||
to="/settings"
|
|
||||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
onClick={() => setDropdownOpen(!dropdownOpen)}
|
||||||
>
|
>
|
||||||
Settings
|
Settings
|
||||||
</Link>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Link
|
<Link
|
||||||
className="font-medium text-sm text-indigo-500 hover:text-indigo-600 flex items-center py-1 px-3"
|
className="font-medium text-sm text-indigo-500 hover:text-indigo-600 flex items-center py-1 px-3"
|
||||||
to="/signin"
|
to="/"
|
||||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
onClick={() => logOut()}
|
||||||
>
|
>
|
||||||
Sign Out
|
Sign Out
|
||||||
</Link>
|
</Link>
|
||||||
@@ -95,6 +100,6 @@ function DropdownProfile({
|
|||||||
</Transition>
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
|
|
||||||
export default DropdownProfile;
|
export default DropdownProfile;
|
||||||
|
|||||||
@@ -1,90 +0,0 @@
|
|||||||
import React, { useState, useRef, useEffect } from 'react';
|
|
||||||
import Transition from '../utils/Transition';
|
|
||||||
|
|
||||||
function DropdownSort({
|
|
||||||
align
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const [dropdownOpen, setDropdownOpen] = useState(false);
|
|
||||||
|
|
||||||
const trigger = useRef(null);
|
|
||||||
const dropdown = useRef(null);
|
|
||||||
|
|
||||||
// close on click outside
|
|
||||||
useEffect(() => {
|
|
||||||
const clickHandler = ({ target }) => {
|
|
||||||
if (!dropdown.current) return;
|
|
||||||
if (!dropdownOpen || dropdown.current.contains(target) || trigger.current.contains(target)) return;
|
|
||||||
setDropdownOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('click', clickHandler);
|
|
||||||
return () => document.removeEventListener('click', clickHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
// close if the esc key is pressed
|
|
||||||
useEffect(() => {
|
|
||||||
const keyHandler = ({ keyCode }) => {
|
|
||||||
if (!dropdownOpen || keyCode !== 27) return;
|
|
||||||
setDropdownOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('keydown', keyHandler);
|
|
||||||
return () => document.removeEventListener('keydown', keyHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="relative inline-flex">
|
|
||||||
<button
|
|
||||||
ref={trigger}
|
|
||||||
className="inline-flex justify-center items-center group"
|
|
||||||
aria-haspopup="true"
|
|
||||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
|
||||||
aria-expanded={dropdownOpen}
|
|
||||||
>
|
|
||||||
<div className="flex items-center truncate">
|
|
||||||
<span className="truncate font-medium text-indigo-500 group-hover:text-indigo-600">Newest</span>
|
|
||||||
<svg className="w-3 h-3 shrink-0 ml-1 fill-current text-slate-400" viewBox="0 0 12 12">
|
|
||||||
<path d="M5.9 11.4L.5 6l1.4-1.4 4 4 4-4L11.3 6z" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<Transition
|
|
||||||
className={`origin-top-right z-10 absolute top-full bg-white border border-slate-200 py-1.5 rounded shadow-lg overflow-hidden mt-1 ${
|
|
||||||
align === 'right' ? 'right-0' : 'left-0'
|
|
||||||
}`}
|
|
||||||
show={dropdownOpen}
|
|
||||||
enter="transition ease-out duration-200 transform"
|
|
||||||
enterStart="opacity-0 -translate-y-2"
|
|
||||||
enterEnd="opacity-100 translate-y-0"
|
|
||||||
leave="transition ease-out duration-200"
|
|
||||||
leaveStart="opacity-100"
|
|
||||||
leaveEnd="opacity-0"
|
|
||||||
>
|
|
||||||
<div ref={dropdown} onFocus={() => setDropdownOpen(true)} onBlur={() => setDropdownOpen(false)}>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
className="font-medium text-sm text-slate-600 hover:text-slate-800 flex items-center py-1 px-3"
|
|
||||||
href="#0"
|
|
||||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
|
||||||
>
|
|
||||||
Oldest
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
className="font-medium text-sm text-slate-600 hover:text-slate-800 flex items-center py-1 px-3"
|
|
||||||
href="#0"
|
|
||||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
|
||||||
>
|
|
||||||
Popular
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</Transition>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DropdownSort;
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
import React, { useState, useRef, useEffect } from 'react';
|
|
||||||
import Transition from '../utils/Transition';
|
|
||||||
|
|
||||||
import DropdownImage from '../images/user-avatar-32.png';
|
|
||||||
import DropdownImage01 from '../images/channel-01.png';
|
|
||||||
import DropdownImage02 from '../images/channel-02.png';
|
|
||||||
import DropdownImage03 from '../images/channel-03.png';
|
|
||||||
|
|
||||||
function DropdownSwitch({
|
|
||||||
align
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const [dropdownOpen, setDropdownOpen] = useState(false);
|
|
||||||
|
|
||||||
const trigger = useRef(null);
|
|
||||||
const dropdown = useRef(null);
|
|
||||||
|
|
||||||
// close on click outside
|
|
||||||
useEffect(() => {
|
|
||||||
const clickHandler = ({ target }) => {
|
|
||||||
if (!dropdown.current) return;
|
|
||||||
if (!dropdownOpen || dropdown.current.contains(target) || trigger.current.contains(target)) return;
|
|
||||||
setDropdownOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('click', clickHandler);
|
|
||||||
return () => document.removeEventListener('click', clickHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
// close if the esc key is pressed
|
|
||||||
useEffect(() => {
|
|
||||||
const keyHandler = ({ keyCode }) => {
|
|
||||||
if (!dropdownOpen || keyCode !== 27) return;
|
|
||||||
setDropdownOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('keydown', keyHandler);
|
|
||||||
return () => document.removeEventListener('keydown', keyHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="relative">
|
|
||||||
<button
|
|
||||||
ref={trigger}
|
|
||||||
className="grow flex items-center truncate"
|
|
||||||
aria-haspopup="true"
|
|
||||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
|
||||||
aria-expanded={dropdownOpen}
|
|
||||||
>
|
|
||||||
<img className="w-8 h-8 rounded-full mr-2" src={DropdownImage} width="32" height="32" alt="Group 01" />
|
|
||||||
<div className="truncate">
|
|
||||||
<span className="text-sm font-medium">Acme Inc.</span>
|
|
||||||
</div>
|
|
||||||
<svg className="w-3 h-3 shrink-0 ml-1 fill-current text-slate-400" viewBox="0 0 12 12">
|
|
||||||
<path d="M5.9 11.4L.5 6l1.4-1.4 4 4 4-4L11.3 6z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<Transition
|
|
||||||
className={`origin-top-right z-10 absolute top-full min-w-60 bg-white border border-slate-200 py-1.5 rounded shadow-lg overflow-hidden mt-1 ${align === 'right' ? 'right-0' : 'left-0'}`}
|
|
||||||
show={dropdownOpen}
|
|
||||||
enter="transition ease-out duration-200 transform"
|
|
||||||
enterStart="opacity-0 -translate-y-2"
|
|
||||||
enterEnd="opacity-100 translate-y-0"
|
|
||||||
leave="transition ease-out duration-200"
|
|
||||||
leaveStart="opacity-100"
|
|
||||||
leaveEnd="opacity-0"
|
|
||||||
>
|
|
||||||
<ul
|
|
||||||
ref={dropdown}
|
|
||||||
onFocus={() => setDropdownOpen(true)}
|
|
||||||
onBlur={() => setDropdownOpen(false)}
|
|
||||||
>
|
|
||||||
<li>
|
|
||||||
<a className="font-medium text-sm text-slate-600 hover:text-slate-800 block py-1.5 px-3" href="#0" onClick={() => setDropdownOpen(false)}>
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<div className="grow flex items-center truncate">
|
|
||||||
<img className="w-7 h-7 rounded-full mr-2" src={DropdownImage01} width="28" height="28" alt="Channel 01" />
|
|
||||||
<div className="truncate">Acme Inc.</div>
|
|
||||||
</div>
|
|
||||||
<svg className="w-3 h-3 shrink-0 fill-current text-indigo-500 ml-1" viewBox="0 0 12 12">
|
|
||||||
<path d="M10.28 1.28L3.989 7.575 1.695 5.28A1 1 0 00.28 6.695l3 3a1 1 0 001.414 0l7-7A1 1 0 0010.28 1.28z" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a className="font-medium text-sm text-slate-600 hover:text-slate-800 block py-1.5 px-3" href="#0" onClick={() => setDropdownOpen(false)}>
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<div className="grow flex items-center truncate">
|
|
||||||
<img className="w-7 h-7 rounded-full mr-2" src={DropdownImage02} width="28" height="28" alt="Channel 02" />
|
|
||||||
<div className="truncate">Acme Limited</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a className="font-medium text-sm text-slate-600 hover:text-slate-800 block py-1.5 px-3" href="#0" onClick={() => setDropdownOpen(false)}>
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<div className="grow flex items-center truncate">
|
|
||||||
<img className="w-7 h-7 rounded-full mr-2" src={DropdownImage03} width="28" height="28" alt="Channel 03" />
|
|
||||||
<div className="truncate">Acme Srl</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</Transition>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DropdownSwitch;
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
import React, { useState, useRef, useEffect } from 'react';
|
|
||||||
import Transition from '../utils/Transition';
|
|
||||||
|
|
||||||
function DropdownTransaction({
|
|
||||||
align
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const [dropdownOpen, setDropdownOpen] = useState(false);
|
|
||||||
|
|
||||||
const trigger = useRef(null);
|
|
||||||
const dropdown = useRef(null);
|
|
||||||
|
|
||||||
// close on click outside
|
|
||||||
useEffect(() => {
|
|
||||||
const clickHandler = ({ target }) => {
|
|
||||||
if (!dropdown.current) return;
|
|
||||||
if (!dropdownOpen || dropdown.current.contains(target) || trigger.current.contains(target)) return;
|
|
||||||
setDropdownOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('click', clickHandler);
|
|
||||||
return () => document.removeEventListener('click', clickHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
// close if the esc key is pressed
|
|
||||||
useEffect(() => {
|
|
||||||
const keyHandler = ({ keyCode }) => {
|
|
||||||
if (!dropdownOpen || keyCode !== 27) return;
|
|
||||||
setDropdownOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('keydown', keyHandler);
|
|
||||||
return () => document.removeEventListener('keydown', keyHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="relative inline-flex">
|
|
||||||
<button
|
|
||||||
ref={trigger}
|
|
||||||
className="inline-flex justify-center items-center group"
|
|
||||||
aria-haspopup="true"
|
|
||||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
|
||||||
aria-expanded={dropdownOpen}
|
|
||||||
>
|
|
||||||
<div className="flex items-center truncate">
|
|
||||||
<span className="truncate font-medium text-indigo-500 group-hover:text-indigo-600">My Personal Account</span>
|
|
||||||
<svg className="w-3 h-3 shrink-0 ml-1 fill-current text-slate-400" viewBox="0 0 12 12">
|
|
||||||
<path d="M5.9 11.4L.5 6l1.4-1.4 4 4 4-4L11.3 6z" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<Transition
|
|
||||||
className={`origin-top-right z-10 absolute top-full min-w-44 bg-white border border-slate-200 py-1.5 rounded shadow-lg overflow-hidden mt-1 ${
|
|
||||||
align === 'right' ? 'right-0' : 'left-0'
|
|
||||||
}`}
|
|
||||||
show={dropdownOpen}
|
|
||||||
enter="transition ease-out duration-200 transform"
|
|
||||||
enterStart="opacity-0 -translate-y-2"
|
|
||||||
enterEnd="opacity-100 translate-y-0"
|
|
||||||
leave="transition ease-out duration-200"
|
|
||||||
leaveStart="opacity-100"
|
|
||||||
leaveEnd="opacity-0"
|
|
||||||
>
|
|
||||||
<div ref={dropdown} onFocus={() => setDropdownOpen(true)} onBlur={() => setDropdownOpen(false)}>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
className="font-medium text-sm text-slate-600 hover:text-slate-800 flex items-center py-1 px-3"
|
|
||||||
href="#0"
|
|
||||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
|
||||||
>
|
|
||||||
Business Account
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
className="font-medium text-sm text-slate-600 hover:text-slate-800 flex items-center py-1 px-3"
|
|
||||||
href="#0"
|
|
||||||
onClick={() => setDropdownOpen(!dropdownOpen)}
|
|
||||||
>
|
|
||||||
Family Account
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</Transition>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DropdownTransaction;
|
|
||||||
15
src/components/LoadingOverlay.jsx
Normal file
15
src/components/LoadingOverlay.jsx
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import React from 'react';
|
||||||
|
import {ThreeCircles} from 'react-loader-spinner';
|
||||||
|
|
||||||
|
export const LoadingOverlay = () => ReactDOM.createPortal((
|
||||||
|
<div className='absolute left-0 top-0 h-screen w-screen z-50 loading-overlay'>
|
||||||
|
<ThreeCircles
|
||||||
|
height="100"
|
||||||
|
width="100"
|
||||||
|
color="#6366f1"
|
||||||
|
visible={true}
|
||||||
|
ariaLabel="three-circles-rotating"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
), document.body)
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
import React, { useRef, useEffect } from 'react';
|
|
||||||
import Transition from '../utils/Transition';
|
|
||||||
|
|
||||||
function ModalAction({
|
|
||||||
children,
|
|
||||||
id,
|
|
||||||
modalOpen,
|
|
||||||
setModalOpen
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const modalContent = useRef(null);
|
|
||||||
|
|
||||||
// close on click outside
|
|
||||||
useEffect(() => {
|
|
||||||
const clickHandler = ({ target }) => {
|
|
||||||
if (!modalOpen || modalContent.current.contains(target)) return
|
|
||||||
setModalOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('click', clickHandler);
|
|
||||||
return () => document.removeEventListener('click', clickHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
// close if the esc key is pressed
|
|
||||||
useEffect(() => {
|
|
||||||
const keyHandler = ({ keyCode }) => {
|
|
||||||
if (!modalOpen || keyCode !== 27) return;
|
|
||||||
setModalOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('keydown', keyHandler);
|
|
||||||
return () => document.removeEventListener('keydown', keyHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{/* Modal backdrop */}
|
|
||||||
<Transition
|
|
||||||
className="fixed inset-0 bg-slate-900 bg-opacity-30 z-50 transition-opacity"
|
|
||||||
show={modalOpen}
|
|
||||||
enter="transition ease-out duration-200"
|
|
||||||
enterStart="opacity-0"
|
|
||||||
enterEnd="opacity-100"
|
|
||||||
leave="transition ease-out duration-100"
|
|
||||||
leaveStart="opacity-100"
|
|
||||||
leaveEnd="opacity-0"
|
|
||||||
aria-hidden="true"
|
|
||||||
/>
|
|
||||||
{/* Modal dialog */}
|
|
||||||
<Transition
|
|
||||||
id={id}
|
|
||||||
className="fixed inset-0 z-50 overflow-hidden flex items-center my-4 justify-center transform px-4 sm:px-6"
|
|
||||||
role="dialog"
|
|
||||||
aria-modal="true"
|
|
||||||
show={modalOpen}
|
|
||||||
enter="transition ease-in-out duration-200"
|
|
||||||
enterStart="opacity-0 translate-y-4"
|
|
||||||
enterEnd="opacity-100 translate-y-0"
|
|
||||||
leave="transition ease-in-out duration-200"
|
|
||||||
leaveStart="opacity-100 translate-y-0"
|
|
||||||
leaveEnd="opacity-0 translate-y-4"
|
|
||||||
>
|
|
||||||
<div ref={modalContent} className="bg-white rounded shadow-lg overflow-auto max-w-lg w-full max-h-full">
|
|
||||||
<div className="p-6">
|
|
||||||
<div className="relative">
|
|
||||||
{/* Close button */}
|
|
||||||
<button className="absolute top-0 right-0 text-slate-400 hover:text-slate-500" onClick={(e) => { e.stopPropagation(); setModalOpen(false); }}>
|
|
||||||
<div className="sr-only">Close</div>
|
|
||||||
<svg className="w-4 h-4 fill-current">
|
|
||||||
<path d="M7.95 6.536l4.242-4.243a1 1 0 111.415 1.414L9.364 7.95l4.243 4.242a1 1 0 11-1.415 1.415L7.95 9.364l-4.243 4.243a1 1 0 01-1.414-1.415L6.536 7.95 2.293 3.707a1 1 0 011.414-1.414L7.95 6.536z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Transition>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ModalAction;
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
import React, { useRef, useEffect } from 'react';
|
|
||||||
import Transition from '../utils/Transition';
|
|
||||||
|
|
||||||
function ModalBasic({
|
|
||||||
children,
|
|
||||||
id,
|
|
||||||
title,
|
|
||||||
modalOpen,
|
|
||||||
setModalOpen
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const modalContent = useRef(null);
|
|
||||||
|
|
||||||
// close on click outside
|
|
||||||
useEffect(() => {
|
|
||||||
const clickHandler = ({ target }) => {
|
|
||||||
if (!modalOpen || modalContent.current.contains(target)) return
|
|
||||||
setModalOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('click', clickHandler);
|
|
||||||
return () => document.removeEventListener('click', clickHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
// close if the esc key is pressed
|
|
||||||
useEffect(() => {
|
|
||||||
const keyHandler = ({ keyCode }) => {
|
|
||||||
if (!modalOpen || keyCode !== 27) return;
|
|
||||||
setModalOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('keydown', keyHandler);
|
|
||||||
return () => document.removeEventListener('keydown', keyHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{/* Modal backdrop */}
|
|
||||||
<Transition
|
|
||||||
className="fixed inset-0 bg-slate-900 bg-opacity-30 z-50 transition-opacity"
|
|
||||||
show={modalOpen}
|
|
||||||
enter="transition ease-out duration-200"
|
|
||||||
enterStart="opacity-0"
|
|
||||||
enterEnd="opacity-100"
|
|
||||||
leave="transition ease-out duration-100"
|
|
||||||
leaveStart="opacity-100"
|
|
||||||
leaveEnd="opacity-0"
|
|
||||||
aria-hidden="true"
|
|
||||||
/>
|
|
||||||
{/* Modal dialog */}
|
|
||||||
<Transition
|
|
||||||
id={id}
|
|
||||||
className="fixed inset-0 z-50 overflow-hidden flex items-center my-4 justify-center transform px-4 sm:px-6"
|
|
||||||
role="dialog"
|
|
||||||
aria-modal="true"
|
|
||||||
show={modalOpen}
|
|
||||||
enter="transition ease-in-out duration-200"
|
|
||||||
enterStart="opacity-0 translate-y-4"
|
|
||||||
enterEnd="opacity-100 translate-y-0"
|
|
||||||
leave="transition ease-in-out duration-200"
|
|
||||||
leaveStart="opacity-100 translate-y-0"
|
|
||||||
leaveEnd="opacity-0 translate-y-4"
|
|
||||||
>
|
|
||||||
<div ref={modalContent} className="bg-white rounded shadow-lg overflow-auto max-w-lg w-full max-h-full">
|
|
||||||
{/* Modal header */}
|
|
||||||
<div className="px-5 py-3 border-b border-slate-200">
|
|
||||||
<div className="flex justify-between items-center">
|
|
||||||
<div className="font-semibold text-slate-800">{title}</div>
|
|
||||||
<button className="text-slate-400 hover:text-slate-500" onClick={(e) => { e.stopPropagation(); setModalOpen(false); }}>
|
|
||||||
<div className="sr-only">Close</div>
|
|
||||||
<svg className="w-4 h-4 fill-current">
|
|
||||||
<path d="M7.95 6.536l4.242-4.243a1 1 0 111.415 1.414L9.364 7.95l4.243 4.242a1 1 0 11-1.415 1.415L7.95 9.364l-4.243 4.243a1 1 0 01-1.414-1.415L6.536 7.95 2.293 3.707a1 1 0 011.414-1.414L7.95 6.536z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</Transition>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ModalBasic;
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
import React, { useRef, useEffect } from 'react';
|
|
||||||
import Transition from '../utils/Transition';
|
|
||||||
|
|
||||||
function ModalBlank({
|
|
||||||
children,
|
|
||||||
id,
|
|
||||||
modalOpen,
|
|
||||||
setModalOpen
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const modalContent = useRef(null);
|
|
||||||
|
|
||||||
// close on click outside
|
|
||||||
useEffect(() => {
|
|
||||||
const clickHandler = ({ target }) => {
|
|
||||||
if (!modalOpen || modalContent.current.contains(target)) return
|
|
||||||
setModalOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('click', clickHandler);
|
|
||||||
return () => document.removeEventListener('click', clickHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
// close if the esc key is pressed
|
|
||||||
useEffect(() => {
|
|
||||||
const keyHandler = ({ keyCode }) => {
|
|
||||||
if (!modalOpen || keyCode !== 27) return;
|
|
||||||
setModalOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('keydown', keyHandler);
|
|
||||||
return () => document.removeEventListener('keydown', keyHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{/* Modal backdrop */}
|
|
||||||
<Transition
|
|
||||||
className="fixed inset-0 bg-slate-900 bg-opacity-30 z-50 transition-opacity"
|
|
||||||
show={modalOpen}
|
|
||||||
enter="transition ease-out duration-200"
|
|
||||||
enterStart="opacity-0"
|
|
||||||
enterEnd="opacity-100"
|
|
||||||
leave="transition ease-out duration-100"
|
|
||||||
leaveStart="opacity-100"
|
|
||||||
leaveEnd="opacity-0"
|
|
||||||
aria-hidden="true"
|
|
||||||
/>
|
|
||||||
{/* Modal dialog */}
|
|
||||||
<Transition
|
|
||||||
id={id}
|
|
||||||
className="fixed inset-0 z-50 overflow-hidden flex items-center my-4 justify-center transform px-4 sm:px-6"
|
|
||||||
role="dialog"
|
|
||||||
aria-modal="true"
|
|
||||||
show={modalOpen}
|
|
||||||
enter="transition ease-in-out duration-200"
|
|
||||||
enterStart="opacity-0 translate-y-4"
|
|
||||||
enterEnd="opacity-100 translate-y-0"
|
|
||||||
leave="transition ease-in-out duration-200"
|
|
||||||
leaveStart="opacity-100 translate-y-0"
|
|
||||||
leaveEnd="opacity-0 translate-y-4"
|
|
||||||
>
|
|
||||||
<div ref={modalContent} className="bg-white rounded shadow-lg overflow-auto max-w-lg w-full max-h-full">
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</Transition>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ModalBlank;
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
import React, { useRef, useEffect } from 'react';
|
|
||||||
import Transition from '../utils/Transition';
|
|
||||||
|
|
||||||
function ModalCookies({
|
|
||||||
children,
|
|
||||||
id,
|
|
||||||
title,
|
|
||||||
modalOpen,
|
|
||||||
setModalOpen
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const modalContent = useRef(null);
|
|
||||||
|
|
||||||
// close on click outside
|
|
||||||
useEffect(() => {
|
|
||||||
const clickHandler = ({ target }) => {
|
|
||||||
if (!modalOpen || modalContent.current.contains(target)) return
|
|
||||||
setModalOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('click', clickHandler);
|
|
||||||
return () => document.removeEventListener('click', clickHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
// close if the esc key is pressed
|
|
||||||
useEffect(() => {
|
|
||||||
const keyHandler = ({ keyCode }) => {
|
|
||||||
if (!modalOpen || keyCode !== 27) return;
|
|
||||||
setModalOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('keydown', keyHandler);
|
|
||||||
return () => document.removeEventListener('keydown', keyHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{/* Modal backdrop */}
|
|
||||||
<Transition
|
|
||||||
className="fixed inset-0 bg-slate-900 bg-opacity-30 z-50 transition-opacity"
|
|
||||||
show={modalOpen}
|
|
||||||
enter="transition ease-out duration-200"
|
|
||||||
enterStart="opacity-0"
|
|
||||||
enterEnd="opacity-100"
|
|
||||||
leave="transition ease-out duration-100"
|
|
||||||
leaveStart="opacity-100"
|
|
||||||
leaveEnd="opacity-0"
|
|
||||||
aria-hidden="true"
|
|
||||||
/>
|
|
||||||
{/* Modal dialog */}
|
|
||||||
<Transition
|
|
||||||
id={id}
|
|
||||||
className="fixed inset-0 z-50 overflow-hidden flex items-center my-4 justify-center transform px-4 sm:px-6"
|
|
||||||
role="dialog"
|
|
||||||
aria-modal="true"
|
|
||||||
show={modalOpen}
|
|
||||||
enter="transition ease-in-out duration-200"
|
|
||||||
enterStart="opacity-0 translate-y-4"
|
|
||||||
enterEnd="opacity-100 translate-y-0"
|
|
||||||
leave="transition ease-in-out duration-200"
|
|
||||||
leaveStart="opacity-100 translate-y-0"
|
|
||||||
leaveEnd="opacity-0 translate-y-4"
|
|
||||||
>
|
|
||||||
<div ref={modalContent} className="bg-white rounded shadow-lg overflow-auto max-w-lg w-full max-h-full">
|
|
||||||
<div className="p-5">
|
|
||||||
{/* Modal header */}
|
|
||||||
<div className="mb-2">
|
|
||||||
<div className="flex justify-between items-center">
|
|
||||||
<div className="text-lg font-semibold text-slate-800">{title}</div>
|
|
||||||
<button className="text-slate-400 hover:text-slate-500" onClick={(e) => { e.stopPropagation(); setModalOpen(false); }}>
|
|
||||||
<div className="sr-only">Close</div>
|
|
||||||
<svg className="w-4 h-4 fill-current">
|
|
||||||
<path d="M7.95 6.536l4.242-4.243a1 1 0 111.415 1.414L9.364 7.95l4.243 4.242a1 1 0 11-1.415 1.415L7.95 9.364l-4.243 4.243a1 1 0 01-1.414-1.415L6.536 7.95 2.293 3.707a1 1 0 011.414-1.414L7.95 6.536z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Transition>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ModalCookies;
|
|
||||||
@@ -1,197 +0,0 @@
|
|||||||
import React, { useRef, useEffect } from 'react';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import Transition from '../utils/Transition';
|
|
||||||
|
|
||||||
function ModalSearch({
|
|
||||||
id,
|
|
||||||
searchId,
|
|
||||||
modalOpen,
|
|
||||||
setModalOpen
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const modalContent = useRef(null);
|
|
||||||
const searchInput = useRef(null);
|
|
||||||
|
|
||||||
// close on click outside
|
|
||||||
useEffect(() => {
|
|
||||||
const clickHandler = ({ target }) => {
|
|
||||||
if (!modalOpen || modalContent.current.contains(target)) return
|
|
||||||
setModalOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('click', clickHandler);
|
|
||||||
return () => document.removeEventListener('click', clickHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
// close if the esc key is pressed
|
|
||||||
useEffect(() => {
|
|
||||||
const keyHandler = ({ keyCode }) => {
|
|
||||||
if (!modalOpen || keyCode !== 27) return;
|
|
||||||
setModalOpen(false);
|
|
||||||
};
|
|
||||||
document.addEventListener('keydown', keyHandler);
|
|
||||||
return () => document.removeEventListener('keydown', keyHandler);
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
modalOpen && searchInput.current.focus();
|
|
||||||
}, [modalOpen]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{/* Modal backdrop */}
|
|
||||||
<Transition
|
|
||||||
className="fixed inset-0 bg-slate-900 bg-opacity-30 z-50 transition-opacity"
|
|
||||||
show={modalOpen}
|
|
||||||
enter="transition ease-out duration-200"
|
|
||||||
enterStart="opacity-0"
|
|
||||||
enterEnd="opacity-100"
|
|
||||||
leave="transition ease-out duration-100"
|
|
||||||
leaveStart="opacity-100"
|
|
||||||
leaveEnd="opacity-0"
|
|
||||||
aria-hidden="true"
|
|
||||||
/>
|
|
||||||
{/* Modal dialog */}
|
|
||||||
<Transition
|
|
||||||
id={id}
|
|
||||||
className="fixed inset-0 z-50 overflow-hidden flex items-start top-20 mb-4 justify-center transform px-4 sm:px-6"
|
|
||||||
role="dialog"
|
|
||||||
aria-modal="true"
|
|
||||||
show={modalOpen}
|
|
||||||
enter="transition ease-in-out duration-200"
|
|
||||||
enterStart="opacity-0 translate-y-4"
|
|
||||||
enterEnd="opacity-100 translate-y-0"
|
|
||||||
leave="transition ease-in-out duration-200"
|
|
||||||
leaveStart="opacity-100 translate-y-0"
|
|
||||||
leaveEnd="opacity-0 translate-y-4"
|
|
||||||
>
|
|
||||||
<div ref={modalContent} className="bg-white overflow-auto max-w-2xl w-full max-h-full rounded shadow-lg">
|
|
||||||
{/* Search form */}
|
|
||||||
<form className="border-b border-slate-200">
|
|
||||||
<div className="relative">
|
|
||||||
<label htmlFor={searchId} className="sr-only">Search</label>
|
|
||||||
<input id={searchId} className="w-full border-0 focus:ring-transparent placeholder-slate-400 appearance-none py-3 pl-10 pr-4" type="search" placeholder="Search Anything…" ref={searchInput} />
|
|
||||||
<button className="absolute inset-0 right-auto group" type="submit" aria-label="Search">
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current text-slate-400 group-hover:text-slate-500 ml-4 mr-2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M7 14c-3.86 0-7-3.14-7-7s3.14-7 7-7 7 3.14 7 7-3.14 7-7 7zM7 2C4.243 2 2 4.243 2 7s2.243 5 5 5 5-2.243 5-5-2.243-5-5-5z" />
|
|
||||||
<path d="M15.707 14.293L13.314 11.9a8.019 8.019 0 01-1.414 1.414l2.393 2.393a.997.997 0 001.414 0 .999.999 0 000-1.414z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<div className="py-4 px-2">
|
|
||||||
{/* Recent searches */}
|
|
||||||
<div className="mb-3 last:mb-0">
|
|
||||||
<div className="text-xs font-semibold text-slate-400 uppercase px-2 mb-2">Recent searches</div>
|
|
||||||
<ul className="text-sm">
|
|
||||||
<li>
|
|
||||||
<Link
|
|
||||||
className="flex items-center p-2 text-slate-800 hover:text-white hover:bg-indigo-500 rounded group"
|
|
||||||
to="#0"
|
|
||||||
onClick={() => setModalOpen(!modalOpen)}
|
|
||||||
>
|
|
||||||
<svg className="w-4 h-4 fill-current text-slate-400 group-hover:text-white group-hover:text-opacity-50 shrink-0 mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M15.707 14.293v.001a1 1 0 01-1.414 1.414L11.185 12.6A6.935 6.935 0 017 14a7.016 7.016 0 01-5.173-2.308l-1.537 1.3L0 8l4.873 1.12-1.521 1.285a4.971 4.971 0 008.59-2.835l1.979.454a6.971 6.971 0 01-1.321 3.157l3.107 3.112zM14 6L9.127 4.88l1.521-1.28a4.971 4.971 0 00-8.59 2.83L.084 5.976a6.977 6.977 0 0112.089-3.668l1.537-1.3L14 6z" />
|
|
||||||
</svg>
|
|
||||||
<span>Form Builder - 23 hours on-demand video</span>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Link
|
|
||||||
className="flex items-center p-2 text-slate-800 hover:text-white hover:bg-indigo-500 rounded group"
|
|
||||||
to="#0"
|
|
||||||
onClick={() => setModalOpen(!modalOpen)}
|
|
||||||
>
|
|
||||||
<svg className="w-4 h-4 fill-current text-slate-400 group-hover:text-white group-hover:text-opacity-50 shrink-0 mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M15.707 14.293v.001a1 1 0 01-1.414 1.414L11.185 12.6A6.935 6.935 0 017 14a7.016 7.016 0 01-5.173-2.308l-1.537 1.3L0 8l4.873 1.12-1.521 1.285a4.971 4.971 0 008.59-2.835l1.979.454a6.971 6.971 0 01-1.321 3.157l3.107 3.112zM14 6L9.127 4.88l1.521-1.28a4.971 4.971 0 00-8.59 2.83L.084 5.976a6.977 6.977 0 0112.089-3.668l1.537-1.3L14 6z" />
|
|
||||||
</svg>
|
|
||||||
<span>Access Mosaic on mobile and TV</span>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Link
|
|
||||||
className="flex items-center p-2 text-slate-800 hover:text-white hover:bg-indigo-500 rounded group"
|
|
||||||
to="#0"
|
|
||||||
onClick={() => setModalOpen(!modalOpen)}
|
|
||||||
>
|
|
||||||
<svg className="w-4 h-4 fill-current text-slate-400 group-hover:text-white group-hover:text-opacity-50 shrink-0 mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M15.707 14.293v.001a1 1 0 01-1.414 1.414L11.185 12.6A6.935 6.935 0 017 14a7.016 7.016 0 01-5.173-2.308l-1.537 1.3L0 8l4.873 1.12-1.521 1.285a4.971 4.971 0 008.59-2.835l1.979.454a6.971 6.971 0 01-1.321 3.157l3.107 3.112zM14 6L9.127 4.88l1.521-1.28a4.971 4.971 0 00-8.59 2.83L.084 5.976a6.977 6.977 0 0112.089-3.668l1.537-1.3L14 6z" />
|
|
||||||
</svg>
|
|
||||||
<span>Product Update - Q4 2021</span>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Link
|
|
||||||
className="flex items-center p-2 text-slate-800 hover:text-white hover:bg-indigo-500 rounded group"
|
|
||||||
to="#0"
|
|
||||||
onClick={() => setModalOpen(!modalOpen)}
|
|
||||||
>
|
|
||||||
<svg className="w-4 h-4 fill-current text-slate-400 group-hover:text-white group-hover:text-opacity-50 shrink-0 mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M15.707 14.293v.001a1 1 0 01-1.414 1.414L11.185 12.6A6.935 6.935 0 017 14a7.016 7.016 0 01-5.173-2.308l-1.537 1.3L0 8l4.873 1.12-1.521 1.285a4.971 4.971 0 008.59-2.835l1.979.454a6.971 6.971 0 01-1.321 3.157l3.107 3.112zM14 6L9.127 4.88l1.521-1.28a4.971 4.971 0 00-8.59 2.83L.084 5.976a6.977 6.977 0 0112.089-3.668l1.537-1.3L14 6z" />
|
|
||||||
</svg>
|
|
||||||
<span>Master Digital Marketing Strategy course</span>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Link
|
|
||||||
className="flex items-center p-2 text-slate-800 hover:text-white hover:bg-indigo-500 rounded group"
|
|
||||||
to="#0"
|
|
||||||
onClick={() => setModalOpen(!modalOpen)}
|
|
||||||
>
|
|
||||||
<svg className="w-4 h-4 fill-current text-slate-400 group-hover:text-white group-hover:text-opacity-50 shrink-0 mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M15.707 14.293v.001a1 1 0 01-1.414 1.414L11.185 12.6A6.935 6.935 0 017 14a7.016 7.016 0 01-5.173-2.308l-1.537 1.3L0 8l4.873 1.12-1.521 1.285a4.971 4.971 0 008.59-2.835l1.979.454a6.971 6.971 0 01-1.321 3.157l3.107 3.112zM14 6L9.127 4.88l1.521-1.28a4.971 4.971 0 00-8.59 2.83L.084 5.976a6.977 6.977 0 0112.089-3.668l1.537-1.3L14 6z" />
|
|
||||||
</svg>
|
|
||||||
<span>Dedicated forms for products</span>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Link
|
|
||||||
className="flex items-center p-2 text-slate-800 hover:text-white hover:bg-indigo-500 rounded group"
|
|
||||||
to="#0"
|
|
||||||
onClick={() => setModalOpen(!modalOpen)}
|
|
||||||
>
|
|
||||||
<svg className="w-4 h-4 fill-current text-slate-400 group-hover:text-white group-hover:text-opacity-50 shrink-0 mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M15.707 14.293v.001a1 1 0 01-1.414 1.414L11.185 12.6A6.935 6.935 0 017 14a7.016 7.016 0 01-5.173-2.308l-1.537 1.3L0 8l4.873 1.12-1.521 1.285a4.971 4.971 0 008.59-2.835l1.979.454a6.971 6.971 0 01-1.321 3.157l3.107 3.112zM14 6L9.127 4.88l1.521-1.28a4.971 4.971 0 00-8.59 2.83L.084 5.976a6.977 6.977 0 0112.089-3.668l1.537-1.3L14 6z" />
|
|
||||||
</svg>
|
|
||||||
<span>Product Update - Q4 2021</span>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{/* Recent pages */}
|
|
||||||
<div className="mb-3 last:mb-0">
|
|
||||||
<div className="text-xs font-semibold text-slate-400 uppercase px-2 mb-2">Recent pages</div>
|
|
||||||
<ul className="text-sm">
|
|
||||||
<li>
|
|
||||||
<Link
|
|
||||||
className="flex items-center p-2 text-slate-800 hover:text-white hover:bg-indigo-500 rounded group"
|
|
||||||
to="#0"
|
|
||||||
onClick={() => setModalOpen(!modalOpen)}
|
|
||||||
>
|
|
||||||
<svg className="w-4 h-4 fill-current text-slate-400 group-hover:text-white group-hover:text-opacity-50 shrink-0 mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M14 0H2c-.6 0-1 .4-1 1v14c0 .6.4 1 1 1h8l5-5V1c0-.6-.4-1-1-1zM3 2h10v8H9v4H3V2z" />
|
|
||||||
</svg>
|
|
||||||
<span><span className="font-medium text-slate-800 group-hover:text-white">Messages</span> - Conversation / … / Mike Mills</span>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Link
|
|
||||||
className="flex items-center p-2 text-slate-800 hover:text-white hover:bg-indigo-500 rounded group"
|
|
||||||
to="#0"
|
|
||||||
onClick={() => setModalOpen(!modalOpen)}
|
|
||||||
>
|
|
||||||
<svg className="w-4 h-4 fill-current text-slate-400 group-hover:text-white group-hover:text-opacity-50 shrink-0 mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M14 0H2c-.6 0-1 .4-1 1v14c0 .6.4 1 1 1h8l5-5V1c0-.6-.4-1-1-1zM3 2h10v8H9v4H3V2z" />
|
|
||||||
</svg>
|
|
||||||
<span><span className="font-medium text-slate-800 group-hover:text-white">Messages</span> - Conversation / … / Eva Patrick</span>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Transition>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ModalSearch;
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
function Notification({
|
|
||||||
children,
|
|
||||||
className,
|
|
||||||
type,
|
|
||||||
open,
|
|
||||||
setOpen
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const typeIcon = (type) => {
|
|
||||||
switch (type) {
|
|
||||||
case 'warning':
|
|
||||||
return (
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current text-amber-500 mt-[3px] mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm0 12c-.6 0-1-.4-1-1s.4-1 1-1 1 .4 1 1-.4 1-1 1zm1-3H7V4h2v5z" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
case 'error':
|
|
||||||
return (
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current text-rose-500 mt-[3px] mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm3.5 10.1l-1.4 1.4L8 9.4l-2.1 2.1-1.4-1.4L6.6 8 4.5 5.9l1.4-1.4L8 6.6l2.1-2.1 1.4 1.4L9.4 8l2.1 2.1z" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
case 'success':
|
|
||||||
return (
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current text-emerald-500 mt-[3px] mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zM7 11.4L3.6 8 5 6.6l2 2 4-4L12.4 6 7 11.4z" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
return (
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current text-indigo-500 mt-[3px] mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm1 12H7V7h2v5zM8 6c-.6 0-1-.4-1-1s.4-1 1-1 1 .4 1 1-.4 1-1 1z" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{open &&
|
|
||||||
<div className={className}>
|
|
||||||
<div className="inline-flex flex-col max-w-lg px-4 py-2 rounded-sm text-sm bg-white shadow-lg border border-slate-200 text-slate-600">
|
|
||||||
<div className="flex w-full justify-between items-start">
|
|
||||||
<div className="flex">
|
|
||||||
{typeIcon(type)}
|
|
||||||
<div>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button className="opacity-70 hover:opacity-80 ml-3 mt-[3px]" onClick={() => setOpen(false)}>
|
|
||||||
<div className="sr-only">Close</div>
|
|
||||||
<svg className="w-4 h-4 fill-current">
|
|
||||||
<path d="M7.95 6.536l4.242-4.243a1 1 0 111.415 1.414L9.364 7.95l4.243 4.242a1 1 0 11-1.415 1.415L7.95 9.364l-4.243 4.243a1 1 0 01-1.414-1.415L6.536 7.95 2.293 3.707a1 1 0 011.414-1.414L7.95 6.536z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div className="text-right mt-1">
|
|
||||||
<a className="font-medium text-indigo-500 hover:text-indigo-600" href="#0">Action -></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Notification;
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
function PaginationClassic() {
|
|
||||||
return (
|
|
||||||
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between">
|
|
||||||
<nav className="mb-4 sm:mb-0 sm:order-1" role="navigation" aria-label="Navigation">
|
|
||||||
<ul className="flex justify-center">
|
|
||||||
<li className="ml-3 first:ml-0">
|
|
||||||
<a className="btn bg-white border-slate-200 text-slate-300 cursor-not-allowed" href="#0" disabled><- Previous</a>
|
|
||||||
</li>
|
|
||||||
<li className="ml-3 first:ml-0">
|
|
||||||
<a className="btn bg-white border-slate-200 hover:border-slate-300 text-indigo-500" href="#0">Next -></a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
<div className="text-sm text-slate-500 text-center sm:text-left">
|
|
||||||
Showing <span className="font-medium text-slate-600">1</span> to <span className="font-medium text-slate-600">10</span> of <span className="font-medium text-slate-600">467</span> results
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default PaginationClassic;
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
function PaginationNumeric() {
|
|
||||||
return (
|
|
||||||
<div className="flex justify-center">
|
|
||||||
<nav className="flex" role="navigation" aria-label="Navigation">
|
|
||||||
<div className="mr-2">
|
|
||||||
<span className="inline-flex items-center justify-center rounded leading-5 px-2.5 py-2 bg-white border border-slate-200 text-slate-300">
|
|
||||||
<span className="sr-only">Previous</span><wbr />
|
|
||||||
<svg className="h-4 w-4 fill-current" viewBox="0 0 16 16">
|
|
||||||
<path d="M9.4 13.4l1.4-1.4-4-4 4-4-1.4-1.4L4 8z" />
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<ul className="inline-flex text-sm font-medium -space-x-px shadow-sm">
|
|
||||||
<li>
|
|
||||||
<span className="inline-flex items-center justify-center rounded-l leading-5 px-3.5 py-2 bg-white border border-slate-200 text-indigo-500">1</span>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a className="inline-flex items-center justify-center leading-5 px-3.5 py-2 bg-white hover:bg-indigo-500 border border-slate-200 text-slate-600 hover:text-white" href="#0">2</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a className="inline-flex items-center justify-center leading-5 px-3.5 py-2 bg-white hover:bg-indigo-500 border border-slate-200 text-slate-600 hover:text-white" href="#0">3</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<span className="inline-flex items-center justify-center leading-5 px-3.5 py-2 bg-white border border-slate-200 text-slate-400">…</span>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a className="inline-flex items-center justify-center rounded-r leading-5 px-3.5 py-2 bg-white hover:bg-indigo-500 border border-slate-200 text-slate-600 hover:text-white" href="#0">9</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<div className="ml-2">
|
|
||||||
<a href="#0" className="inline-flex items-center justify-center rounded leading-5 px-2.5 py-2 bg-white hover:bg-indigo-500 border border-slate-200 text-slate-600 hover:text-white shadow-sm">
|
|
||||||
<span className="sr-only">Next</span><wbr />
|
|
||||||
<svg className="h-4 w-4 fill-current" viewBox="0 0 16 16">
|
|
||||||
<path d="M6.6 13.4L5.2 12l4-4-4-4 1.4-1.4L12 8z" />
|
|
||||||
</svg>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default PaginationNumeric;
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
function PaginationNumeric2() {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<nav className="flex justify-between" role="navigation" aria-label="Navigation">
|
|
||||||
<div className="flex-1 mr-2">
|
|
||||||
<a className="btn bg-white border-slate-200 text-slate-300 cursor-not-allowed" href="#0" disabled><-<span className="hidden sm:inline"> Previous</span></a>
|
|
||||||
</div>
|
|
||||||
<div className="grow text-center">
|
|
||||||
<ul className="inline-flex text-sm font-medium -space-x-px">
|
|
||||||
<li>
|
|
||||||
<span className="inline-flex items-center justify-center rounded-full leading-5 px-2 py-2 bg-white border border-slate-200 text-indigo-500 shadow-sm"><span className="w-5">1</span></span>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a className="inline-flex items-center justify-center leading-5 px-2 py-2 text-slate-600 hover:text-indigo-500 border border-transparent" href="#0"><span className="w-5">2</span></a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a className="inline-flex items-center justify-center leading-5 px-2 py-2 text-slate-600 hover:text-indigo-500 border border-transparent" href="#0"><span className="w-5">3</span></a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<span className="inline-flex items-center justify-center leading-5 px-2 py-2 text-slate-400">…</span>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a className="inline-flex items-center justify-center rounded-r leading-5 px-2 py-2 text-slate-600 hover:text-indigo-500 border border-transparent" href="#0"><span className="w-5">9</span></a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div className="flex-1 text-right ml-2">
|
|
||||||
<a className="btn bg-white border-slate-200 hover:border-slate-300 text-indigo-500" href="#0"><span className="hidden sm:inline">Next </span>-></a>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default PaginationNumeric2;
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
function Toast({
|
|
||||||
children,
|
|
||||||
className,
|
|
||||||
type,
|
|
||||||
open,
|
|
||||||
setOpen
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const typeIcon = (type) => {
|
|
||||||
switch (type) {
|
|
||||||
case 'warning':
|
|
||||||
return (
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current opacity-80 mt-[3px] mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm0 12c-.6 0-1-.4-1-1s.4-1 1-1 1 .4 1 1-.4 1-1 1zm1-3H7V4h2v5z" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
case 'error':
|
|
||||||
return (
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current opacity-80 mt-[3px] mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm3.5 10.1l-1.4 1.4L8 9.4l-2.1 2.1-1.4-1.4L6.6 8 4.5 5.9l1.4-1.4L8 6.6l2.1-2.1 1.4 1.4L9.4 8l2.1 2.1z" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
case 'success':
|
|
||||||
return (
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current opacity-80 mt-[3px] mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zM7 11.4L3.6 8 5 6.6l2 2 4-4L12.4 6 7 11.4z" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
return (
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current opacity-80 mt-[3px] mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm1 12H7V7h2v5zM8 6c-.6 0-1-.4-1-1s.4-1 1-1 1 .4 1 1-.4 1-1 1z" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const typeColor = (type) => {
|
|
||||||
switch (type) {
|
|
||||||
case 'warning':
|
|
||||||
return 'bg-amber-500';
|
|
||||||
case 'error':
|
|
||||||
return 'bg-rose-500';
|
|
||||||
case 'success':
|
|
||||||
return 'bg-emerald-500';
|
|
||||||
default:
|
|
||||||
return 'bg-indigo-500';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{open &&
|
|
||||||
<div className={className}>
|
|
||||||
<div className={`inline-flex min-w-80 px-4 py-2 rounded-sm text-sm text-white ${typeColor(type)}`}>
|
|
||||||
<div className="flex w-full justify-between items-start">
|
|
||||||
<div className="flex">
|
|
||||||
{typeIcon(type)}
|
|
||||||
<div className="font-medium">
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button className="opacity-70 hover:opacity-80 ml-3 mt-[3px]" onClick={() => setOpen(false)}>
|
|
||||||
<div className="sr-only">Close</div>
|
|
||||||
<svg className="w-4 h-4 fill-current">
|
|
||||||
<path d="M7.95 6.536l4.242-4.243a1 1 0 111.415 1.414L9.364 7.95l4.243 4.242a1 1 0 11-1.415 1.415L7.95 9.364l-4.243 4.243a1 1 0 01-1.414-1.415L6.536 7.95 2.293 3.707a1 1 0 011.414-1.414L7.95 6.536z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Toast;
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
function Toast2({
|
|
||||||
children,
|
|
||||||
className,
|
|
||||||
type,
|
|
||||||
open,
|
|
||||||
setOpen
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const typeIcon = (type) => {
|
|
||||||
switch (type) {
|
|
||||||
case 'warning':
|
|
||||||
return (
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current opacity-80 mt-[3px] mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm0 12c-.6 0-1-.4-1-1s.4-1 1-1 1 .4 1 1-.4 1-1 1zm1-3H7V4h2v5z" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
case 'error':
|
|
||||||
return (
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current opacity-80 mt-[3px] mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm3.5 10.1l-1.4 1.4L8 9.4l-2.1 2.1-1.4-1.4L6.6 8 4.5 5.9l1.4-1.4L8 6.6l2.1-2.1 1.4 1.4L9.4 8l2.1 2.1z" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
case 'success':
|
|
||||||
return (
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current opacity-80 mt-[3px] mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zM7 11.4L3.6 8 5 6.6l2 2 4-4L12.4 6 7 11.4z" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
return (
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current opacity-80 mt-[3px] mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm1 12H7V7h2v5zM8 6c-.6 0-1-.4-1-1s.4-1 1-1 1 .4 1 1-.4 1-1 1z" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const typeColor = (type) => {
|
|
||||||
switch (type) {
|
|
||||||
case 'warning':
|
|
||||||
return 'bg-amber-100 border-amber-200 text-amber-600';
|
|
||||||
case 'error':
|
|
||||||
return 'bg-rose-100 border-rose-200 text-rose-600';
|
|
||||||
case 'success':
|
|
||||||
return 'bg-emerald-100 border-emerald-200 text-emerald-600';
|
|
||||||
default:
|
|
||||||
return 'bg-indigo-100 border-indigo-200 text-indigo-500';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{open &&
|
|
||||||
<div className={className}>
|
|
||||||
<div className={`inline-flex min-w-80 px-4 py-2 rounded-sm text-sm border ${typeColor(type)}`}>
|
|
||||||
<div className="flex w-full justify-between items-start">
|
|
||||||
<div className="flex">
|
|
||||||
{typeIcon(type)}
|
|
||||||
<div>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button className="opacity-70 hover:opacity-80 ml-3 mt-[3px]" onClick={() => setOpen(false)}>
|
|
||||||
<div className="sr-only">Close</div>
|
|
||||||
<svg className="w-4 h-4 fill-current">
|
|
||||||
<path d="M7.95 6.536l4.242-4.243a1 1 0 111.415 1.414L9.364 7.95l4.243 4.242a1 1 0 11-1.415 1.415L7.95 9.364l-4.243 4.243a1 1 0 01-1.414-1.415L6.536 7.95 2.293 3.707a1 1 0 011.414-1.414L7.95 6.536z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Toast2;
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
function Toast3({
|
|
||||||
children,
|
|
||||||
className,
|
|
||||||
type,
|
|
||||||
open,
|
|
||||||
setOpen
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const typeIcon = (type) => {
|
|
||||||
switch (type) {
|
|
||||||
case 'warning':
|
|
||||||
return (
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current text-amber-500 mt-[3px] mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm0 12c-.6 0-1-.4-1-1s.4-1 1-1 1 .4 1 1-.4 1-1 1zm1-3H7V4h2v5z" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
case 'error':
|
|
||||||
return (
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current text-rose-500 mt-[3px] mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm3.5 10.1l-1.4 1.4L8 9.4l-2.1 2.1-1.4-1.4L6.6 8 4.5 5.9l1.4-1.4L8 6.6l2.1-2.1 1.4 1.4L9.4 8l2.1 2.1z" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
case 'success':
|
|
||||||
return (
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current text-emerald-500 mt-[3px] mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zM7 11.4L3.6 8 5 6.6l2 2 4-4L12.4 6 7 11.4z" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
return (
|
|
||||||
<svg className="w-4 h-4 shrink-0 fill-current text-indigo-500 mt-[3px] mr-3" viewBox="0 0 16 16">
|
|
||||||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm1 12H7V7h2v5zM8 6c-.6 0-1-.4-1-1s.4-1 1-1 1 .4 1 1-.4 1-1 1z" />
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{open &&
|
|
||||||
<div className={className}>
|
|
||||||
<div className="inline-flex min-w-80 px-4 py-2 rounded-sm text-sm bg-white shadow-lg border border-slate-200 text-slate-600">
|
|
||||||
<div className="flex w-full justify-between items-start">
|
|
||||||
<div className="flex">
|
|
||||||
{typeIcon(type)}
|
|
||||||
<div>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button className="opacity-70 hover:opacity-80 ml-3 mt-[3px]" onClick={() => setOpen(false)}>
|
|
||||||
<div className="sr-only">Close</div>
|
|
||||||
<svg className="w-4 h-4 fill-current">
|
|
||||||
<path d="M7.95 6.536l4.242-4.243a1 1 0 111.415 1.414L9.364 7.95l4.243 4.242a1 1 0 11-1.415 1.415L7.95 9.364l-4.243 4.243a1 1 0 01-1.414-1.415L6.536 7.95 2.293 3.707a1 1 0 011.414-1.414L7.95 6.536z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Toast3;
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
import Transition from '../utils/Transition';
|
|
||||||
|
|
||||||
function Tooltip({
|
|
||||||
children,
|
|
||||||
className,
|
|
||||||
bg,
|
|
||||||
size,
|
|
||||||
position,
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const [tooltipOpen, setTooltipOpen] = useState(false);
|
|
||||||
|
|
||||||
const positionOuterClasses = (position) => {
|
|
||||||
switch (position) {
|
|
||||||
case 'right':
|
|
||||||
return 'left-full top-1/2 transform -translate-y-1/2';
|
|
||||||
case 'left':
|
|
||||||
return 'right-full top-1/2 transform -translate-y-1/2';
|
|
||||||
case 'bottom':
|
|
||||||
return 'top-full left-1/2 transform -translate-x-1/2';
|
|
||||||
default:
|
|
||||||
return 'bottom-full left-1/2 transform -translate-x-1/2';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const sizeClasses = (size) => {
|
|
||||||
switch (size) {
|
|
||||||
case 'lg':
|
|
||||||
return 'min-w-72 p-3';
|
|
||||||
case 'md':
|
|
||||||
return 'min-w-56 p-3';
|
|
||||||
case 'sm':
|
|
||||||
return 'min-w-44 p-2';
|
|
||||||
default:
|
|
||||||
return 'p-2';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const positionInnerClasses = (position) => {
|
|
||||||
switch (position) {
|
|
||||||
case 'right':
|
|
||||||
return 'ml-2';
|
|
||||||
case 'left':
|
|
||||||
return 'mr-2';
|
|
||||||
case 'bottom':
|
|
||||||
return 'mt-2';
|
|
||||||
default:
|
|
||||||
return 'mb-2';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={`relative ${className}`}
|
|
||||||
onMouseEnter={() => setTooltipOpen(true)}
|
|
||||||
onMouseLeave={() => setTooltipOpen(false)}
|
|
||||||
onFocus={() => setTooltipOpen(true)}
|
|
||||||
onBlur={() => setTooltipOpen(false)}
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
className="block"
|
|
||||||
aria-haspopup="true"
|
|
||||||
aria-expanded={tooltipOpen}
|
|
||||||
onClick={(e) => e.preventDefault()}
|
|
||||||
>
|
|
||||||
<svg className="w-4 h-4 fill-current text-slate-400" viewBox="0 0 16 16">
|
|
||||||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm0 12c-.6 0-1-.4-1-1s.4-1 1-1 1 .4 1 1-.4 1-1 1zm1-3H7V4h2v5z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<div className={`z-10 absolute ${positionOuterClasses(position)}`}>
|
|
||||||
<Transition
|
|
||||||
show={tooltipOpen}
|
|
||||||
tag="div"
|
|
||||||
className={`rounded overflow-hidden ${bg === 'dark' ? 'bg-slate-800' : 'bg-white border border-slate-200 shadow-lg'} ${sizeClasses(size)} ${positionInnerClasses(position)}`}
|
|
||||||
enter="transition ease-out duration-200 transform"
|
|
||||||
enterStart="opacity-0 -translate-y-2"
|
|
||||||
enterEnd="opacity-100 translate-y-0"
|
|
||||||
leave="transition ease-out duration-200"
|
|
||||||
leaveStart="opacity-100"
|
|
||||||
leaveEnd="opacity-0"
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Transition>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Tooltip;
|
|
||||||
@@ -9,3 +9,10 @@
|
|||||||
@apply ring-0;
|
@apply ring-0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.loading-overlay {
|
||||||
|
background-color: rgba(0, 0, 0, 0.25);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|||||||
@@ -103,4 +103,4 @@ input[type="search"]::-webkit-search-results-decoration {
|
|||||||
.no-scrollbar {
|
.no-scrollbar {
|
||||||
-ms-overflow-style: none; /* IE and Edge */
|
-ms-overflow-style: none; /* IE and Edge */
|
||||||
scrollbar-width: none; /* Firefox */
|
scrollbar-width: none; /* Firefox */
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
|
|
||||||
// Additional styles
|
|
||||||
@import 'additional-styles/utility-patterns.scss';
|
@import 'additional-styles/utility-patterns.scss';
|
||||||
@import 'additional-styles/range-slider.scss';
|
@import 'additional-styles/range-slider.scss';
|
||||||
@import 'additional-styles/toggle-switch.scss';
|
@import 'additional-styles/toggle-switch.scss';
|
||||||
|
|||||||
92
src/images/GenerateOnboardingSvg/GenerateSvg.js
Normal file
92
src/images/GenerateOnboardingSvg/GenerateSvg.js
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
function createBlob(options) {
|
||||||
|
|
||||||
|
let points = [];
|
||||||
|
let slice = (Math.PI * 2) / options.numPoints;
|
||||||
|
let startAngle = 0;
|
||||||
|
|
||||||
|
for (let i = 0; i < options.subkey.length; i++) {
|
||||||
|
let angle = startAngle + i * slice;
|
||||||
|
let rnd = Number("0x"+options.subkey.substring(i+0,i+1));
|
||||||
|
let point = {
|
||||||
|
x: options.centerX + Math.cos(angle) * (options.radius + rnd),
|
||||||
|
y: options.centerY + Math.sin(angle) * (options.radius + rnd)
|
||||||
|
};
|
||||||
|
points.push(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
let size = points.length;
|
||||||
|
let path = "M" + points[0].x + " " + points[0].y + " C";
|
||||||
|
|
||||||
|
for (let i = 0; i < size; i++) {
|
||||||
|
let p0 = points[(i - 1 + size) % size];
|
||||||
|
let p1 = points[i];
|
||||||
|
let p2 = points[(i + 1) % size];
|
||||||
|
let p3 = points[(i + 2) % size];
|
||||||
|
|
||||||
|
let x1 = p1.x + (p2.x - p0.x) / 6;
|
||||||
|
let y1 = p1.y + (p2.y - p0.y) / 6;
|
||||||
|
|
||||||
|
let x2 = p2.x - (p3.x - p1.x) / 6;
|
||||||
|
let y2 = p2.y - (p3.y - p1.y) / 6;
|
||||||
|
|
||||||
|
path += " " + x1 + " " + y1 + " " + x2 + " " + y2 + " " + p2.x + " " + p2.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
return path + "z";
|
||||||
|
}
|
||||||
|
|
||||||
|
export var generateSvgAvatar = ( function () {
|
||||||
|
return function (publicKey, seed, raw) {
|
||||||
|
let pubKey = publicKey || Math.floor(Math.random()*65535*65535).toString(16) + Math.floor(Math.random()*65535*65535).toString(16) + Math.floor(Math.random()*65535*65535).toString(16) + Math.floor(Math.random()*65535*65535).toString(16) + Math.floor(Math.random()*65535*65535).toString(16) + Math.floor(Math.random()*65535*65535).toString(16) + Math.floor(Math.random()*65535*65535).toString(16) + Math.floor(Math.random()*65535*65535).toString(16);
|
||||||
|
//pubKey = "73f47d4929d7b2b6598ca4999d52567f9bb5aef3e353e0a66b468096db6e4e88"
|
||||||
|
let particles = [];
|
||||||
|
let gradients = ['#000000'];
|
||||||
|
let defs = [];
|
||||||
|
|
||||||
|
for (let a = 0; a<64; a = a + 8) {
|
||||||
|
let blob = createBlob({
|
||||||
|
numPoints: 8,
|
||||||
|
centerX: 256,
|
||||||
|
centerY: 256-a*4,
|
||||||
|
radius: 16,
|
||||||
|
subkey: pubKey.substring(a,a + 8)
|
||||||
|
});
|
||||||
|
|
||||||
|
let color = "#" + pubKey.substring(a+2,a+8);
|
||||||
|
let width = Number("0x"+pubKey.substring(a,a+1));
|
||||||
|
let opacity = Number("0x"+pubKey.substring(a+1,a+2))/8;
|
||||||
|
|
||||||
|
gradients.push(color);
|
||||||
|
defs.push(`<radialGradient id="a-${a}" cx="0" cy="0" r="0.75" fx="0.35" fy="0.5" spreadMethod="reflect"><stop offset="0%" stop-color="${gradients[gradients.length-1]}"/><stop offset="100%" stop-color="${gradients[gradients.length]}"/></radialGradient>`);
|
||||||
|
particles.push(`<path d="${blob}" stroke="url(#a-${a})" stroke-width="${width}" stroke-opacity = "${opacity}" fill="transparent"/>`);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
let ph = "";
|
||||||
|
let off = 4 + Number("0x"+pubKey.substring(0,1));
|
||||||
|
let rotate = 0;
|
||||||
|
for (var i = 0; i < off; i++){
|
||||||
|
ph = ph + `<use xlink:href="#pattern-${pubKey}" mask="url(#mask)" class="segment" style="transform-origin:center center;transform: scaleY(1) rotate(${rotate}deg)"></use>,` + "\n";
|
||||||
|
rotate = rotate + 360/off;
|
||||||
|
}
|
||||||
|
|
||||||
|
var svg = [
|
||||||
|
'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="512" height="512" preserveAspectRatio="xMidYMid slice" viewBox="0 0 512 512">',
|
||||||
|
'<defs>',
|
||||||
|
'<radialGradient id="e" cx="0" cy="0" r="0.75" fx="0.35" fy="0.5" spreadMethod="reflect">',
|
||||||
|
'<stop offset="0%" stop-color="red"/>',
|
||||||
|
'<stop offset="100%" stop-color="blue"/>',
|
||||||
|
'</radialGradient>',defs.join('\n'),
|
||||||
|
'</defs>',
|
||||||
|
'<symbol id="pattern-' + pubKey + '">',
|
||||||
|
particles.join(''),
|
||||||
|
'</symbol>',
|
||||||
|
'<g style="transform-origin:center center; transform: rotate(' + pubKey + 'deg)">',
|
||||||
|
ph,
|
||||||
|
'</g>',
|
||||||
|
'</svg>',
|
||||||
|
].join('');
|
||||||
|
return raw ? svg : 'data:image/svg+xml;base64,' + btoa(svg);
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
||||||
10
src/images/profile-icon.svg
Normal file
10
src/images/profile-icon.svg
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<circle cx="18" cy="18" r="18" fill="#E1E1F7"/>
|
||||||
|
<rect x="6" y="6" width="24" height="24" fill="url(#pattern0)"/>
|
||||||
|
<defs>
|
||||||
|
<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1">
|
||||||
|
<use xlink:href="#image0_21_1525" transform="scale(0.0125)"/>
|
||||||
|
</pattern>
|
||||||
|
<image id="image0_21_1525" width="80" height="80" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAYAAACOEfKtAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAUKADAAQAAAABAAAAUAAAAAAx4ExPAAAHHUlEQVR4Ae1bWYwVRRRlwBGXaBRxRQaMGvDDiAG/lCigjHEDE/VHPox8uGCi4o8mij/G6Iea6JcJ0TCSEDVKYhC3EOPglhgMGoMxKswQBRWXuG8snjNTd7xTr+u9qq7q9/pp3eRQ1bfvPffW7br9+r0eJkzIkiuQK5ArkCuQK5ArkCuQK5ArkCuQK5ArkCvw/6pAT5uWOw1xLgQWAWcCUw3+xrgL2ApsAJ4B/gJccixOLAb6gdnACQB1oTxw6Q45G2k+DewFDnhgGDaXA7acAcU6YB8Qw2Pz1vZ4MjJ7TC32d8yfB24B5gLckbQ5AmBxbgC2ACzOfuA2gNILPAroC8CdeitwDjAdeAt4FyDPjYDmoV3XyYnIWBbBwj0AsNVaCW8nKwEWkFgGvAGwqH8C24BBwJbNUGg9eW4HyMEd2w90jXBHvQ9w0Z8Ac4BQuQcOuk3/wPF5oSSwF54fMX8N4MU5Eqi1vIDsuHjuliklM50EvyFAF/ErHJ8LiLBtufNs0XofHtu/o8eXIDoXvQfoS5DJ4eBYAGwCyPsLMBug2G07qi3Wc9dtBHYDNo/4dXzkfecjk+CKxNlwJw0Y7rcjuMmzNgFPRApu13kmsSGMB7nNSp/hbmQbcwfpViahblseixTpuRv5wVbEI35B48Qga7fxEnNqPUY+cqSWX0G42pAutcj5acuC2FKk/wlG7xlDm8f2b+uxPG7wW0JVsgjELFRMGzO3VDzkSiafgomLOy0ZYyPRSSbGFxiL2pMePnrNQ58oSdXC8qDM+1RV8oMh5uNRUXvytI/+e8Vjpp0f5MZ8aIWpHAZu7nLeD2PkYDin4BnJIdUObMdVlQdz2YlSRJ+2FVuOfCak2Dyj2sB/UxVQkjkmMH6IuXDLxRJfn7YVW47ylGDzaJu2zzcjItviggojy6fn65Exzoc/c43lGUkj1Q78zixKdok5TDoIN3dOaNtq+2kmqyQ7MFUBd5qkTk5asvFk080hY4W2rbaXHCXn8VECj1J97Ro2cWcExg8xF+4hOPH3viKZX6SETuvlQgw5bIPUqXbgDhN1ZlD0MOM+Yy4XS7x1e4qOo0svxbR5tK/3PFUBvzQRZ3pHDjeUHbjLctXtqU+59EcZI5tH+7Z9/iwiHgA+rzDydhODb+5iJBVPTA4Nvj9DwwLyfUhVQm7GYCxXe/roNU90rqlaWD7RTo/OyE0g3Izlak8fveZxR2vzmUcQj7tjVYVxyc0YD0fGSMUTmcZ4d3kfwgUKxluUPxI+GS+2qHzali7iL6PNY9H6HaZqYX5Bvx+Q78SMzl89YkVzkPs+4GWL1Kdte5WPi0eZdHb6McLzKp+SII1TDRdfk8bIDDgzp1iehhxS7UBNLEnO0sqSc+EQTqHxbVuxf9xMbB45X3qsooDvmGyuKZ3Vv47CIZxyxqdtxZZjnzmwebRNbeb8eZ9/osY3YMdFZHU8fPnMRy7Oywpz4Ev5WJ6y8Uv5DcCL95znSnmPOq03HGsMR2jbiv06i8fQ1XvgHz3uMYnfXSLVe43vNxinGn/+aDto5npopudFJDSP9q31vB/Z8S+ruICHAjLlgzJ96HtRgJ9t+iAUKXhs3rYeX2YWwYX4Cm2JSwFpQ9vXR695bP9kx1V8CuvkNuiDwPmLsA/9tC2yJ09Xi+wE30WE2rt4U/G4+Ef0Ve/ApsEDT/q0bSBlvHmVBeTD66qIFOlLDpH9mHBX2eLSi53NI/pajj3Iir/MvALsA6SNQt4/0Fb8yPESUObT2OZhTsyNOdZO+HbvWuADQBbPv2FZAywAQnY6bekzAJBD+LZivgzoBXzamTwLAfLILiUXc2Suqd5Igqq8TIbrCmAHIAv9DPOVgLy8wbS0kOMOgO9ahH8Y873Aq4AtzR6qt8B4JyA82zFn7lxDR+RKRNUL4w65CuCVTy3kvBpgDF0AxgsR/r54HbANEB6ugWtpm8xCpE2AJPAh5lcAPUDVwhiMxZgSfzfm3Hm2NGtznlsKaB6uiWurVHgPkjdw32J+EzCp0ojF5Ix5M8AcWEje45YDWljUQa0wc623ebg23h+TC+8TqwG56k9hfnTyKOGEU+CyFpC8nsD8kHCakf8UpHm4Vq45iTAhPkowSX4qXg/UTZYjIfnEfhNz/S6FuTZrZ+5IEc2zEcoyF0O4xkZeVRbva+CsMW39JsyNOTJX7iAtLFKrdhb7Zjxi4z32w5IJ/QbUuXiyoDkmV+a8UJQlRs2zuIT/mAtfITKZO8c09Z/cZXLmT/i6PSVz33YWHt6+nDLReWb0xFxz/skWdnU6Lbn2IilefFv4ie2jF555NkHIMQMVBQvh6IRtqrxb8tTi+2AbKsy25c6bb8VqpbfMGw9bfXvoxt3XuMp4jbNOre6B8aEzQ65ArkCuQK5ArkCuQK5ArkCuQK5ArkCuQK5ArsB/qgL/AIxZGoBhTSTCAAAAAElFTkSuQmCC"/>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.1 KiB |
11
src/main.jsx
11
src/main.jsx
@@ -1,8 +1,15 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
import { BrowserRouter as Router } from 'react-router-dom'
|
import {Buffer} from "buffer";
|
||||||
|
import { HashRouter as Router } from 'react-router-dom'
|
||||||
import App from './App'
|
import App from './App'
|
||||||
|
|
||||||
|
globalThis.Buffer = Buffer
|
||||||
|
|
||||||
|
BigInt.prototype.toJSON = function() {
|
||||||
|
return this.toString()
|
||||||
|
}
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<Router>
|
<Router>
|
||||||
@@ -10,4 +17,4 @@ ReactDOM.render(
|
|||||||
</Router>
|
</Router>
|
||||||
</React.StrictMode>,
|
</React.StrictMode>,
|
||||||
document.getElementById('root')
|
document.getElementById('root')
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,92 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
|
|
||||||
import Sidebar from '../partials/Sidebar';
|
|
||||||
import Header from '../partials/Header';
|
|
||||||
import Datepicker from '../components/Datepicker';
|
|
||||||
import AnalyticsCard01 from '../partials/analytics/AnalyticsCard01';
|
|
||||||
import AnalyticsCard02 from '../partials/analytics/AnalyticsCard02';
|
|
||||||
import AnalyticsCard03 from '../partials/analytics/AnalyticsCard03';
|
|
||||||
import AnalyticsCard04 from '../partials/analytics/AnalyticsCard04';
|
|
||||||
import AnalyticsCard05 from '../partials/analytics/AnalyticsCard05';
|
|
||||||
import AnalyticsCard06 from '../partials/analytics/AnalyticsCard06';
|
|
||||||
import AnalyticsCard07 from '../partials/analytics/AnalyticsCard07';
|
|
||||||
import AnalyticsCard08 from '../partials/analytics/AnalyticsCard08';
|
|
||||||
import AnalyticsCard09 from '../partials/analytics/AnalyticsCard09';
|
|
||||||
import AnalyticsCard10 from '../partials/analytics/AnalyticsCard10';
|
|
||||||
import AnalyticsCard11 from '../partials/analytics/AnalyticsCard11';
|
|
||||||
|
|
||||||
function Analytics() {
|
|
||||||
|
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex h-screen overflow-hidden">
|
|
||||||
|
|
||||||
{/* Sidebar */}
|
|
||||||
<Sidebar sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
{/* Content area */}
|
|
||||||
<div className="relative flex flex-col flex-1 overflow-y-auto overflow-x-hidden">
|
|
||||||
|
|
||||||
{/* Site header */}
|
|
||||||
<Header sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div className="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
|
|
||||||
|
|
||||||
{/* Page header */}
|
|
||||||
<div className="sm:flex sm:justify-between sm:items-center mb-8">
|
|
||||||
|
|
||||||
{/* Left: Title */}
|
|
||||||
<div className="mb-4 sm:mb-0">
|
|
||||||
<h1 className="text-2xl md:text-3xl text-slate-800 font-bold">Analytics ✨</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Right: Actions */}
|
|
||||||
<div className="grid grid-flow-col sm:auto-cols-max justify-start sm:justify-end gap-2">
|
|
||||||
|
|
||||||
{/* Datepicker built with flatpickr */}
|
|
||||||
<Datepicker align="right" />
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Cards */}
|
|
||||||
<div className="grid grid-cols-12 gap-6">
|
|
||||||
|
|
||||||
{/* Line chart (Analytics) */}
|
|
||||||
<AnalyticsCard01 />
|
|
||||||
{/* Line chart (Active Users Right Now) */}
|
|
||||||
<AnalyticsCard02 />
|
|
||||||
{/* Stacked bar chart (Acquisition Channels) */}
|
|
||||||
<AnalyticsCard03 />
|
|
||||||
{/* Horizontal bar chart (Audience Overview) */}
|
|
||||||
<AnalyticsCard04 />
|
|
||||||
{/* Report card (Top Channels) */}
|
|
||||||
<AnalyticsCard05 />
|
|
||||||
{/* Report card (Top Pages) */}
|
|
||||||
<AnalyticsCard06 />
|
|
||||||
{/* Report card (Top Countries) */}
|
|
||||||
<AnalyticsCard07 />
|
|
||||||
{/* Doughnut chart (Sessions By Device) */}
|
|
||||||
<AnalyticsCard08 />
|
|
||||||
{/* Doughnut chart (Visit By Age Category) */}
|
|
||||||
<AnalyticsCard09 />
|
|
||||||
{/* Polar chart (Sessions By Gender) */}
|
|
||||||
<AnalyticsCard10 />
|
|
||||||
{/* Table (Top Products) */}
|
|
||||||
<AnalyticsCard11 />
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Analytics;
|
|
||||||
@@ -1,461 +0,0 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
|
||||||
|
|
||||||
import Sidebar from '../partials/Sidebar';
|
|
||||||
import Header from '../partials/Header';
|
|
||||||
|
|
||||||
function Calendar() {
|
|
||||||
|
|
||||||
const today = new Date();
|
|
||||||
const monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
|
|
||||||
const dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
|
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
||||||
const [month, setMonth] = useState(today.getMonth());
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const [year, setYear] = useState(today.getFullYear());
|
|
||||||
const [daysInMonth, setDaysInMonth] = useState([])
|
|
||||||
const [startingBlankDays, setStartingBlankDays] = useState([])
|
|
||||||
const [endingBlankDays, setEndingBlankDays] = useState([])
|
|
||||||
const events = [
|
|
||||||
// Previous month
|
|
||||||
{
|
|
||||||
eventStart: new Date(new Date().getFullYear(), new Date().getMonth() - 1, 8, 3),
|
|
||||||
eventEnd: new Date(new Date().getFullYear(), new Date().getMonth() - 1, 8, 7),
|
|
||||||
eventName: '⛱️ Relax for 2 at Marienbad',
|
|
||||||
eventColor: 'indigo'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventStart: new Date(new Date().getFullYear(), new Date().getMonth() - 1, 12, 10),
|
|
||||||
eventEnd: new Date(new Date().getFullYear(), new Date().getMonth(), 12, 11),
|
|
||||||
eventName: 'Team Catch-up',
|
|
||||||
eventColor: 'sky'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventStart: new Date(new Date().getFullYear(), new Date().getMonth() - 1, 18, 2),
|
|
||||||
eventEnd: '',
|
|
||||||
eventName: '✍️ New Project (2)',
|
|
||||||
eventColor: 'yellow'
|
|
||||||
},
|
|
||||||
// Current month
|
|
||||||
{
|
|
||||||
eventStart: new Date(new Date().getFullYear(), new Date().getMonth(), 1, 10),
|
|
||||||
eventEnd: new Date(new Date().getFullYear(), new Date().getMonth(), 1, 11),
|
|
||||||
eventName: 'Meeting w/ Patrick Lin',
|
|
||||||
eventColor: 'sky'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventStart: new Date(new Date().getFullYear(), new Date().getMonth(), 1, 19),
|
|
||||||
eventEnd: '',
|
|
||||||
eventName: 'Reservation at La Ginestre',
|
|
||||||
eventColor: 'indigo'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventStart: new Date(new Date().getFullYear(), new Date().getMonth(), 3, 9),
|
|
||||||
eventEnd: new Date(new Date().getFullYear(), new Date().getMonth(), 3, 10),
|
|
||||||
eventName: '✍️ New Project',
|
|
||||||
eventColor: 'yellow'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventStart: new Date(new Date().getFullYear(), new Date().getMonth(), 7, 21),
|
|
||||||
eventEnd: new Date(new Date().getFullYear(), new Date().getMonth(), 7, 22),
|
|
||||||
eventName: '⚽ 2021 - Semi-final',
|
|
||||||
eventColor: 'red'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventStart: new Date(new Date().getFullYear(), new Date().getMonth(), 9, 10),
|
|
||||||
eventEnd: new Date(new Date().getFullYear(), new Date().getMonth(), 9, 11),
|
|
||||||
eventName: 'Meeting w/Carolyn',
|
|
||||||
eventColor: 'sky'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventStart: new Date(new Date().getFullYear(), new Date().getMonth(), 9, 13),
|
|
||||||
eventEnd: '',
|
|
||||||
eventName: 'Pick up Marta at school',
|
|
||||||
eventColor: 'emerald'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventStart: new Date(new Date().getFullYear(), new Date().getMonth(), 9, 14),
|
|
||||||
eventEnd: new Date(new Date().getFullYear(), new Date().getMonth(), 9, 15),
|
|
||||||
eventName: 'Meeting w/ Patrick Lin',
|
|
||||||
eventColor: 'emerald'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventStart: new Date(new Date().getFullYear(), new Date().getMonth(), 9, 19),
|
|
||||||
eventEnd: '',
|
|
||||||
eventName: 'Reservation at La Ginestre',
|
|
||||||
eventColor: 'indigo'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventStart: new Date(new Date().getFullYear(), new Date().getMonth(), 11, 10),
|
|
||||||
eventEnd: new Date(new Date().getFullYear(), new Date().getMonth(), 11, 11),
|
|
||||||
eventName: '⛱️ Relax for 2 at Marienbad',
|
|
||||||
eventColor: 'indigo'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventStart: new Date(new Date().getFullYear(), new Date().getMonth(), 11, 19),
|
|
||||||
eventEnd: '',
|
|
||||||
eventName: '⚽ 2021 - Semi-final',
|
|
||||||
eventColor: 'red'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventStart: new Date(new Date().getFullYear(), new Date().getMonth(), 14, 10),
|
|
||||||
eventEnd: new Date(new Date().getFullYear(), new Date().getMonth(), 14, 11),
|
|
||||||
eventName: 'Team Catch-up',
|
|
||||||
eventColor: 'sky'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventStart: new Date(new Date().getFullYear(), new Date().getMonth(), 21, 2),
|
|
||||||
eventEnd: '',
|
|
||||||
eventName: 'Pick up Marta at school',
|
|
||||||
eventColor: 'emerald'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventStart: new Date(new Date().getFullYear(), new Date().getMonth(), 21, 3),
|
|
||||||
eventEnd: new Date(new Date().getFullYear(), new Date().getMonth(), 21, 7),
|
|
||||||
eventName: '✍️ New Project (2)',
|
|
||||||
eventColor: 'yellow'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventStart: new Date(new Date().getFullYear(), new Date().getMonth(), 22, 10),
|
|
||||||
eventEnd: new Date(new Date().getFullYear(), new Date().getMonth(), 22, 11),
|
|
||||||
eventName: 'Team Catch-up',
|
|
||||||
eventColor: 'sky'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventStart: new Date(new Date().getFullYear(), new Date().getMonth(), 22, 19),
|
|
||||||
eventEnd: '',
|
|
||||||
eventName: '⚽ 2021 - Semi-final',
|
|
||||||
eventColor: 'red'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventStart: new Date(new Date().getFullYear(), new Date().getMonth(), 23, 0),
|
|
||||||
eventEnd: new Date(new Date().getFullYear(), new Date().getMonth(), 23, 23),
|
|
||||||
eventName: 'You stay at Meridiana B&B',
|
|
||||||
eventColor: 'indigo'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventStart: new Date(new Date().getFullYear(), new Date().getMonth(), 25, 10),
|
|
||||||
eventEnd: new Date(new Date().getFullYear(), new Date().getMonth(), 25, 11),
|
|
||||||
eventName: 'Meeting w/ Kylie Joh',
|
|
||||||
eventColor: 'sky'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventStart: new Date(new Date().getFullYear(), new Date().getMonth(), 29, 10),
|
|
||||||
eventEnd: new Date(new Date().getFullYear(), new Date().getMonth(), 29, 11),
|
|
||||||
eventName: 'Call Request ->',
|
|
||||||
eventColor: 'sky'
|
|
||||||
},
|
|
||||||
// Next month
|
|
||||||
{
|
|
||||||
eventStart: new Date(new Date().getFullYear(), new Date().getMonth() + 1, 2, 3),
|
|
||||||
eventEnd: new Date(new Date().getFullYear(), new Date().getMonth() + 1, 2, 7),
|
|
||||||
eventName: '✍️ New Project (2)',
|
|
||||||
eventColor: 'yellow'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventStart: new Date(new Date().getFullYear(), new Date().getMonth() + 1, 14, 10),
|
|
||||||
eventEnd: new Date(new Date().getFullYear(), new Date().getMonth(), 14, 11),
|
|
||||||
eventName: 'Team Catch-up',
|
|
||||||
eventColor: 'sky'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventStart: new Date(new Date().getFullYear(), new Date().getMonth() + 1, 25, 2),
|
|
||||||
eventEnd: new Date(new Date().getFullYear(), new Date().getMonth() + 1, 25, 3),
|
|
||||||
eventName: 'Pick up Marta at school',
|
|
||||||
eventColor: 'emerald'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventStart: new Date(new Date().getFullYear(), new Date().getMonth() + 1, 27, 21),
|
|
||||||
eventEnd: new Date(new Date().getFullYear(), new Date().getMonth() + 1, 27, 22),
|
|
||||||
eventName: '⚽ 2021 - Semi-final',
|
|
||||||
eventColor: 'red'
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const isToday = (date) => {
|
|
||||||
const day = new Date(year, month, date);
|
|
||||||
return today.toDateString() === day.toDateString() ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const getEvents = (date) => {
|
|
||||||
return events.filter(e => new Date(e.eventStart).toDateString() === new Date(year, month, date).toDateString());
|
|
||||||
}
|
|
||||||
|
|
||||||
const eventColor = (color) => {
|
|
||||||
switch (color) {
|
|
||||||
case 'sky':
|
|
||||||
return 'text-white bg-sky-500';
|
|
||||||
case 'indigo':
|
|
||||||
return 'text-white bg-indigo-500';
|
|
||||||
case 'yellow':
|
|
||||||
return 'text-white bg-amber-500';
|
|
||||||
case 'emerald':
|
|
||||||
return 'text-white bg-emerald-500';
|
|
||||||
case 'red':
|
|
||||||
return 'text-white bg-rose-400';
|
|
||||||
default:
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getDays = () => {
|
|
||||||
const days = new Date(year, month + 1, 0).getDate();
|
|
||||||
|
|
||||||
// starting empty cells (previous month)
|
|
||||||
const startingDayOfWeek = new Date(year, month).getDay();
|
|
||||||
let startingBlankDaysArray = [];
|
|
||||||
for (let i = 1; i <= startingDayOfWeek; i++) {
|
|
||||||
startingBlankDaysArray.push(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ending empty cells (next month)
|
|
||||||
const endingDayOfWeek = new Date(year, month + 1, 0).getDay();
|
|
||||||
let endingBlankDaysArray = [];
|
|
||||||
for (let i = 1; i < 7 - endingDayOfWeek; i++) {
|
|
||||||
endingBlankDaysArray.push(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// current month cells
|
|
||||||
let daysArray = [];
|
|
||||||
for (let i = 1; i <= days; i++) {
|
|
||||||
daysArray.push(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
setStartingBlankDays(startingBlankDaysArray);
|
|
||||||
setEndingBlankDays(endingBlankDaysArray);
|
|
||||||
setDaysInMonth(daysArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
getDays();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex h-screen overflow-hidden">
|
|
||||||
|
|
||||||
{/* Sidebar */}
|
|
||||||
<Sidebar sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
{/* Content area */}
|
|
||||||
<div className="relative flex flex-col flex-1 overflow-y-auto overflow-x-hidden">
|
|
||||||
|
|
||||||
{/* Site header */}
|
|
||||||
<Header sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div className="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
|
|
||||||
|
|
||||||
{/* Page header */}
|
|
||||||
<div className="sm:flex sm:justify-between sm:items-center mb-4">
|
|
||||||
|
|
||||||
{/* Left: Title */}
|
|
||||||
<div className="mb-4 sm:mb-0">
|
|
||||||
<h1 className="text-2xl md:text-3xl text-slate-800 font-bold"><span>{`${monthNames[month]} ${year}`}</span> ✨</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Right: Actions */}
|
|
||||||
<div className="grid grid-flow-col sm:auto-cols-max justify-start sm:justify-end gap-2">
|
|
||||||
|
|
||||||
{/* Previous month button */}
|
|
||||||
<button
|
|
||||||
className="btn px-2.5 bg-white border-slate-200 hover:border-slate-300 text-slate-500 hover:text-slate-600 disabled:border-slate-200 disabled:bg-slate-100 disabled:text-slate-400 disabled:cursor-not-allowed"
|
|
||||||
disabled={month === 0 ? true : false}
|
|
||||||
onClick={() => {setMonth(month - 1);getDays();}}
|
|
||||||
>
|
|
||||||
<span className="sr-only">Previous month</span><wbr />
|
|
||||||
<svg className="h-4 w-4 fill-current" viewBox="0 0 16 16">
|
|
||||||
<path d="M9.4 13.4l1.4-1.4-4-4 4-4-1.4-1.4L4 8z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{/* Next month button */}
|
|
||||||
<button
|
|
||||||
className="btn px-2.5 bg-white border-slate-200 hover:border-slate-300 text-slate-500 hover:text-slate-600 disabled:border-slate-200 disabled:bg-slate-100 disabled:text-slate-400 disabled:cursor-not-allowed"
|
|
||||||
disabled={month === 11 ? true : false}
|
|
||||||
onClick={() => {setMonth(month + 1);getDays();}}
|
|
||||||
>
|
|
||||||
<span className="sr-only">Next month</span><wbr />
|
|
||||||
<svg className="h-4 w-4 fill-current" viewBox="0 0 16 16">
|
|
||||||
<path d="M6.6 13.4L5.2 12l4-4-4-4 1.4-1.4L12 8z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<hr className="w-px h-full bg-slate-200 mx-1" />
|
|
||||||
|
|
||||||
{/* Create event button */}
|
|
||||||
<button className="btn bg-indigo-500 hover:bg-indigo-600 text-white">
|
|
||||||
<svg className="w-4 h-4 fill-current opacity-50 shrink-0" viewBox="0 0 16 16">
|
|
||||||
<path d="M15 7H9V1c0-.6-.4-1-1-1S7 .4 7 1v6H1c-.6 0-1 .4-1 1s.4 1 1 1h6v6c0 .6.4 1 1 1s1-.4 1-1V9h6c.6 0 1-.4 1-1s-.4-1-1-1z" />
|
|
||||||
</svg>
|
|
||||||
<span className="hidden xs:block ml-2">Create Event</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Filters and view buttons */}
|
|
||||||
<div className="sm:flex sm:justify-between sm:items-center mb-4">
|
|
||||||
|
|
||||||
{/* Filters */}
|
|
||||||
<div className="mb-4 sm:mb-0 mr-2">
|
|
||||||
<ul className="flex flex-wrap items-center -m-1">
|
|
||||||
<li className="m-1">
|
|
||||||
<button className="btn-sm bg-white border-slate-200 hover:border-slate-300 text-slate-500">
|
|
||||||
<div className="w-1 h-3.5 bg-sky-500 shrink-0"></div>
|
|
||||||
<span className="ml-1.5">Acme Inc.</span>
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li className="m-1">
|
|
||||||
<button className="btn-sm bg-white border-slate-200 hover:border-slate-300 text-slate-500">
|
|
||||||
<div className="w-1 h-3.5 bg-emerald-500 shrink-0"></div>
|
|
||||||
<span className="ml-1.5">Life & Family</span>
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li className="m-1">
|
|
||||||
<button className="btn-sm bg-white border-slate-200 hover:border-slate-300 text-slate-500">
|
|
||||||
<div className="w-1 h-3.5 bg-indigo-500 shrink-0"></div>
|
|
||||||
<span className="ml-1.5">Reservations</span>
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li className="m-1">
|
|
||||||
<button className="btn-sm bg-white border-slate-200 hover:border-slate-300 text-slate-500">
|
|
||||||
<div className="w-1 h-3.5 bg-rose-400 shrink-0"></div>
|
|
||||||
<span className="ml-1.5">Events</span>
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li className="m-1">
|
|
||||||
<button className="btn-sm bg-white border-slate-200 hover:border-slate-300 text-slate-500">
|
|
||||||
<div className="w-1 h-3.5 bg-amber-500 shrink-0"></div>
|
|
||||||
<span className="ml-1.5">Misc</span>
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li className="m-1">
|
|
||||||
<button className="btn-sm bg-white border-slate-200 hover:border-slate-300 text-indigo-500">+Add New</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* View buttons (requires custom integration) */}
|
|
||||||
<div className="flex flex-nowrap -space-x-px">
|
|
||||||
<button className="btn bg-slate-50 border-slate-200 hover:bg-slate-50 text-indigo-500 rounded-none first:rounded-l last:rounded-r">Month</button>
|
|
||||||
<button className="btn bg-white border-slate-200 hover:bg-slate-50 text-slate-600 rounded-none first:rounded-l last:rounded-r">Week</button>
|
|
||||||
<button className="btn bg-white border-slate-200 hover:bg-slate-50 text-slate-600 rounded-none first:rounded-l last:rounded-r">Day</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Calendar table */}
|
|
||||||
<div className="bg-white rounded-sm shadow overflow-hidden">
|
|
||||||
|
|
||||||
{/* Days of the week */}
|
|
||||||
<div className="grid grid-cols-7 gap-px border-b border-slate-200">
|
|
||||||
{
|
|
||||||
dayNames.map(day => {
|
|
||||||
return (
|
|
||||||
<div className="px-1 py-3" key={day}>
|
|
||||||
<div className="text-slate-500 text-sm font-medium text-center lg:hidden">{day.substring(0,3)}</div>
|
|
||||||
<div className="text-slate-500 text-sm font-medium text-center hidden lg:block">{day}</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Day cells */}
|
|
||||||
<div className="grid grid-cols-7 gap-px bg-slate-200">
|
|
||||||
{/* Diagonal stripes pattern */}
|
|
||||||
<svg className="sr-only">
|
|
||||||
<defs>
|
|
||||||
<pattern id="stripes" patternUnits="userSpaceOnUse" width="5" height="5" patternTransform="rotate(135)">
|
|
||||||
<line className="stroke-current text-slate-200 opacity-50" x1="0" y="0" x2="0" y2="5" strokeWidth="2" />
|
|
||||||
</pattern>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
||||||
{/* Empty cells (previous month) */}
|
|
||||||
{
|
|
||||||
startingBlankDays.map(blankday => {
|
|
||||||
return (
|
|
||||||
<div className="bg-slate-50 h-20 sm:h-28 lg:h-36" key={blankday}>
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
|
|
||||||
<rect width="100%" height="100%" fill="url(#stripes)" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
{/* Days of the current month */}
|
|
||||||
{
|
|
||||||
daysInMonth.map(day => {
|
|
||||||
return (
|
|
||||||
<div className="relative bg-white h-20 sm:h-28 lg:h-36 overflow-hidden" key={day}>
|
|
||||||
<div className="h-full flex flex-col justify-between">
|
|
||||||
{/* Events */}
|
|
||||||
<div className="grow flex flex-col relative p-0.5 sm:p-1.5 overflow-hidden">
|
|
||||||
{
|
|
||||||
getEvents(day).map(event => {
|
|
||||||
return (
|
|
||||||
<button className="relative w-full text-left mb-1" key={event.eventName}>
|
|
||||||
<div className={`px-2 py-0.5 rounded overflow-hidden ${eventColor(event.eventColor)}`}>
|
|
||||||
{/* Event name */}
|
|
||||||
<div className="text-xs font-semibold truncate">{event.eventName}</div>
|
|
||||||
{/* Event time */}
|
|
||||||
<div className="text-xs uppercase truncate hidden sm:block">
|
|
||||||
{/* Start date */}
|
|
||||||
{event.eventStart &&
|
|
||||||
<span>{event.eventStart.toLocaleTimeString([], {hour12: true, hour: 'numeric', minute:'numeric'})}</span>
|
|
||||||
}
|
|
||||||
{/* End date */}
|
|
||||||
{event.eventEnd &&
|
|
||||||
<span>
|
|
||||||
- <span>{event.eventEnd.toLocaleTimeString([], {hour12: true, hour: 'numeric', minute:'numeric'})}</span>
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
<div className="absolute bottom-0 left-0 right-0 h-4 bg-gradient-to-t from-white to-transparent pointer-events-none" aria-hidden="true"></div>
|
|
||||||
</div>
|
|
||||||
{/* Cell footer */}
|
|
||||||
<div className="flex justify-between items-center p-0.5 sm:p-1.5">
|
|
||||||
{/* More button (if more than 2 events) */}
|
|
||||||
{getEvents(day).length > 2 &&
|
|
||||||
<button className="text-xs text-slate-500 font-medium whitespace-nowrap text-center sm:py-0.5 px-0.5 sm:px-2 border border-slate-200 rounded">
|
|
||||||
<span className="md:hidden">+</span><span>{getEvents(day).length - 2}</span> <span className="hidden md:inline">more</span>
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
{/* Day number */}
|
|
||||||
<button className={`inline-flex ml-auto w-6 h-6 items-center justify-center text-xs sm:text-sm font-medium text-center rounded-full hover:bg-indigo-100 ${isToday(day) && 'text-indigo-500'}`}>{day}</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
{/* Empty cells (next month) */}
|
|
||||||
{
|
|
||||||
endingBlankDays.map(blankday => {
|
|
||||||
return (
|
|
||||||
<div className="bg-slate-50 h-20 sm:h-28 lg:h-36" key={blankday}>
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
|
|
||||||
<rect width="100%" height="100%" fill="url(#stripes)" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Calendar;
|
|
||||||
@@ -1,423 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
|
|
||||||
import Sidebar from '../partials/Sidebar';
|
|
||||||
import Header from '../partials/Header';
|
|
||||||
import SearchForm from '../partials/actions/SearchForm';
|
|
||||||
import FilterButton from '../components/DropdownFilter';
|
|
||||||
import CampaignsCard from '../partials/campaigns/CampaignsCard';
|
|
||||||
import PaginationNumeric from '../components/PaginationNumeric';
|
|
||||||
|
|
||||||
import Image01 from '../images/user-28-01.jpg';
|
|
||||||
import Image02 from '../images/user-28-02.jpg';
|
|
||||||
import Image03 from '../images/user-28-03.jpg';
|
|
||||||
import Image04 from '../images/user-28-04.jpg';
|
|
||||||
import Image05 from '../images/user-28-05.jpg';
|
|
||||||
import Image06 from '../images/user-28-06.jpg';
|
|
||||||
import Image07 from '../images/user-28-07.jpg';
|
|
||||||
import Image08 from '../images/user-28-08.jpg';
|
|
||||||
import Image09 from '../images/user-28-09.jpg';
|
|
||||||
import Image10 from '../images/user-28-10.jpg';
|
|
||||||
import Image11 from '../images/user-28-11.jpg';
|
|
||||||
import Image12 from '../images/user-28-12.jpg';
|
|
||||||
|
|
||||||
function Campaigns() {
|
|
||||||
|
|
||||||
const items = [
|
|
||||||
{
|
|
||||||
id: 0,
|
|
||||||
category: '1',
|
|
||||||
members: [
|
|
||||||
{
|
|
||||||
name: 'User 01',
|
|
||||||
image: Image01,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'User 02',
|
|
||||||
image: Image02,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'User 03',
|
|
||||||
image: Image03,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
],
|
|
||||||
title: 'Monitor progress in Real Time Value',
|
|
||||||
link: '#0',
|
|
||||||
content: 'Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts.',
|
|
||||||
dates: {
|
|
||||||
from: 'Jan 20',
|
|
||||||
to: 'Jan 27'
|
|
||||||
},
|
|
||||||
type: 'One-Time'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
category: '2',
|
|
||||||
members: [
|
|
||||||
{
|
|
||||||
name: 'User 04',
|
|
||||||
image: Image04,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'User 05',
|
|
||||||
image: Image05,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
],
|
|
||||||
title: 'Monitor progress in Real Time Value',
|
|
||||||
link: '#0',
|
|
||||||
content: 'Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts.',
|
|
||||||
dates: {
|
|
||||||
from: 'Jan 20',
|
|
||||||
to: 'Jan 27'
|
|
||||||
},
|
|
||||||
type: 'Off-Track'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
category: '3',
|
|
||||||
members: [
|
|
||||||
{
|
|
||||||
name: 'User 07',
|
|
||||||
image: Image07,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'User 08',
|
|
||||||
image: Image08,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'User 09',
|
|
||||||
image: Image09,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
],
|
|
||||||
title: 'Monitor progress in Real Time Value',
|
|
||||||
link: '#0',
|
|
||||||
content: 'Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts.',
|
|
||||||
dates: {
|
|
||||||
from: 'Jan 20',
|
|
||||||
to: 'Jan 27'
|
|
||||||
},
|
|
||||||
type: 'At Risk'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
category: '1',
|
|
||||||
members: [
|
|
||||||
{
|
|
||||||
name: 'User 10',
|
|
||||||
image: Image10,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
],
|
|
||||||
title: 'Monitor progress in Real Time Value',
|
|
||||||
link: '#0',
|
|
||||||
content: 'Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts.',
|
|
||||||
dates: {
|
|
||||||
from: 'Jan 20',
|
|
||||||
to: 'Jan 27'
|
|
||||||
},
|
|
||||||
type: 'At Risk'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
category: '4',
|
|
||||||
members: [
|
|
||||||
{
|
|
||||||
name: 'User 11',
|
|
||||||
image: Image11,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'User 05',
|
|
||||||
image: Image05,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'User 12',
|
|
||||||
image: Image12,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
],
|
|
||||||
title: 'Monitor progress in Real Time Value',
|
|
||||||
link: '#0',
|
|
||||||
content: 'Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts.',
|
|
||||||
dates: {
|
|
||||||
from: 'Jan 20',
|
|
||||||
to: 'Jan 27'
|
|
||||||
},
|
|
||||||
type: 'One-Time'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 6,
|
|
||||||
category: '2',
|
|
||||||
members: [
|
|
||||||
{
|
|
||||||
name: 'User 07',
|
|
||||||
image: Image07,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'User 04',
|
|
||||||
image: Image04,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'User 11',
|
|
||||||
image: Image11,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
],
|
|
||||||
title: 'Monitor progress in Real Time Value',
|
|
||||||
link: '#0',
|
|
||||||
content: 'Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts.',
|
|
||||||
dates: {
|
|
||||||
from: 'Jan 20',
|
|
||||||
to: 'Jan 27'
|
|
||||||
},
|
|
||||||
type: 'At Risk'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 7,
|
|
||||||
category: '4',
|
|
||||||
members: [
|
|
||||||
{
|
|
||||||
name: 'User 01',
|
|
||||||
image: Image01,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'User 02',
|
|
||||||
image: Image02,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'User 06',
|
|
||||||
image: Image06,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
],
|
|
||||||
title: 'Monitor progress in Real Time Value',
|
|
||||||
link: '#0',
|
|
||||||
content: 'Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts.',
|
|
||||||
dates: {
|
|
||||||
from: 'Jan 20',
|
|
||||||
to: 'Jan 27'
|
|
||||||
},
|
|
||||||
type: 'One-Time'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 8,
|
|
||||||
category: '1',
|
|
||||||
members: [
|
|
||||||
{
|
|
||||||
name: 'User 09',
|
|
||||||
image: Image09,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'User 01',
|
|
||||||
image: Image01,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
],
|
|
||||||
title: 'Monitor progress in Real Time Value',
|
|
||||||
link: '#0',
|
|
||||||
content: 'Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts.',
|
|
||||||
dates: {
|
|
||||||
from: 'Jan 20',
|
|
||||||
to: 'Jan 27'
|
|
||||||
},
|
|
||||||
type: 'Off-Track'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 9,
|
|
||||||
category: '3',
|
|
||||||
members: [
|
|
||||||
{
|
|
||||||
name: 'User 07',
|
|
||||||
image: Image07,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'User 08',
|
|
||||||
image: Image08,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'User 09',
|
|
||||||
image: Image09,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'User 06',
|
|
||||||
image: Image06,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
],
|
|
||||||
title: 'Monitor progress in Real Time Value',
|
|
||||||
link: '#0',
|
|
||||||
content: 'Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts.',
|
|
||||||
dates: {
|
|
||||||
from: 'Jan 20',
|
|
||||||
to: 'Jan 27'
|
|
||||||
},
|
|
||||||
type: 'One-Time'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 10,
|
|
||||||
category: '4',
|
|
||||||
members: [
|
|
||||||
{
|
|
||||||
name: 'User 06',
|
|
||||||
image: Image06,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'User 11',
|
|
||||||
image: Image11,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
],
|
|
||||||
title: 'Monitor progress in Real Time Value',
|
|
||||||
link: '#0',
|
|
||||||
content: 'Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts.',
|
|
||||||
dates: {
|
|
||||||
from: 'Jan 20',
|
|
||||||
to: 'Jan 27'
|
|
||||||
},
|
|
||||||
type: 'Off-Track'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 11,
|
|
||||||
category: '2',
|
|
||||||
members: [
|
|
||||||
{
|
|
||||||
name: 'User 05',
|
|
||||||
image: Image05,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
],
|
|
||||||
title: 'Monitor progress in Real Time Value',
|
|
||||||
link: '#0',
|
|
||||||
content: 'Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts.',
|
|
||||||
dates: {
|
|
||||||
from: 'Jan 20',
|
|
||||||
to: 'Jan 27'
|
|
||||||
},
|
|
||||||
type: 'Off-Track'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 12,
|
|
||||||
category: '3',
|
|
||||||
members: [
|
|
||||||
{
|
|
||||||
name: 'User 07',
|
|
||||||
image: Image07,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'User 08',
|
|
||||||
image: Image08,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'User 09',
|
|
||||||
image: Image09,
|
|
||||||
link: '#0'
|
|
||||||
},
|
|
||||||
],
|
|
||||||
title: 'Monitor progress in Real Time Value',
|
|
||||||
link: '#0',
|
|
||||||
content: 'Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts.',
|
|
||||||
dates: {
|
|
||||||
from: 'Jan 20',
|
|
||||||
to: 'Jan 27'
|
|
||||||
},
|
|
||||||
type: 'At Risk'
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex h-screen overflow-hidden">
|
|
||||||
|
|
||||||
{/* Sidebar */}
|
|
||||||
<Sidebar sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
{/* Content area */}
|
|
||||||
<div className="relative flex flex-col flex-1 overflow-y-auto overflow-x-hidden">
|
|
||||||
|
|
||||||
{/* Site header */}
|
|
||||||
<Header sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div className="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
|
|
||||||
|
|
||||||
{/* Page header */}
|
|
||||||
<div className="sm:flex sm:justify-between sm:items-center mb-8">
|
|
||||||
|
|
||||||
{/* Left: Title */}
|
|
||||||
<div className="mb-4 sm:mb-0">
|
|
||||||
<h1 className="text-2xl md:text-3xl text-slate-800 font-bold">Campaigns ✨</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Right: Actions */}
|
|
||||||
<div className="grid grid-flow-col sm:auto-cols-max justify-start sm:justify-end gap-2">
|
|
||||||
{/* Search form */}
|
|
||||||
<SearchForm />
|
|
||||||
{/* Filter button */}
|
|
||||||
<FilterButton align="right" />
|
|
||||||
{/* Create campaign button */}
|
|
||||||
<button className="btn bg-indigo-500 hover:bg-indigo-600 text-white">
|
|
||||||
<svg className="w-4 h-4 fill-current opacity-50 shrink-0" viewBox="0 0 16 16">
|
|
||||||
<path d="M15 7H9V1c0-.6-.4-1-1-1S7 .4 7 1v6H1c-.6 0-1 .4-1 1s.4 1 1 1h6v6c0 .6.4 1 1 1s1-.4 1-1V9h6c.6 0 1-.4 1-1s-.4-1-1-1z" />
|
|
||||||
</svg>
|
|
||||||
<span className="hidden xs:block ml-2">Create Campaign</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Cards */}
|
|
||||||
<div className="grid grid-cols-12 gap-6">
|
|
||||||
{
|
|
||||||
items.map(item => {
|
|
||||||
return (
|
|
||||||
<CampaignsCard
|
|
||||||
key={item.id}
|
|
||||||
id={item.id}
|
|
||||||
category={item.category}
|
|
||||||
members={item.members}
|
|
||||||
title={item.title}
|
|
||||||
link={item.link}
|
|
||||||
content={item.content}
|
|
||||||
dates={item.dates}
|
|
||||||
type={item.type}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Pagination */}
|
|
||||||
<div className="mt-8">
|
|
||||||
<PaginationNumeric />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Campaigns;
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
|
|
||||||
import Sidebar from '../partials/Sidebar';
|
|
||||||
import Header from '../partials/Header';
|
|
||||||
import WelcomeBanner from '../partials/dashboard/WelcomeBanner';
|
|
||||||
import DashboardAvatars from '../partials/dashboard/DashboardAvatars';
|
|
||||||
import FilterButton from '../components/DropdownFilter';
|
|
||||||
import Datepicker from '../components/Datepicker';
|
|
||||||
import DashboardCard01 from '../partials/dashboard/DashboardCard01';
|
|
||||||
import DashboardCard02 from '../partials/dashboard/DashboardCard02';
|
|
||||||
import DashboardCard03 from '../partials/dashboard/DashboardCard03';
|
|
||||||
import DashboardCard04 from '../partials/dashboard/DashboardCard04';
|
|
||||||
import DashboardCard05 from '../partials/dashboard/DashboardCard05';
|
|
||||||
import DashboardCard06 from '../partials/dashboard/DashboardCard06';
|
|
||||||
import DashboardCard07 from '../partials/dashboard/DashboardCard07';
|
|
||||||
import DashboardCard08 from '../partials/dashboard/DashboardCard08';
|
|
||||||
import DashboardCard09 from '../partials/dashboard/DashboardCard09';
|
|
||||||
import DashboardCard10 from '../partials/dashboard/DashboardCard10';
|
|
||||||
import DashboardCard11 from '../partials/dashboard/DashboardCard11';
|
|
||||||
|
|
||||||
function Dashboard() {
|
|
||||||
|
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex h-screen overflow-hidden">
|
|
||||||
|
|
||||||
{/* Sidebar */}
|
|
||||||
<Sidebar sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
{/* Content area */}
|
|
||||||
<div className="relative flex flex-col flex-1 overflow-y-auto overflow-x-hidden">
|
|
||||||
|
|
||||||
{/* Site header */}
|
|
||||||
<Header sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div className="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
|
|
||||||
|
|
||||||
{/* Welcome banner */}
|
|
||||||
<WelcomeBanner />
|
|
||||||
|
|
||||||
{/* Dashboard actions */}
|
|
||||||
<div className="sm:flex sm:justify-between sm:items-center mb-8">
|
|
||||||
|
|
||||||
{/* Left: Avatars */}
|
|
||||||
<DashboardAvatars />
|
|
||||||
|
|
||||||
{/* Right: Actions */}
|
|
||||||
<div className="grid grid-flow-col sm:auto-cols-max justify-start sm:justify-end gap-2">
|
|
||||||
{/* Filter button */}
|
|
||||||
<FilterButton align="right" />
|
|
||||||
{/* Datepicker built with flatpickr */}
|
|
||||||
<Datepicker align="right" />
|
|
||||||
{/* Add view button */}
|
|
||||||
<button className="btn bg-indigo-500 hover:bg-indigo-600 text-white">
|
|
||||||
<svg className="w-4 h-4 fill-current opacity-50 shrink-0" viewBox="0 0 16 16">
|
|
||||||
<path d="M15 7H9V1c0-.6-.4-1-1-1S7 .4 7 1v6H1c-.6 0-1 .4-1 1s.4 1 1 1h6v6c0 .6.4 1 1 1s1-.4 1-1V9h6c.6 0 1-.4 1-1s-.4-1-1-1z" />
|
|
||||||
</svg>
|
|
||||||
<span className="hidden xs:block ml-2">Add View</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Cards */}
|
|
||||||
<div className="grid grid-cols-12 gap-6">
|
|
||||||
|
|
||||||
{/* Line chart (Acme Plus) */}
|
|
||||||
<DashboardCard01 />
|
|
||||||
{/* Line chart (Acme Advanced) */}
|
|
||||||
<DashboardCard02 />
|
|
||||||
{/* Line chart (Acme Professional) */}
|
|
||||||
<DashboardCard03 />
|
|
||||||
{/* Bar chart (Direct vs Indirect) */}
|
|
||||||
<DashboardCard04 />
|
|
||||||
{/* Line chart (Real Time Value) */}
|
|
||||||
<DashboardCard05 />
|
|
||||||
{/* Doughnut chart (Top Countries) */}
|
|
||||||
<DashboardCard06 />
|
|
||||||
{/* Table (Top Channels) */}
|
|
||||||
<DashboardCard07 />
|
|
||||||
{/* Line chart (Sales Over Time) */}
|
|
||||||
<DashboardCard08 />
|
|
||||||
{/* Stacked bar chart (Sales VS Refunds) */}
|
|
||||||
<DashboardCard09 />
|
|
||||||
{/* Card (Recent Activity) */}
|
|
||||||
<DashboardCard10 />
|
|
||||||
{/* Card (Income/Expenses) */}
|
|
||||||
<DashboardCard11 />
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Dashboard;
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
|
|
||||||
import Sidebar from '../partials/Sidebar';
|
|
||||||
import Header from '../partials/Header';
|
|
||||||
import Datepicker from '../components/Datepicker';
|
|
||||||
import FintechIntro from '../partials/fintech/FintechIntro';
|
|
||||||
import FintechCard01 from '../partials/fintech/FintechCard01';
|
|
||||||
import FintechCard02 from '../partials/fintech/FintechCard02';
|
|
||||||
import FintechCard03 from '../partials/fintech/FintechCard03';
|
|
||||||
import FintechCard04 from '../partials/fintech/FintechCard04';
|
|
||||||
import FintechCard05 from '../partials/fintech/FintechCard05';
|
|
||||||
import FintechCard06 from '../partials/fintech/FintechCard06';
|
|
||||||
import FintechCard07 from '../partials/fintech/FintechCard07';
|
|
||||||
import FintechCard08 from '../partials/fintech/FintechCard08';
|
|
||||||
import FintechCard09 from '../partials/fintech/FintechCard09';
|
|
||||||
import FintechCard10 from '../partials/fintech/FintechCard10';
|
|
||||||
import FintechCard11 from '../partials/fintech/FintechCard11';
|
|
||||||
import FintechCard12 from '../partials/fintech/FintechCard12';
|
|
||||||
import FintechCard13 from '../partials/fintech/FintechCard13';
|
|
||||||
import FintechCard14 from '../partials/fintech/FintechCard14';
|
|
||||||
|
|
||||||
function Fintech() {
|
|
||||||
|
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='flex h-screen overflow-hidden'>
|
|
||||||
{/* Sidebar */}
|
|
||||||
<Sidebar sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
{/* Content area */}
|
|
||||||
<div className='relative flex flex-col flex-1 overflow-y-auto overflow-x-hidden'>
|
|
||||||
{/* Site header */}
|
|
||||||
<Header sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div className='px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto'>
|
|
||||||
|
|
||||||
{/* Page header */}
|
|
||||||
<div className='sm:flex sm:justify-between sm:items-center mb-5'>
|
|
||||||
|
|
||||||
{/* Left: Title */}
|
|
||||||
<div className='mb-4 sm:mb-0'>
|
|
||||||
<h1 className='text-2xl md:text-3xl text-slate-800 font-bold'>Fintech ✨</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Right: Actions */}
|
|
||||||
<div className='grid grid-flow-col sm:auto-cols-max justify-start sm:justify-end gap-2'>
|
|
||||||
|
|
||||||
{/* Datepicker built with flatpickr */}
|
|
||||||
<Datepicker align='right' />
|
|
||||||
|
|
||||||
{/* Add account button */}
|
|
||||||
<button className='btn bg-indigo-500 hover:bg-indigo-600 text-white'>
|
|
||||||
<svg className='w-4 h-4 fill-current opacity-50 shrink-0' viewBox='0 0 16 16'>
|
|
||||||
<path d='M15 7H9V1c0-.6-.4-1-1-1S7 .4 7 1v6H1c-.6 0-1 .4-1 1s.4 1 1 1h6v6c0 .6.4 1 1 1s1-.4 1-1V9h6c.6 0 1-.4 1-1s-.4-1-1-1z' />
|
|
||||||
</svg>
|
|
||||||
<span className='hidden xs:block ml-2'>Add Account</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Cards */}
|
|
||||||
<div className='grid grid-cols-12 gap-6'>
|
|
||||||
|
|
||||||
{/* Page Intro */}
|
|
||||||
<FintechIntro />
|
|
||||||
{/* Line chart (Portfolio Returns) */}
|
|
||||||
<FintechCard01 />
|
|
||||||
{/* Credit Card */}
|
|
||||||
<FintechCard02 />
|
|
||||||
{/* Bar chart (Cash Flow) */}
|
|
||||||
<FintechCard03 />
|
|
||||||
{/* Horizontal bar chart (Cash Flow by Account) */}
|
|
||||||
<FintechCard04 />
|
|
||||||
{/* Table (Recent Expenses) */}
|
|
||||||
<FintechCard05 />
|
|
||||||
{/* Table (Recent Earnings) */}
|
|
||||||
<FintechCard06 />
|
|
||||||
{/* Line chart (Saving Goals) */}
|
|
||||||
<FintechCard07 />
|
|
||||||
{/* Line chart (Growth Portfolio) */}
|
|
||||||
<FintechCard08 />
|
|
||||||
{/* Pie chart (Portfolio Value) */}
|
|
||||||
<FintechCard09 />
|
|
||||||
{/* Line charts (Stock graphs) */}
|
|
||||||
<FintechCard10 />
|
|
||||||
<FintechCard11 />
|
|
||||||
<FintechCard12 />
|
|
||||||
<FintechCard13 />
|
|
||||||
{/* Table (Market Trends) */}
|
|
||||||
<FintechCard14 />
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Fintech;
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
|
|
||||||
import Sidebar from '../partials/Sidebar';
|
|
||||||
import Header from '../partials/Header';
|
|
||||||
import InboxSidebar from '../partials/inbox/InboxSidebar';
|
|
||||||
import InboxBody from '../partials/inbox/InboxBody';
|
|
||||||
|
|
||||||
function Inbox() {
|
|
||||||
|
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
||||||
const [inboxSidebarOpen, setInboxSidebarOpen] = useState(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex h-screen overflow-hidden">
|
|
||||||
|
|
||||||
{/* Sidebar */}
|
|
||||||
<Sidebar sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
{/* Content area */}
|
|
||||||
<div className="relative flex flex-col flex-1 overflow-y-auto overflow-x-hidden">
|
|
||||||
|
|
||||||
{/* Site header */}
|
|
||||||
<Header sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div className="relative flex">
|
|
||||||
|
|
||||||
{/* Inbox sidebar */}
|
|
||||||
<InboxSidebar inboxSidebarOpen={inboxSidebarOpen} setInboxSidebarOpen={setInboxSidebarOpen} />
|
|
||||||
|
|
||||||
{/* Inbox body */}
|
|
||||||
<InboxBody inboxSidebarOpen={inboxSidebarOpen} setInboxSidebarOpen={setInboxSidebarOpen} />
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Inbox;
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
import React, { useState, useEffect, useRef } from 'react';
|
|
||||||
|
|
||||||
import Sidebar from '../partials/Sidebar';
|
|
||||||
import Header from '../partials/Header';
|
|
||||||
import MessagesSidebar from '../partials/messages/MessagesSidebar';
|
|
||||||
import MessagesHeader from '../partials/messages/MessagesHeader';
|
|
||||||
import MessagesBody from '../partials/messages/MessagesBody';
|
|
||||||
import MessagesFooter from '../partials/messages/MessagesFooter';
|
|
||||||
|
|
||||||
function Messages() {
|
|
||||||
|
|
||||||
const contentArea = useRef(null)
|
|
||||||
|
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
||||||
const [msgSidebarOpen, setMsgSidebarOpen] = useState(true);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
contentArea.current.scrollTop = 99999999
|
|
||||||
}, [msgSidebarOpen]); // automatically scroll the chat and make the most recent message visible
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex h-screen overflow-hidden">
|
|
||||||
|
|
||||||
{/* Sidebar */}
|
|
||||||
<Sidebar sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
{/* Content area */}
|
|
||||||
<div className="relative flex flex-col flex-1 overflow-y-auto overflow-x-hidden" ref={contentArea}>
|
|
||||||
|
|
||||||
{/* Site header */}
|
|
||||||
<Header sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div className="relative flex">
|
|
||||||
|
|
||||||
{/* Messages sidebar */}
|
|
||||||
<MessagesSidebar msgSidebarOpen={msgSidebarOpen} setMsgSidebarOpen={setMsgSidebarOpen} />
|
|
||||||
|
|
||||||
{/* Messages body */}
|
|
||||||
<div className={`grow flex flex-col md:translate-x-0 transform transition-transform duration-300 ease-in-out ${msgSidebarOpen ? 'translate-x-1/3' : 'translate-x-0'}`}>
|
|
||||||
<MessagesHeader msgSidebarOpen={msgSidebarOpen} setMsgSidebarOpen={setMsgSidebarOpen} />
|
|
||||||
<MessagesBody />
|
|
||||||
<MessagesFooter />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Messages;
|
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
import OnboardingImage from '../images/onboarding-image.jpg';
|
|
||||||
import OnboardingDecoration from '../images/auth-decoration.png';
|
|
||||||
|
|
||||||
function Onboarding01() {
|
|
||||||
return (
|
|
||||||
<main className="bg-white">
|
|
||||||
|
|
||||||
<div className="relative flex">
|
|
||||||
|
|
||||||
{/* Content */}
|
|
||||||
<div className="w-full md:w-1/2">
|
|
||||||
|
|
||||||
<div className="min-h-screen h-full flex flex-col after:flex-1">
|
|
||||||
|
|
||||||
<div className="flex-1">
|
|
||||||
|
|
||||||
{/* Header */}
|
|
||||||
<div className="flex items-center justify-between h-16 px-4 sm:px-6 lg:px-8">
|
|
||||||
{/* Logo */}
|
|
||||||
<Link className="block" to="/">
|
|
||||||
<svg width="32" height="32" viewBox="0 0 32 32">
|
|
||||||
<defs>
|
|
||||||
<linearGradient x1="28.538%" y1="20.229%" x2="100%" y2="108.156%" id="logo-a">
|
|
||||||
<stop stopColor="#A5B4FC" stopOpacity="0" offset="0%" />
|
|
||||||
<stop stopColor="#A5B4FC" offset="100%" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient x1="88.638%" y1="29.267%" x2="22.42%" y2="100%" id="logo-b">
|
|
||||||
<stop stopColor="#38BDF8" stopOpacity="0" offset="0%" />
|
|
||||||
<stop stopColor="#38BDF8" offset="100%" />
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
<rect fill="#6366F1" width="32" height="32" rx="16" />
|
|
||||||
<path d="M18.277.16C26.035 1.267 32 7.938 32 16c0 8.837-7.163 16-16 16a15.937 15.937 0 01-10.426-3.863L18.277.161z" fill="#4F46E5" />
|
|
||||||
<path d="M7.404 2.503l18.339 26.19A15.93 15.93 0 0116 32C7.163 32 0 24.837 0 16 0 10.327 2.952 5.344 7.404 2.503z" fill="url(#logo-a)" />
|
|
||||||
<path d="M2.223 24.14L29.777 7.86A15.926 15.926 0 0132 16c0 8.837-7.163 16-16 16-5.864 0-10.991-3.154-13.777-7.86z" fill="url(#logo-b)" />
|
|
||||||
</svg>
|
|
||||||
</Link>
|
|
||||||
<div className="text-sm">
|
|
||||||
Have an account? <Link className="font-medium text-indigo-500 hover:text-indigo-600" to="/signin">Sign In</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Progress bar */}
|
|
||||||
<div className="px-4 pt-12 pb-8">
|
|
||||||
<div className="max-w-md mx-auto w-full">
|
|
||||||
<div className="relative">
|
|
||||||
<div className="absolute left-0 top-1/2 -mt-px w-full h-0.5 bg-slate-200" aria-hidden="true"></div>
|
|
||||||
<ul className="relative flex justify-between w-full">
|
|
||||||
<li>
|
|
||||||
<Link className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-indigo-500 text-white" to="/onboarding-01">1</Link>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Link className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-slate-100 text-slate-500" to="/onboarding-02">2</Link>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Link className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-slate-100 text-slate-500" to="/onboarding-03">3</Link>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Link className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-slate-100 text-slate-500" to="/onboarding-04">4</Link>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="px-4 py-8">
|
|
||||||
<div className="max-w-md mx-auto">
|
|
||||||
|
|
||||||
<h1 className="text-3xl text-slate-800 font-bold mb-6">Tell us what’s your situation ✨</h1>
|
|
||||||
{/* Form */}
|
|
||||||
<form>
|
|
||||||
<div className="space-y-3 mb-8">
|
|
||||||
<label className="relative block cursor-pointer">
|
|
||||||
<input type="radio" name="radio-buttons" className="peer sr-only" defaultChecked />
|
|
||||||
<div className="flex items-center bg-white text-sm font-medium text-slate-800 p-4 rounded border border-slate-200 hover:border-slate-300 shadow-sm duration-150 ease-in-out">
|
|
||||||
<svg className="w-6 h-6 shrink-0 fill-current mr-4" viewBox="0 0 24 24">
|
|
||||||
<path className="text-indigo-500" d="m12 10.856 9-5-8.514-4.73a1 1 0 0 0-.972 0L3 5.856l9 5Z" />
|
|
||||||
<path className="text-indigo-300" d="m11 12.588-9-5V18a1 1 0 0 0 .514.874L11 23.588v-11Z" />
|
|
||||||
<path className="text-indigo-200" d="M13 12.588v11l8.486-4.714A1 1 0 0 0 22 18V7.589l-9 4.999Z" />
|
|
||||||
</svg>
|
|
||||||
<span>I have a company</span>
|
|
||||||
</div>
|
|
||||||
<div className="absolute inset-0 border-2 border-transparent peer-checked:border-indigo-400 rounded pointer-events-none" aria-hidden="true"></div>
|
|
||||||
</label>
|
|
||||||
<label className="relative block cursor-pointer">
|
|
||||||
<input type="radio" name="radio-buttons" className="peer sr-only" />
|
|
||||||
<div className="flex items-center bg-white text-sm font-medium text-slate-800 p-4 rounded border border-slate-200 hover:border-slate-300 shadow-sm duration-150 ease-in-out">
|
|
||||||
<svg className="w-6 h-6 shrink-0 fill-current mr-4" viewBox="0 0 24 24">
|
|
||||||
<path className="text-indigo-500" d="m12 10.856 9-5-8.514-4.73a1 1 0 0 0-.972 0L3 5.856l9 5Z" />
|
|
||||||
<path className="text-indigo-300" d="m11 12.588-9-5V18a1 1 0 0 0 .514.874L11 23.588v-11Z" />
|
|
||||||
</svg>
|
|
||||||
<span>I’m a freelance / contractor</span>
|
|
||||||
</div>
|
|
||||||
<div className="absolute inset-0 border-2 border-transparent peer-checked:border-indigo-400 rounded pointer-events-none" aria-hidden="true"></div>
|
|
||||||
</label>
|
|
||||||
<label className="relative block cursor-pointer">
|
|
||||||
<input type="radio" name="radio-buttons" className="peer sr-only" />
|
|
||||||
<div className="flex items-center bg-white text-sm font-medium text-slate-800 p-4 rounded border border-slate-200 hover:border-slate-300 shadow-sm duration-150 ease-in-out">
|
|
||||||
<svg className="w-6 h-6 shrink-0 fill-current mr-4" viewBox="0 0 24 24">
|
|
||||||
<path className="text-indigo-500" d="m12 10.856 9-5-8.514-4.73a1 1 0 0 0-.972 0L3 5.856l9 5Z" />
|
|
||||||
</svg>
|
|
||||||
<span>I’m just getting started</span>
|
|
||||||
</div>
|
|
||||||
<div className="absolute inset-0 border-2 border-transparent peer-checked:border-indigo-400 rounded pointer-events-none" aria-hidden="true"></div>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<Link className="btn bg-indigo-500 hover:bg-indigo-600 text-white ml-auto" to="/onboarding-02">Next Step -></Link>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Image */}
|
|
||||||
<div className="hidden md:block absolute top-0 bottom-0 right-0 md:w-1/2" aria-hidden="true">
|
|
||||||
<img className="object-cover object-center w-full h-full" src={OnboardingImage} width="760" height="1024" alt="Onboarding" />
|
|
||||||
<img className="absolute top-1/4 left-0 transform -translate-x-1/2 ml-8 hidden lg:block" src={OnboardingDecoration} width="218" height="224" alt="Authentication decoration" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</main>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Onboarding01;
|
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
import OnboardingImage from '../images/onboarding-image.jpg';
|
|
||||||
import OnboardingDecoration from '../images/auth-decoration.png';
|
|
||||||
|
|
||||||
function Onboarding03() {
|
|
||||||
return (
|
|
||||||
<main className="bg-white">
|
|
||||||
|
|
||||||
<div className="relative flex">
|
|
||||||
|
|
||||||
{/* Content */}
|
|
||||||
<div className="w-full md:w-1/2">
|
|
||||||
|
|
||||||
<div className="min-h-screen h-full flex flex-col after:flex-1">
|
|
||||||
|
|
||||||
<div className="flex-1">
|
|
||||||
|
|
||||||
{/* Header */}
|
|
||||||
<div className="flex items-center justify-between h-16 px-4 sm:px-6 lg:px-8">
|
|
||||||
{/* Logo */}
|
|
||||||
<Link className="block" to="/">
|
|
||||||
<svg width="32" height="32" viewBox="0 0 32 32">
|
|
||||||
<defs>
|
|
||||||
<linearGradient x1="28.538%" y1="20.229%" x2="100%" y2="108.156%" id="logo-a">
|
|
||||||
<stop stopColor="#A5B4FC" stopOpacity="0" offset="0%" />
|
|
||||||
<stop stopColor="#A5B4FC" offset="100%" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient x1="88.638%" y1="29.267%" x2="22.42%" y2="100%" id="logo-b">
|
|
||||||
<stop stopColor="#38BDF8" stopOpacity="0" offset="0%" />
|
|
||||||
<stop stopColor="#38BDF8" offset="100%" />
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
<rect fill="#6366F1" width="32" height="32" rx="16" />
|
|
||||||
<path d="M18.277.16C26.035 1.267 32 7.938 32 16c0 8.837-7.163 16-16 16a15.937 15.937 0 01-10.426-3.863L18.277.161z" fill="#4F46E5" />
|
|
||||||
<path d="M7.404 2.503l18.339 26.19A15.93 15.93 0 0116 32C7.163 32 0 24.837 0 16 0 10.327 2.952 5.344 7.404 2.503z" fill="url(#logo-a)" />
|
|
||||||
<path d="M2.223 24.14L29.777 7.86A15.926 15.926 0 0132 16c0 8.837-7.163 16-16 16-5.864 0-10.991-3.154-13.777-7.86z" fill="url(#logo-b)" />
|
|
||||||
</svg>
|
|
||||||
</Link>
|
|
||||||
<div className="text-sm">
|
|
||||||
Have an account? <Link className="font-medium text-indigo-500 hover:text-indigo-600" to="/signin">Sign In</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Progress bar */}
|
|
||||||
<div className="px-4 pt-12 pb-8">
|
|
||||||
<div className="max-w-md mx-auto w-full">
|
|
||||||
<div className="relative">
|
|
||||||
<div className="absolute left-0 top-1/2 -mt-px w-full h-0.5 bg-slate-200" aria-hidden="true"></div>
|
|
||||||
<ul className="relative flex justify-between w-full">
|
|
||||||
<li>
|
|
||||||
<Link className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-indigo-500 text-white" to="/onboarding-01">1</Link>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Link className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-indigo-500 text-white" to="/onboarding-02">2</Link>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Link className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-indigo-500 text-white" to="/onboarding-03">3</Link>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Link className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-slate-100 text-slate-500" to="/onboarding-04">4</Link>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="px-4 py-8">
|
|
||||||
<div className="max-w-md mx-auto">
|
|
||||||
|
|
||||||
<h1 className="text-3xl text-slate-800 font-bold mb-6">Company information ✨</h1>
|
|
||||||
{/* htmlForm */}
|
|
||||||
<form>
|
|
||||||
<div className="space-y-4 mb-8">
|
|
||||||
{/* Company Name */}
|
|
||||||
<div>
|
|
||||||
<label className="block text-sm font-medium mb-1" htmlFor="company-name">Company Name <span className="text-rose-500">*</span></label>
|
|
||||||
<input id="company-name" className="form-input w-full" type="text" />
|
|
||||||
</div>
|
|
||||||
{/* City and Postal Code */}
|
|
||||||
<div className="flex space-x-4">
|
|
||||||
<div className="flex-1">
|
|
||||||
<label className="block text-sm font-medium mb-1" htmlFor="city">City <span className="text-rose-500">*</span></label>
|
|
||||||
<input id="city" className="form-input w-full" type="text" />
|
|
||||||
</div>
|
|
||||||
<div className="flex-1">
|
|
||||||
<label className="block text-sm font-medium mb-1" htmlFor="postal-code">Postal Code <span className="text-rose-500">*</span></label>
|
|
||||||
<input id="postal-code" className="form-input w-full" type="text" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/* Street Address */}
|
|
||||||
<div>
|
|
||||||
<label className="block text-sm font-medium mb-1" htmlFor="street">Street Address <span className="text-rose-500">*</span></label>
|
|
||||||
<input id="street" className="form-input w-full" type="text" />
|
|
||||||
</div>
|
|
||||||
{/* Country */}
|
|
||||||
<div>
|
|
||||||
<label className="block text-sm font-medium mb-1" htmlFor="country">Country <span className="text-rose-500">*</span></label>
|
|
||||||
<select id="country" className="form-select w-full">
|
|
||||||
<option>USA</option>
|
|
||||||
<option>Italy</option>
|
|
||||||
<option>United Kingdom</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<Link className="text-sm underline hover:no-underline" to="/onboarding-02"><- Back</Link>
|
|
||||||
<Link className="btn bg-indigo-500 hover:bg-indigo-600 text-white ml-auto" to="/onboarding-04">Next Step -></Link>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Image */}
|
|
||||||
<div className="hidden md:block absolute top-0 bottom-0 right-0 md:w-1/2" aria-hidden="true">
|
|
||||||
<img className="object-cover object-center w-full h-full" src={OnboardingImage} width="760" height="1024" alt="Onboarding" />
|
|
||||||
<img className="absolute top-1/4 left-0 transform -translate-x-1/2 ml-8 hidden lg:block" src={OnboardingDecoration} width="218" height="224" alt="Authentication decoration" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</main>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Onboarding03;
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
import OnboardingImage from '../images/onboarding-image.jpg';
|
|
||||||
import OnboardingDecoration from '../images/auth-decoration.png';
|
|
||||||
|
|
||||||
function Onboarding04() {
|
|
||||||
return (
|
|
||||||
<main className="bg-white">
|
|
||||||
|
|
||||||
<div className="relative flex">
|
|
||||||
|
|
||||||
{/* Content */}
|
|
||||||
<div className="w-full md:w-1/2">
|
|
||||||
|
|
||||||
<div className="min-h-screen h-full flex flex-col after:flex-1">
|
|
||||||
|
|
||||||
<div className="flex-1">
|
|
||||||
|
|
||||||
{/* Header */}
|
|
||||||
<div className="flex items-center justify-between h-16 px-4 sm:px-6 lg:px-8">
|
|
||||||
{/* Logo */}
|
|
||||||
<Link className="block" to="/">
|
|
||||||
<svg width="32" height="32" viewBox="0 0 32 32">
|
|
||||||
<defs>
|
|
||||||
<linearGradient x1="28.538%" y1="20.229%" x2="100%" y2="108.156%" id="logo-a">
|
|
||||||
<stop stopColor="#A5B4FC" stopOpacity="0" offset="0%" />
|
|
||||||
<stop stopColor="#A5B4FC" offset="100%" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient x1="88.638%" y1="29.267%" x2="22.42%" y2="100%" id="logo-b">
|
|
||||||
<stop stopColor="#38BDF8" stopOpacity="0" offset="0%" />
|
|
||||||
<stop stopColor="#38BDF8" offset="100%" />
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
<rect fill="#6366F1" width="32" height="32" rx="16" />
|
|
||||||
<path d="M18.277.16C26.035 1.267 32 7.938 32 16c0 8.837-7.163 16-16 16a15.937 15.937 0 01-10.426-3.863L18.277.161z" fill="#4F46E5" />
|
|
||||||
<path d="M7.404 2.503l18.339 26.19A15.93 15.93 0 0116 32C7.163 32 0 24.837 0 16 0 10.327 2.952 5.344 7.404 2.503z" fill="url(#logo-a)" />
|
|
||||||
<path d="M2.223 24.14L29.777 7.86A15.926 15.926 0 0132 16c0 8.837-7.163 16-16 16-5.864 0-10.991-3.154-13.777-7.86z" fill="url(#logo-b)" />
|
|
||||||
</svg>
|
|
||||||
</Link>
|
|
||||||
<div className="text-sm">
|
|
||||||
Have an account? <Link className="font-medium text-indigo-500 hover:text-indigo-600" to="/signin">Sign In</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Progress bar */}
|
|
||||||
<div className="px-4 pt-12 pb-8">
|
|
||||||
<div className="max-w-md mx-auto w-full">
|
|
||||||
<div className="relative">
|
|
||||||
<div className="absolute left-0 top-1/2 -mt-px w-full h-0.5 bg-slate-200" aria-hidden="true"></div>
|
|
||||||
<ul className="relative flex justify-between w-full">
|
|
||||||
<li>
|
|
||||||
<Link className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-indigo-500 text-white" to="/onboarding-01">1</Link>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Link className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-indigo-500 text-white" to="/onboarding-02">2</Link>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Link className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-indigo-500 text-white" to="/onboarding-03">3</Link>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<Link className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-indigo-500 text-white" to="/onboarding-04">4</Link>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="px-4 py-8">
|
|
||||||
<div className="max-w-md mx-auto">
|
|
||||||
|
|
||||||
<div className="text-center">
|
|
||||||
<svg className="inline-flex w-16 h-16 fill-current mb-6" viewBox="0 0 64 64">
|
|
||||||
<circle className="text-emerald-100" cx="32" cy="32" r="32" />
|
|
||||||
<path className="text-emerald-500" d="m28.5 41-8-8 3-3 5 5 12-12 3 3z" />
|
|
||||||
</svg>
|
|
||||||
<h1 className="text-3xl text-slate-800 font-bold mb-8">Nice to have you, Acme Inc. 🙌</h1>
|
|
||||||
<Link className="btn bg-indigo-500 hover:bg-indigo-600 text-white" to="/">Go To Dashboard -></Link>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Image */}
|
|
||||||
<div className="hidden md:block absolute top-0 bottom-0 right-0 md:w-1/2" aria-hidden="true">
|
|
||||||
<img className="object-cover object-center w-full h-full" src={OnboardingImage} width="760" height="1024" alt="Onboarding" />
|
|
||||||
<img className="absolute top-1/4 left-0 transform -translate-x-1/2 ml-8 hidden lg:block" src={OnboardingDecoration} width="218" height="224" alt="Authentication decoration" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</main>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Onboarding04;
|
|
||||||
@@ -1,10 +1,21 @@
|
|||||||
import React from 'react';
|
import React, {useEffect} from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import OnboardingImage from '../images/onboarding-image.jpg';
|
import OnboardingImage from '../images/onboarding-image.jpg';
|
||||||
import OnboardingDecoration from '../images/auth-decoration.png';
|
import OnboardingDecoration from '../images/auth-decoration.png';
|
||||||
|
import Logo from "../images/logo.png";
|
||||||
|
import { observer } from "mobx-react-lite";
|
||||||
|
import { store } from "../store/store";
|
||||||
|
import { Navigate } from "react-router-dom";
|
||||||
|
|
||||||
|
const Onboarding1 = observer(() => {
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
store.clearDataRegistration()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
if(store.passPhrase)
|
||||||
|
return <Navigate to="/digitalId/profile-id" replace={true} />
|
||||||
|
|
||||||
function Onboarding02() {
|
|
||||||
return (
|
return (
|
||||||
<main className="bg-white">
|
<main className="bg-white">
|
||||||
|
|
||||||
@@ -20,46 +31,31 @@ function Onboarding02() {
|
|||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex items-center justify-between h-16 px-4 sm:px-6 lg:px-8">
|
<div className="flex items-center justify-between h-16 px-4 sm:px-6 lg:px-8">
|
||||||
{/* Logo */}
|
{/* Logo */}
|
||||||
<Link className="block" to="/">
|
<Link className="block" to="/dashboard">
|
||||||
<svg width="32" height="32" viewBox="0 0 32 32">
|
<img alt='logo' src={Logo} width="89" height="32"/>
|
||||||
<defs>
|
|
||||||
<linearGradient x1="28.538%" y1="20.229%" x2="100%" y2="108.156%" id="logo-a">
|
|
||||||
<stop stopColor="#A5B4FC" stopOpacity="0" offset="0%" />
|
|
||||||
<stop stopColor="#A5B4FC" offset="100%" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient x1="88.638%" y1="29.267%" x2="22.42%" y2="100%" id="logo-b">
|
|
||||||
<stop stopColor="#38BDF8" stopOpacity="0" offset="0%" />
|
|
||||||
<stop stopColor="#38BDF8" offset="100%" />
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
<rect fill="#6366F1" width="32" height="32" rx="16" />
|
|
||||||
<path d="M18.277.16C26.035 1.267 32 7.938 32 16c0 8.837-7.163 16-16 16a15.937 15.937 0 01-10.426-3.863L18.277.161z" fill="#4F46E5" />
|
|
||||||
<path d="M7.404 2.503l18.339 26.19A15.93 15.93 0 0116 32C7.163 32 0 24.837 0 16 0 10.327 2.952 5.344 7.404 2.503z" fill="url(#logo-a)" />
|
|
||||||
<path d="M2.223 24.14L29.777 7.86A15.926 15.926 0 0132 16c0 8.837-7.163 16-16 16-5.864 0-10.991-3.154-13.777-7.86z" fill="url(#logo-b)" />
|
|
||||||
</svg>
|
|
||||||
</Link>
|
</Link>
|
||||||
<div className="text-sm">
|
<div className="text-sm">
|
||||||
Have an account? <Link className="font-medium text-indigo-500 hover:text-indigo-600" to="/signin">Sign In</Link>
|
Have an account? <Link className="font-medium text-indigo-500 hover:text-indigo-600" to="/signIn">Sign In</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Progress bar */}
|
{/* Progress bar */}
|
||||||
<div className="px-4 pt-12 pb-8">
|
<div className="px-4 pt-12 pb-[142px]">
|
||||||
<div className="max-w-md mx-auto w-full">
|
<div className="max-w-md mx-auto w-full">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<div className="absolute left-0 top-1/2 -mt-px w-full h-0.5 bg-slate-200" aria-hidden="true"></div>
|
<div className="absolute left-0 top-1/2 -mt-px w-full h-0.5 bg-slate-200" aria-hidden="true"></div>
|
||||||
<ul className="relative flex justify-between w-full">
|
<ul className="relative flex justify-between w-full">
|
||||||
<li>
|
<li>
|
||||||
<Link className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-indigo-500 text-white" to="/onboarding-01">1</Link>
|
<span className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-indigo-500 text-white" to="/">1</span>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Link className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-indigo-500 text-white" to="/onboarding-02">2</Link>
|
<span className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-slate-100 text-slate-500" to="/onboarding-2">2</span>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Link className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-slate-100 text-slate-500" to="/onboarding-03">3</Link>
|
<span className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-slate-100 text-slate-500" to="/onboarding-3">3</span>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Link className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-slate-100 text-slate-500" to="/onboarding-04">4</Link>
|
<span className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-slate-100 text-slate-500" to="/onboarding-4">4</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -70,9 +66,9 @@ function Onboarding02() {
|
|||||||
<div className="px-4 py-8">
|
<div className="px-4 py-8">
|
||||||
<div className="max-w-md mx-auto">
|
<div className="max-w-md mx-auto">
|
||||||
|
|
||||||
<h1 className="text-3xl text-slate-800 font-bold mb-6">Tell us about your company ✨</h1>
|
<h1 className="text-3xl text-slate-800 font-bold mb-12">Tell us about your company ✨</h1>
|
||||||
{/* Form */}
|
{/* Form */}
|
||||||
<form>
|
<div>
|
||||||
<div className="sm:flex space-y-3 sm:space-y-0 sm:space-x-4 mb-8">
|
<div className="sm:flex space-y-3 sm:space-y-0 sm:space-x-4 mb-8">
|
||||||
<label className="flex-1 relative block cursor-pointer">
|
<label className="flex-1 relative block cursor-pointer">
|
||||||
<input type="radio" name="radio-buttons" className="peer sr-only" defaultChecked />
|
<input type="radio" name="radio-buttons" className="peer sr-only" defaultChecked />
|
||||||
@@ -81,7 +77,7 @@ function Onboarding02() {
|
|||||||
<circle className="text-indigo-100" cx="20" cy="20" r="20" />
|
<circle className="text-indigo-100" cx="20" cy="20" r="20" />
|
||||||
<path className="text-indigo-500" d="m26.371 23.749-3.742-1.5a1 1 0 0 1-.629-.926v-.878A3.982 3.982 0 0 0 24 17v-1.828A4.087 4.087 0 0 0 20 11a4.087 4.087 0 0 0-4 4.172V17a3.982 3.982 0 0 0 2 3.445v.878a1 1 0 0 1-.629.928l-3.742 1.5a1 1 0 0 0-.629.926V27a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.323a1 1 0 0 0-.629-.928Z" />
|
<path className="text-indigo-500" d="m26.371 23.749-3.742-1.5a1 1 0 0 1-.629-.926v-.878A3.982 3.982 0 0 0 24 17v-1.828A4.087 4.087 0 0 0 20 11a4.087 4.087 0 0 0-4 4.172V17a3.982 3.982 0 0 0 2 3.445v.878a1 1 0 0 1-.629.928l-3.742 1.5a1 1 0 0 0-.629.926V27a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.323a1 1 0 0 0-.629-.928Z" />
|
||||||
</svg>
|
</svg>
|
||||||
<div className="font-medium text-slate-800 mb-1">Individual</div>
|
<div className="font-semibold text-slate-800 mb-1">Individual</div>
|
||||||
<div className="text-sm">Lorem ipsum is place text commonly used.</div>
|
<div className="text-sm">Lorem ipsum is place text commonly used.</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="absolute inset-0 border-2 border-transparent peer-checked:border-indigo-400 rounded pointer-events-none" aria-hidden="true"></div>
|
<div className="absolute inset-0 border-2 border-transparent peer-checked:border-indigo-400 rounded pointer-events-none" aria-hidden="true"></div>
|
||||||
@@ -96,7 +92,7 @@ function Onboarding02() {
|
|||||||
<path className="text-indigo-300" d="m30.377 22.749-3.709-1.5a1 1 0 0 1-.623-.926v-.878A3.989 3.989 0 0 0 28.027 16v-1.828c.047-2.257-1.728-4.124-3.964-4.172-2.236.048-4.011 1.915-3.964 4.172V16a3.989 3.989 0 0 0 1.982 3.445v.878a1 1 0 0 1-.623.928c-.906.266-1.626.557-2.159.872-.533.315-1.3 1.272-2.299 2.872 1.131.453 6.075-.546 6.072.682V28a2.99 2.99 0 0 1-.182 1h7.119A.996.996 0 0 0 31 28v-4.323a1 1 0 0 0-.623-.928Z" />
|
<path className="text-indigo-300" d="m30.377 22.749-3.709-1.5a1 1 0 0 1-.623-.926v-.878A3.989 3.989 0 0 0 28.027 16v-1.828c.047-2.257-1.728-4.124-3.964-4.172-2.236.048-4.011 1.915-3.964 4.172V16a3.989 3.989 0 0 0 1.982 3.445v.878a1 1 0 0 1-.623.928c-.906.266-1.626.557-2.159.872-.533.315-1.3 1.272-2.299 2.872 1.131.453 6.075-.546 6.072.682V28a2.99 2.99 0 0 1-.182 1h7.119A.996.996 0 0 0 31 28v-4.323a1 1 0 0 0-.623-.928Z" />
|
||||||
<path className="text-indigo-500" d="m22.371 24.749-3.742-1.5a1 1 0 0 1-.629-.926v-.878A3.982 3.982 0 0 0 20 18v-1.828A4.087 4.087 0 0 0 16 12a4.087 4.087 0 0 0-4 4.172V18a3.982 3.982 0 0 0 2 3.445v.878a1 1 0 0 1-.629.928l-3.742 1.5a1 1 0 0 0-.629.926V28a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.323a1 1 0 0 0-.629-.928Z" />
|
<path className="text-indigo-500" d="m22.371 24.749-3.742-1.5a1 1 0 0 1-.629-.926v-.878A3.982 3.982 0 0 0 20 18v-1.828A4.087 4.087 0 0 0 16 12a4.087 4.087 0 0 0-4 4.172V18a3.982 3.982 0 0 0 2 3.445v.878a1 1 0 0 1-.629.928l-3.742 1.5a1 1 0 0 0-.629.926V28a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.323a1 1 0 0 0-.629-.928Z" />
|
||||||
</svg>
|
</svg>
|
||||||
<div className="font-medium text-slate-800 mb-1">Organization</div>
|
<div className="font-semibold text-slate-800 mb-1">Organization</div>
|
||||||
<div className="text-sm">Lorem ipsum is place text commonly used.</div>
|
<div className="text-sm">Lorem ipsum is place text commonly used.</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="absolute inset-0 border-2 border-transparent peer-checked:border-indigo-400 rounded pointer-events-none" aria-hidden="true"></div>
|
<div className="absolute inset-0 border-2 border-transparent peer-checked:border-indigo-400 rounded pointer-events-none" aria-hidden="true"></div>
|
||||||
@@ -105,7 +101,7 @@ function Onboarding02() {
|
|||||||
<div className="flex items-center justify-between space-x-6 mb-8">
|
<div className="flex items-center justify-between space-x-6 mb-8">
|
||||||
<div>
|
<div>
|
||||||
<div className="font-medium text-slate-800 text-sm mb-1">💸 Lorem ipsum is place text commonly?</div>
|
<div className="font-medium text-slate-800 text-sm mb-1">💸 Lorem ipsum is place text commonly?</div>
|
||||||
<div className="text-xs">Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts.</div>
|
<div className="text-xs font-normal leading-6">Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts.</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className="form-switch">
|
<div className="form-switch">
|
||||||
@@ -118,10 +114,11 @@ function Onboarding02() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<Link className="text-sm underline hover:no-underline" to="/onboarding-01"><- Back</Link>
|
<button className="font-medium btn bg-indigo-500 hover:bg-indigo-600 text-white ml-auto">
|
||||||
<Link className="btn bg-indigo-500 hover:bg-indigo-600 text-white ml-auto" to="/onboarding-03">Next Step -></Link>
|
<Link to="/onboarding-2">Next Step -></Link>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -140,6 +137,6 @@ function Onboarding02() {
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
})
|
||||||
|
|
||||||
export default Onboarding02;
|
export default Onboarding1;
|
||||||
156
src/pages/Onboarding2.jsx
Normal file
156
src/pages/Onboarding2.jsx
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
import React, {useEffect, useMemo, useState} from 'react';
|
||||||
|
import { Link, useNavigate } from 'react-router-dom';
|
||||||
|
import { observer } from "mobx-react-lite";
|
||||||
|
import { store } from "../store/store";
|
||||||
|
import OnboardingImage from '../images/onboarding-image.jpg';
|
||||||
|
import OnboardingDecoration from '../images/auth-decoration.png';
|
||||||
|
import Logo from "../images/logo.png";
|
||||||
|
|
||||||
|
const Onboarding2 = observer(() => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const [dataRegistration, setDataRegistration] = useState(
|
||||||
|
{
|
||||||
|
firstname: '',
|
||||||
|
secondname: '',
|
||||||
|
gender: '',
|
||||||
|
birthdate: '',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const fillingForm = useMemo(() => !Object.keys(dataRegistration).find(item => !dataRegistration[item]), [dataRegistration])
|
||||||
|
|
||||||
|
const saveValueChange = (event) => {
|
||||||
|
const newValue=event.target.value;
|
||||||
|
setDataRegistration({
|
||||||
|
...dataRegistration,
|
||||||
|
[event.target.id]: newValue,
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
const saveStoreRegistration = () => {
|
||||||
|
if (fillingForm) {
|
||||||
|
store.saveDataRegistration(Object.keys(dataRegistration).map(item => ({
|
||||||
|
key: `${item}`,
|
||||||
|
value: dataRegistration[item],
|
||||||
|
})
|
||||||
|
))
|
||||||
|
navigate("/onboarding-3", { replace: true });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if(store.accountData.length === 0)
|
||||||
|
return;
|
||||||
|
setDataRegistration(store.accountData.reduce((acc, item) => ({
|
||||||
|
...acc,
|
||||||
|
[item.key]: item.value
|
||||||
|
}), {}))
|
||||||
|
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main className="bg-white">
|
||||||
|
|
||||||
|
<div className="relative flex">
|
||||||
|
|
||||||
|
{/* Content */}
|
||||||
|
<div className="w-full md:w-1/2">
|
||||||
|
|
||||||
|
<div className="min-h-screen h-full flex flex-col after:flex-1">
|
||||||
|
|
||||||
|
<div className="flex-1">
|
||||||
|
|
||||||
|
{/* Header */}
|
||||||
|
<div className="flex items-center justify-between h-16 px-4 sm:px-6 lg:px-8">
|
||||||
|
{/* Logo */}
|
||||||
|
<Link className="block" to="/dashboard">
|
||||||
|
<img alt='logo' src={Logo} width="89" height="32"/>
|
||||||
|
</Link>
|
||||||
|
<div className="text-sm">
|
||||||
|
Have an account? <Link className="font-medium text-indigo-500 hover:text-indigo-600" to="/signIn">Sign In</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Progress bar */}
|
||||||
|
<div className="px-4 pt-12 pb-[59px]">
|
||||||
|
<div className="max-w-md mx-auto w-full">
|
||||||
|
<div className="relative">
|
||||||
|
<div className="absolute left-0 top-1/2 -mt-px w-full h-0.5 bg-slate-200" aria-hidden="true"></div>
|
||||||
|
<ul className="relative flex justify-between w-full">
|
||||||
|
<li>
|
||||||
|
<span className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-indigo-500 text-white" to="/">1</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-indigo-500 text-white" to="/onboarding-2">2</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-slate-100 text-slate-500" to="/onboarding-3">3</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-slate-100 text-slate-500" to="/onboarding-4">4</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="px-4 py-8">
|
||||||
|
<div className="max-w-[344px] mx-auto">
|
||||||
|
<h1 className="text-3xl text-slate-800 font-bold mb-6">Create your Account ✨</h1>
|
||||||
|
{/* Form */}
|
||||||
|
<div>
|
||||||
|
<div className="space-y-4 mb-8">
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium mb-1" htmlFor="first_name">First name <span className="text-rose-500">*</span></label>
|
||||||
|
<input id="firstname" onChange={(event)=>saveValueChange(event)} className="form-input w-full" type="text" value={dataRegistration.firstname} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium mb-1" htmlFor="second_name">Last name <span className="text-rose-500">*</span></label>
|
||||||
|
<input id="secondname" onChange={(event)=>saveValueChange(event)} className="form-input w-full" type="text" value={dataRegistration.secondname} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium mb-1" htmlFor="gender">Gender <span className="text-rose-500">*</span></label>
|
||||||
|
<select id="gender" onChange={(event)=>saveValueChange(event)} className="form-select w-full" value={dataRegistration.gender}>
|
||||||
|
<option className="hidden"></option>
|
||||||
|
<option>male</option>
|
||||||
|
<option>female</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium mb-1" htmlFor="birthdate">Date of birth <span className="text-rose-500">*</span></label>
|
||||||
|
<input id="birthdate" onChange={(event)=>saveValueChange(event)} className="form-input w-full" type="date" autoComplete="on" value={dataRegistration.birthdate} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center justify-between mt-6">
|
||||||
|
<div className="mr-1">
|
||||||
|
<label className="flex items-center">
|
||||||
|
<input type="checkbox" className="form-checkbox" />
|
||||||
|
<span className="text-sm ml-2">Email me about product news.</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<button onClick={saveStoreRegistration} className="btn bg-indigo-500 hover:bg-indigo-600 text-white ml-3 whitespace-nowrap">Sign Up
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Image */}
|
||||||
|
<div className="hidden md:block absolute top-0 bottom-0 right-0 md:w-1/2" aria-hidden="true">
|
||||||
|
<img className="object-cover object-center w-full h-full" src={OnboardingImage} width="760" height="1024" alt="Onboarding" />
|
||||||
|
<img className="absolute top-1/4 left-0 transform -translate-x-1/2 ml-8 hidden lg:block" src={OnboardingDecoration} width="218" height="224" alt="Authentication decoration" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default Onboarding2;
|
||||||
136
src/pages/Onboarding3.jsx
Normal file
136
src/pages/Onboarding3.jsx
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
import React, {useEffect} from 'react';
|
||||||
|
import {observer} from "mobx-react-lite";
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import {generateSvgAvatar} from "../images/GenerateOnboardingSvg/GenerateSvg";
|
||||||
|
import Logo from "../images/logo.png";
|
||||||
|
import {store} from "../store/store";
|
||||||
|
|
||||||
|
const Onboarding3 = observer(()=>{
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
store.generatePassPhrase();
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const generatePassPhrase = () => {
|
||||||
|
store.generatePassPhrase();
|
||||||
|
};
|
||||||
|
|
||||||
|
const savePassPhraseInStore = copiedPhrase => {
|
||||||
|
if (copiedPhrase.split(' ').length === 12) {
|
||||||
|
store.savePastPassPhrase(copiedPhrase.trim());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const pastePassPhrase = () => {
|
||||||
|
navigator.clipboard.readText().then(res => savePassPhraseInStore(res));
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertPassPhraseToArray = () => store.passPhrase.split(' ').
|
||||||
|
map((item, index) => ({str: item, id: index}));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main className="bg-white">
|
||||||
|
|
||||||
|
<div className="relative flex">
|
||||||
|
|
||||||
|
{/* Content */}
|
||||||
|
<div className="w-full md:w-1/2">
|
||||||
|
|
||||||
|
<div className="min-h-screen h-full flex flex-col after:flex-1">
|
||||||
|
|
||||||
|
<div className="flex-1">
|
||||||
|
|
||||||
|
{/* Header */}
|
||||||
|
<div className="flex items-center justify-between h-16 px-4 sm:px-6 lg:px-8">
|
||||||
|
{/* Logo */}
|
||||||
|
<Link className="block" to="/dashboard">
|
||||||
|
<img alt='logo' src={Logo} width="89" height="32"/>
|
||||||
|
</Link>
|
||||||
|
<div className="text-sm">
|
||||||
|
Have an account? <Link className="font-medium text-indigo-500 hover:text-indigo-600" to="/signIn">Sign In</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Progress bar */}
|
||||||
|
<div className="px-4 pt-12 pb-8">
|
||||||
|
<div className="max-w-md mx-auto w-full">
|
||||||
|
<div className="relative">
|
||||||
|
<div className="absolute left-0 top-1/2 -mt-px w-full h-0.5 bg-slate-200" aria-hidden="true"></div>
|
||||||
|
<ul className="relative flex justify-between w-full">
|
||||||
|
<li>
|
||||||
|
<span className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-indigo-500 text-white" to="/">1</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-indigo-500 text-white" to="/onboarding-2">2</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-indigo-500 text-white" to="/onboarding-3">3</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-slate-100 text-slate-500" to="/onboarding-4">4</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="px-4 mt-20 py-8">
|
||||||
|
<div className="max-w-fit mx-auto flex flex-col gap-y-36">
|
||||||
|
|
||||||
|
<div className="gap-0.5">
|
||||||
|
<h1 className="text-3xl text-slate-800 font-bold mb-12">Company information ✨</h1>
|
||||||
|
{/* htmlForm */}
|
||||||
|
<div className="grid grid-cols-4 gap-y-2.5 gap-[18px] mb-14">
|
||||||
|
{convertPassPhraseToArray().map(tag => (
|
||||||
|
<button key={tag.id} className="min-w-93px w-24 min-h-26px h-26px bg-slate-100 text-slate-500 cursor-pointer hover:bg-blue-100 hover:text-blue-600 rounded-full text-center px-2.5">
|
||||||
|
<span className="text-sm font-medium">{tag.str}</span>
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div className="flex pl-7 gap-x-5">
|
||||||
|
<button onClick={pastePassPhrase} className="btn pl-9 pr-16 border-slate-200 hover:border-slate-300 text-slate-600">
|
||||||
|
<svg className="w-4 h-4 fill-current text-slate-400 shrink-0 mb-0.5" viewBox="0 0 16 16">
|
||||||
|
<path
|
||||||
|
d="M11.7.3c-.4-.4-1-.4-1.4 0l-10 10c-.2.2-.3.4-.3.7v4c0 .6.4 1 1 1h4c.3 0 .5-.1.7-.3l10-10c.4-.4.4-1 0-1.4l-4-4zM4.6 14H2v-2.6l6-6L10.6 8l-6 6zM12 6.6L9.4 4 11 2.4 13.6 5 12 6.6z"></path>
|
||||||
|
</svg>
|
||||||
|
<span className="ml-2">Paste</span>
|
||||||
|
</button>
|
||||||
|
<button onClick={generatePassPhrase} className="btn pr-11 pl-7 border-slate-200 hover:border-slate-300 text-rose-500">
|
||||||
|
<svg className="mb-0.5" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M14.5744 5.66943L13.1504 7.09343C13.4284 7.44043 13.6564 7.75743 13.8194 8.00043C13.0594 9.13043 10.9694 11.8204 8.25836 11.9854L6.44336 13.8004C6.93936 13.9244 7.45736 14.0004 8.00036 14.0004C12.7074 14.0004 15.7444 8.71643 15.8714 8.49243C16.0424 8.18843 16.0434 7.81643 15.8724 7.51243C15.8254 7.42743 15.3724 6.63143 14.5744 5.66943Z" fill="#F43F5E"/>
|
||||||
|
<path fillRule="evenodd" clipRule="evenodd" d="M1.00038 16.0002C0.744375 16.0002 0.488375 15.9022 0.293375 15.7072C-0.0976249 15.3162 -0.0976249 14.6842 0.292375 14.2942L2.82138 11.7653C1.17238 10.2913 0.198375 8.61425 0.128375 8.48925C-0.0416249 8.18625 -0.0426249 7.81725 0.126375 7.51425C0.251375 7.28925 3.24537 2.00025 8.00037 2.00025C9.33138 2.00025 10.5154 2.43125 11.5484 3.03825L14.2934 0.29325C14.6844 -0.09775 15.3164 -0.09775 15.7074 0.29325C16.0984 0.68425 16.0984 1.31625 15.7074 1.70725L1.70738 15.7072C1.51238 15.9022 1.25638 16.0002 1.00038 16.0002ZM8.00037 4.00025C5.14637 4.00025 2.95837 6.83525 2.18138 7.99925C2.55938 8.56225 3.28538 9.51025 4.24038 10.3463L6.07438 8.51225C6.02938 8.34825 6.00037 8.17825 6.00037 8.00025C6.00037 6.89525 6.89537 6.00025 8.00037 6.00025C8.17838 6.00025 8.34838 6.02925 8.51237 6.07425L10.0784 4.50825C9.43738 4.20125 8.74237 4.00025 8.00037 4.00025Z" fill="#F43F5E"/>
|
||||||
|
</svg>
|
||||||
|
<span className="ml-2">Generate</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Link className="text-sm underline hover:no-underline" to="/onboarding-2"><- Back</Link>
|
||||||
|
<button className="btn bg-indigo-500 hover:bg-indigo-600 text-white ml-auto">
|
||||||
|
<Link to="/onboarding-4">Next Step -></Link>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Image */}
|
||||||
|
<div className="flex flex-col items-center h-full w-full hidden md:block absolute top-0 bottom-0 right-0 md:w-1/2" aria-hidden="true">
|
||||||
|
<div className="flex mt-40 flex-col items-center gap-2.5">
|
||||||
|
<img className="object-cover object-center" src={generateSvgAvatar(store.pubKey)} width="493px" height="493px" alt="Onboarding" />
|
||||||
|
<span className="text-sm">Your generated Digital ID</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default Onboarding3;
|
||||||
127
src/pages/Onboarding4.jsx
Normal file
127
src/pages/Onboarding4.jsx
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
import React, {useState} from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import {generateSvgAvatar} from "../images/GenerateOnboardingSvg/GenerateSvg";
|
||||||
|
import Logo from "../images/logo.png";
|
||||||
|
import {observer} from "mobx-react-lite";
|
||||||
|
import { store } from "../store/store";
|
||||||
|
|
||||||
|
const Onboarding4 = observer(() => {
|
||||||
|
|
||||||
|
const [checkBoxesSelected, setCheckBoxesSelected] = useState([]);
|
||||||
|
|
||||||
|
function createAccount() {
|
||||||
|
if(checkBoxesSelected.length === 2) {
|
||||||
|
store.pushAccountData();
|
||||||
|
sessionStorage.setItem('passPhrase', store.passPhrase);
|
||||||
|
store.clearDataRegistration();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function saveCheckBoxesValues(e) {
|
||||||
|
const { id, checked } = e.target;
|
||||||
|
setCheckBoxesSelected([...checkBoxesSelected, id]);
|
||||||
|
if (!checked) {
|
||||||
|
setCheckBoxesSelected(checkBoxesSelected.filter(item => item !== id));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const firstNameAccount = store.accountData.length && store.accountData.find(item => item.key === "firstname").value;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main className="bg-white">
|
||||||
|
|
||||||
|
<div className="relative flex">
|
||||||
|
|
||||||
|
{/* Content */}
|
||||||
|
<div className="w-full md:w-1/2">
|
||||||
|
|
||||||
|
<div className="min-h-screen h-full flex flex-col after:flex-1">
|
||||||
|
|
||||||
|
<div className="flex-1">
|
||||||
|
|
||||||
|
{/* Header */}
|
||||||
|
<div className="flex items-center justify-between h-16 px-4 sm:px-6 lg:px-8">
|
||||||
|
{/* Logo */}
|
||||||
|
<Link className="block" to="/dashboard">
|
||||||
|
<img alt='logo' src={Logo} width="89" height="32"/>
|
||||||
|
</Link>
|
||||||
|
<div className="text-sm">
|
||||||
|
Have an account? <Link className="font-medium text-indigo-500 hover:text-indigo-600" to="/signIn">Sign In</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Progress bar */}
|
||||||
|
<div className="px-4 pt-12 pb-[85px]">
|
||||||
|
<div className="max-w-md mx-auto w-full">
|
||||||
|
<div className="relative">
|
||||||
|
<div className="absolute left-0 top-1/2 -mt-px w-full h-0.5 bg-slate-200" aria-hidden="true"></div>
|
||||||
|
<ul className="relative flex justify-between w-full">
|
||||||
|
<li>
|
||||||
|
<span className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-indigo-500 text-white" to="/">1</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-indigo-500 text-white" to="/onboarding-2">2</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-indigo-500 text-white" to="/onboarding-3">3</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="flex items-center justify-center w-6 h-6 rounded-full text-xs font-semibold bg-indigo-500 text-white" to="/onboarding-4">4</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="px-4 mt-40 py-8">
|
||||||
|
<div className=" flex flex-col items-center gap-20 max-w-md mx-auto">
|
||||||
|
|
||||||
|
<div className="text-center">
|
||||||
|
<svg className="inline-flex w-16 h-16 fill-current mb-6" viewBox="0 0 64 64">
|
||||||
|
<circle className="text-emerald-100" cx="32" cy="32" r="32" />
|
||||||
|
<path className="text-emerald-500" d="m28.5 41-8-8 3-3 5 5 12-12 3 3z" />
|
||||||
|
</svg>
|
||||||
|
<h1 className="text-3xl text-slate-800 font-bold mb-8">{firstNameAccount ? `Nice to meet you, ${firstNameAccount} 🙌` : 'Please, go back step 2'}</h1>
|
||||||
|
<button onClick={createAccount} className="btn px-6 bg-indigo-500 hover:bg-indigo-600 text-white">
|
||||||
|
<Link id="link-dashboard" to={checkBoxesSelected.length===2 && "/digitalId/profile-id"}>Go To Profile -></Link>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<div className="mr-1">
|
||||||
|
<label className="flex items-center">
|
||||||
|
<input id="checkbox-1" onChange={(e)=>saveCheckBoxesValues(e)} type="checkbox" className="form-checkbox" />
|
||||||
|
<span className="text-sm ml-2">I understand that Idntty cannot recover pass phrase</span>
|
||||||
|
</label>
|
||||||
|
<label className="flex items-center">
|
||||||
|
<input id="checkbox-2" onChange={(e)=>saveCheckBoxesValues(e)} type="checkbox" className="form-checkbox" />
|
||||||
|
<div className="text-sm ml-2">
|
||||||
|
I <Link className="text-indigo-500 hover:text-indigo-600 underline" to="/">store my pharse</Link> very carefuly
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Image */}
|
||||||
|
<div className="flex flex-col items-center h-full w-full hidden md:block absolute top-0 bottom-0 right-0 md:w-1/2" aria-hidden="true">
|
||||||
|
<div className="flex mt-40 flex-col items-center gap-2.5">
|
||||||
|
<img className="object-cover object-center" src={generateSvgAvatar(store.pubKey)} width="493px" height="493px" alt="Onboarding" />
|
||||||
|
<span className="text-sm">Your generated Digital ID</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default Onboarding4;
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import AuthImage from '../images/auth-image.jpg';
|
import AuthImage from '../images/auth-image.jpg';
|
||||||
import AuthDecoration from '../images/auth-decoration.png';
|
import AuthDecoration from '../images/auth-decoration.png';
|
||||||
|
import Logo from "../images/logo.png";
|
||||||
|
|
||||||
function ResetPassword() {
|
function ResetPassword() {
|
||||||
return (
|
return (
|
||||||
@@ -18,23 +18,8 @@ function ResetPassword() {
|
|||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<div className="flex items-center justify-between h-16 px-4 sm:px-6 lg:px-8">
|
<div className="flex items-center justify-between h-16 px-4 sm:px-6 lg:px-8">
|
||||||
{/* Logo */}
|
{/* Logo */}
|
||||||
<Link className="block" to="/">
|
<Link className="block" to="/dashboard">
|
||||||
<svg width="32" height="32" viewBox="0 0 32 32">
|
<img alt='logo' src={Logo} width="89" height="32"/>
|
||||||
<defs>
|
|
||||||
<linearGradient x1="28.538%" y1="20.229%" x2="100%" y2="108.156%" id="logo-a">
|
|
||||||
<stop stopColor="#A5B4FC" stopOpacity="0" offset="0%" />
|
|
||||||
<stop stopColor="#A5B4FC" offset="100%" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient x1="88.638%" y1="29.267%" x2="22.42%" y2="100%" id="logo-b">
|
|
||||||
<stop stopColor="#38BDF8" stopOpacity="0" offset="0%" />
|
|
||||||
<stop stopColor="#38BDF8" offset="100%" />
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
<rect fill="#6366F1" width="32" height="32" rx="16" />
|
|
||||||
<path d="M18.277.16C26.035 1.267 32 7.938 32 16c0 8.837-7.163 16-16 16a15.937 15.937 0 01-10.426-3.863L18.277.161z" fill="#4F46E5" />
|
|
||||||
<path d="M7.404 2.503l18.339 26.19A15.93 15.93 0 0116 32C7.163 32 0 24.837 0 16 0 10.327 2.952 5.344 7.404 2.503z" fill="url(#logo-a)" />
|
|
||||||
<path d="M2.223 24.14L29.777 7.86A15.926 15.926 0 0132 16c0 8.837-7.163 16-16 16-5.864 0-10.991-3.154-13.777-7.86z" fill="url(#logo-b)" />
|
|
||||||
</svg>
|
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -42,7 +27,7 @@ function ResetPassword() {
|
|||||||
<div className="max-w-sm mx-auto px-4 py-8">
|
<div className="max-w-sm mx-auto px-4 py-8">
|
||||||
<h1 className="text-3xl text-slate-800 font-bold mb-6">Reset your Password ✨</h1>
|
<h1 className="text-3xl text-slate-800 font-bold mb-6">Reset your Password ✨</h1>
|
||||||
{/* Form */}
|
{/* Form */}
|
||||||
<form>
|
<div>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium mb-1" htmlFor="email">Email Address <span className="text-rose-500">*</span></label>
|
<label className="block text-sm font-medium mb-1" htmlFor="email">Email Address <span className="text-rose-500">*</span></label>
|
||||||
@@ -52,7 +37,7 @@ function ResetPassword() {
|
|||||||
<div className="flex justify-end mt-6">
|
<div className="flex justify-end mt-6">
|
||||||
<button className="btn bg-indigo-500 hover:bg-indigo-600 text-white whitespace-nowrap">Send Reset Link</button>
|
<button className="btn bg-indigo-500 hover:bg-indigo-600 text-white whitespace-nowrap">Send Reset Link</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -70,4 +55,4 @@ function ResetPassword() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ResetPassword;
|
export default ResetPassword;
|
||||||
|
|||||||
102
src/pages/SharedData.jsx
Normal file
102
src/pages/SharedData.jsx
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import {generateSvgAvatar} from "../images/GenerateOnboardingSvg/GenerateSvg";
|
||||||
|
import User06 from "../images/user-28-06.jpg";
|
||||||
|
import User08 from "../images/user-28-08.jpg";
|
||||||
|
import User09 from "../images/user-28-09.jpg";
|
||||||
|
import SharedDataRoadMap from "../partials/sharedData/SharedDataRoadmap";
|
||||||
|
|
||||||
|
function SharedData() {
|
||||||
|
|
||||||
|
const sharedDataItems = {
|
||||||
|
data: localStorage.getItem('digitalId'),
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
dataShared: localStorage.getItem('digitalId'),
|
||||||
|
id: '923',
|
||||||
|
text: 'United Kindom',
|
||||||
|
typeItem: 'Residence',
|
||||||
|
usersImges: [
|
||||||
|
{
|
||||||
|
size: 32,
|
||||||
|
img: User06,
|
||||||
|
imgId: "90"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
size: 32,
|
||||||
|
img: User08,
|
||||||
|
imgId: "93"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
size: 32,
|
||||||
|
img: User09,
|
||||||
|
imgId: "89"
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataShared: localStorage.getItem('digitalId'),
|
||||||
|
id: '401',
|
||||||
|
text: 'A123B3143',
|
||||||
|
typeItem: 'Document ID',
|
||||||
|
usersImges: [
|
||||||
|
{
|
||||||
|
size: 32,
|
||||||
|
img: User06,
|
||||||
|
imgId: "67"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
size: 32,
|
||||||
|
img: User08,
|
||||||
|
imgId: "71"
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main className="bg-white">
|
||||||
|
|
||||||
|
<div className="relative flex">
|
||||||
|
|
||||||
|
{/* Content */}
|
||||||
|
<div className="w-full md:w-1/2">
|
||||||
|
|
||||||
|
<div className="min-h-screen h-full flex flex-col after:flex-1">
|
||||||
|
|
||||||
|
<div className="px-4 mt-16 py-9">
|
||||||
|
<div className=" flex flex-col max-w-md mx-auto">
|
||||||
|
<h1 className="text-3xl text-slate-800 font-bold mb-8">Shared data ✨</h1>
|
||||||
|
<ul>
|
||||||
|
{sharedDataItems.items.map(item => {
|
||||||
|
return(
|
||||||
|
<li key={item.id}>
|
||||||
|
<SharedDataRoadMap data={item}/>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Image */}
|
||||||
|
<div className="flex flex-col items-center h-full w-full hidden md:block absolute top-0 bottom-0 right-0 md:w-1/2" aria-hidden="true">
|
||||||
|
<div className="flex mt-40 flex-col items-center gap-2.5">
|
||||||
|
<img className="object-cover object-center" src={generateSvgAvatar()} width="493px" height="493px" alt="Onboarding" />
|
||||||
|
<span className="text-sm">{sharedDataItems.data}</span>
|
||||||
|
<Link className="mt-12 btn bg-indigo-500 hover:bg-indigo-600 text-white" to="/dashboard">Get my digital ID</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SharedData;
|
||||||
105
src/pages/SignIn.jsx
Normal file
105
src/pages/SignIn.jsx
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
import React, {useState} from 'react';
|
||||||
|
import {observer} from "mobx-react-lite";
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import {generateSvgAvatar} from "../images/GenerateOnboardingSvg/GenerateSvg";
|
||||||
|
import Logo from "../images/logo.png";
|
||||||
|
import {store} from "../store/store";
|
||||||
|
|
||||||
|
const SignIn = observer(()=>{
|
||||||
|
|
||||||
|
const[passPhrase, setPassPhrase] = useState('- - - - - - - - - - - -');
|
||||||
|
const[addedPassPhrase, setAddedPassPhrase] = useState(false);
|
||||||
|
|
||||||
|
function savePassPhrase (copiedPhrase) {
|
||||||
|
if (copiedPhrase.split(' ').length === 12) {
|
||||||
|
store.savePastPassPhrase(copiedPhrase.trim());
|
||||||
|
setPassPhrase(store.passPhrase);
|
||||||
|
setAddedPassPhrase(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertPassPhraseToArray() {
|
||||||
|
return passPhrase.split(' ').map((item, index) => ({str:item, id:index}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function pastePassPhrase() {
|
||||||
|
navigator.clipboard.readText().then(res => savePassPhrase(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main className="bg-white">
|
||||||
|
|
||||||
|
<div className="relative flex">
|
||||||
|
|
||||||
|
{/* Content */}
|
||||||
|
<div className="w-full md:w-1/2">
|
||||||
|
|
||||||
|
<div className="min-h-screen h-full flex flex-col after:flex-1">
|
||||||
|
|
||||||
|
<div className="flex-1">
|
||||||
|
|
||||||
|
{/* Header */}
|
||||||
|
<div className="flex items-center justify-between h-16 px-4 sm:px-6 lg:px-8">
|
||||||
|
{/* Logo */}
|
||||||
|
<Link className="block" to="/">
|
||||||
|
<img alt='logo' src={Logo} width="89" height="32"/>
|
||||||
|
</Link>
|
||||||
|
<div className="text-sm">
|
||||||
|
Have not an account? <Link className="font-medium text-indigo-500 hover:text-indigo-600" to="/">Sign Up</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="px-4 mt-20 py-8">
|
||||||
|
<div className="max-w-fit mx-auto flex flex-col gap-y-36">
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h1 className="text-3xl text-slate-800 font-bold mb-12">Company information ✨</h1>
|
||||||
|
{/* htmlForm */}
|
||||||
|
<div className="grid grid-cols-4 gap-y-2.5 gap-[18px] mb-14">
|
||||||
|
{convertPassPhraseToArray().map(tag => (
|
||||||
|
<button key={tag.id} className="min-w-[93px] min-h-[26px] bg-slate-100 text-slate-500 cursor-pointer hover:bg-blue-100 hover:text-blue-600 rounded-full text-center px-2.5">
|
||||||
|
<span className="text-sm font-medium">{tag.str}</span>
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div className="flex pl-7 gap-x-5">
|
||||||
|
<button onClick={pastePassPhrase} className="btn pl-9 pr-16 border-slate-200 hover:border-slate-300 text-slate-600">
|
||||||
|
<svg className="w-4 h-4 fill-current text-slate-400 shrink-0 mb-0.5" viewBox="0 0 16 16">
|
||||||
|
<path
|
||||||
|
d="M11.7.3c-.4-.4-1-.4-1.4 0l-10 10c-.2.2-.3.4-.3.7v4c0 .6.4 1 1 1h4c.3 0 .5-.1.7-.3l10-10c.4-.4.4-1 0-1.4l-4-4zM4.6 14H2v-2.6l6-6L10.6 8l-6 6zM12 6.6L9.4 4 11 2.4 13.6 5 12 6.6z"></path>
|
||||||
|
</svg>
|
||||||
|
<span className="ml-2">Paste</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<button className="btn bg-indigo-500 hover:bg-indigo-600 text-white ml-auto">
|
||||||
|
<Link to={addedPassPhrase && "/digitalId/profile-id"}>Go To Profile -></Link>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Image */}
|
||||||
|
<div className="flex flex-col items-center h-full w-full hidden md:block absolute top-0 bottom-0 right-0 md:w-1/2" aria-hidden="true">
|
||||||
|
<div className="flex mt-40 flex-col items-center gap-2.5">
|
||||||
|
<div className={`${addedPassPhrase || 'opacity-0'} w-[493px] h-[493px]`}>
|
||||||
|
<img className="object-cover object-center" alt="" src={generateSvgAvatar(store.pubKey)}/>
|
||||||
|
</div>
|
||||||
|
<span className="text-sm">Your Digital ID</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default SignIn;
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
import AuthImage from '../images/auth-image.jpg';
|
|
||||||
import AuthDecoration from '../images/auth-decoration.png';
|
|
||||||
|
|
||||||
function Signin() {
|
|
||||||
return (
|
|
||||||
<main className="bg-white">
|
|
||||||
|
|
||||||
<div className="relative md:flex">
|
|
||||||
|
|
||||||
{/* Content */}
|
|
||||||
<div className="md:w-1/2">
|
|
||||||
<div className="min-h-screen h-full flex flex-col after:flex-1">
|
|
||||||
|
|
||||||
{/* Header */}
|
|
||||||
<div className="flex-1">
|
|
||||||
<div className="flex items-center justify-between h-16 px-4 sm:px-6 lg:px-8">
|
|
||||||
{/* Logo */}
|
|
||||||
<Link className="block" to="/">
|
|
||||||
<svg width="32" height="32" viewBox="0 0 32 32">
|
|
||||||
<defs>
|
|
||||||
<linearGradient x1="28.538%" y1="20.229%" x2="100%" y2="108.156%" id="logo-a">
|
|
||||||
<stop stopColor="#A5B4FC" stopOpacity="0" offset="0%" />
|
|
||||||
<stop stopColor="#A5B4FC" offset="100%" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient x1="88.638%" y1="29.267%" x2="22.42%" y2="100%" id="logo-b">
|
|
||||||
<stop stopColor="#38BDF8" stopOpacity="0" offset="0%" />
|
|
||||||
<stop stopColor="#38BDF8" offset="100%" />
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
<rect fill="#6366F1" width="32" height="32" rx="16" />
|
|
||||||
<path d="M18.277.16C26.035 1.267 32 7.938 32 16c0 8.837-7.163 16-16 16a15.937 15.937 0 01-10.426-3.863L18.277.161z" fill="#4F46E5" />
|
|
||||||
<path d="M7.404 2.503l18.339 26.19A15.93 15.93 0 0116 32C7.163 32 0 24.837 0 16 0 10.327 2.952 5.344 7.404 2.503z" fill="url(#logo-a)" />
|
|
||||||
<path d="M2.223 24.14L29.777 7.86A15.926 15.926 0 0132 16c0 8.837-7.163 16-16 16-5.864 0-10.991-3.154-13.777-7.86z" fill="url(#logo-b)" />
|
|
||||||
</svg>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="max-w-sm mx-auto px-4 py-8">
|
|
||||||
<h1 className="text-3xl text-slate-800 font-bold mb-6">Welcome back! ✨</h1>
|
|
||||||
{/* Form */}
|
|
||||||
<form>
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div>
|
|
||||||
<label className="block text-sm font-medium mb-1" htmlFor="email">Email Address</label>
|
|
||||||
<input id="email" className="form-input w-full" type="email" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label className="block text-sm font-medium mb-1" htmlFor="password">Password</label>
|
|
||||||
<input id="password" className="form-input w-full" type="password" autoComplete="on" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center justify-between mt-6">
|
|
||||||
<div className="mr-1">
|
|
||||||
<Link className="text-sm underline hover:no-underline" to="/reset-password">Forgot Password?</Link>
|
|
||||||
</div>
|
|
||||||
<Link className="btn bg-indigo-500 hover:bg-indigo-600 text-white ml-3" to="/">Sign In</Link>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{/* Footer */}
|
|
||||||
<div className="pt-5 mt-6 border-t border-slate-200">
|
|
||||||
<div className="text-sm">
|
|
||||||
Don’t you have an account? <Link className="font-medium text-indigo-500 hover:text-indigo-600" to="/signup">Sign Up</Link>
|
|
||||||
</div>
|
|
||||||
{/* Warning */}
|
|
||||||
<div className="mt-5">
|
|
||||||
<div className="bg-amber-100 text-amber-600 px-3 py-2 rounded">
|
|
||||||
<svg className="inline w-3 h-3 shrink-0 fill-current mr-2" viewBox="0 0 12 12">
|
|
||||||
<path d="M10.28 1.28L3.989 7.575 1.695 5.28A1 1 0 00.28 6.695l3 3a1 1 0 001.414 0l7-7A1 1 0 0010.28 1.28z" />
|
|
||||||
</svg>
|
|
||||||
<span className="text-sm">
|
|
||||||
To support you during the pandemic super pro features are free until March 31st.
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Image */}
|
|
||||||
<div className="hidden md:block absolute top-0 bottom-0 right-0 md:w-1/2" aria-hidden="true">
|
|
||||||
<img className="object-cover object-center w-full h-full" src={AuthImage} width="760" height="1024" alt="Authentication" />
|
|
||||||
<img className="absolute top-1/4 left-0 transform -translate-x-1/2 ml-8 hidden lg:block" src={AuthDecoration} width="218" height="224" alt="Authentication decoration" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</main>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Signin;
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
import AuthImage from '../images/auth-image.jpg';
|
|
||||||
import AuthDecoration from '../images/auth-decoration.png';
|
|
||||||
|
|
||||||
function Signup() {
|
|
||||||
return (
|
|
||||||
<main className="bg-white">
|
|
||||||
|
|
||||||
<div className="relative md:flex">
|
|
||||||
|
|
||||||
{/* Content */}
|
|
||||||
<div className="md:w-1/2">
|
|
||||||
<div className="min-h-screen h-full flex flex-col after:flex-1">
|
|
||||||
|
|
||||||
{/* Header */}
|
|
||||||
<div className="flex-1">
|
|
||||||
<div className="flex items-center justify-between h-16 px-4 sm:px-6 lg:px-8">
|
|
||||||
{/* Logo */}
|
|
||||||
<Link className="block" to="/">
|
|
||||||
<svg width="32" height="32" viewBox="0 0 32 32">
|
|
||||||
<defs>
|
|
||||||
<linearGradient x1="28.538%" y1="20.229%" x2="100%" y2="108.156%" id="logo-a">
|
|
||||||
<stop stopColor="#A5B4FC" stopOpacity="0" offset="0%" />
|
|
||||||
<stop stopColor="#A5B4FC" offset="100%" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient x1="88.638%" y1="29.267%" x2="22.42%" y2="100%" id="logo-b">
|
|
||||||
<stop stopColor="#38BDF8" stopOpacity="0" offset="0%" />
|
|
||||||
<stop stopColor="#38BDF8" offset="100%" />
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
<rect fill="#6366F1" width="32" height="32" rx="16" />
|
|
||||||
<path d="M18.277.16C26.035 1.267 32 7.938 32 16c0 8.837-7.163 16-16 16a15.937 15.937 0 01-10.426-3.863L18.277.161z" fill="#4F46E5" />
|
|
||||||
<path d="M7.404 2.503l18.339 26.19A15.93 15.93 0 0116 32C7.163 32 0 24.837 0 16 0 10.327 2.952 5.344 7.404 2.503z" fill="url(#logo-a)" />
|
|
||||||
<path d="M2.223 24.14L29.777 7.86A15.926 15.926 0 0132 16c0 8.837-7.163 16-16 16-5.864 0-10.991-3.154-13.777-7.86z" fill="url(#logo-b)" />
|
|
||||||
</svg>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="max-w-sm mx-auto px-4 py-8">
|
|
||||||
<h1 className="text-3xl text-slate-800 font-bold mb-6">Create your Account ✨</h1>
|
|
||||||
{/* Form */}
|
|
||||||
<form>
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div>
|
|
||||||
<label className="block text-sm font-medium mb-1" htmlFor="email">Email Address <span className="text-rose-500">*</span></label>
|
|
||||||
<input id="email" className="form-input w-full" type="email" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label className="block text-sm font-medium mb-1" htmlFor="name">Full Name <span className="text-rose-500">*</span></label>
|
|
||||||
<input id="name" className="form-input w-full" type="text" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label className="block text-sm font-medium mb-1" htmlFor="role">Your Role <span className="text-rose-500">*</span></label>
|
|
||||||
<select id="role" className="form-select w-full">
|
|
||||||
<option>Designer</option>
|
|
||||||
<option>Developer</option>
|
|
||||||
<option>Accountant</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label className="block text-sm font-medium mb-1" htmlFor="password">Password</label>
|
|
||||||
<input id="password" className="form-input w-full" type="password" autoComplete="on" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center justify-between mt-6">
|
|
||||||
<div className="mr-1">
|
|
||||||
<label className="flex items-center">
|
|
||||||
<input type="checkbox" className="form-checkbox" />
|
|
||||||
<span className="text-sm ml-2">Email me about product news.</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<Link className="btn bg-indigo-500 hover:bg-indigo-600 text-white ml-3 whitespace-nowrap" to="/">Sign Up</Link>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{/* Footer */}
|
|
||||||
<div className="pt-5 mt-6 border-t border-slate-200">
|
|
||||||
<div className="text-sm">
|
|
||||||
Have an account? <Link className="font-medium text-indigo-500 hover:text-indigo-600" to="/signin">Sign In</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Image */}
|
|
||||||
<div className="hidden md:block absolute top-0 bottom-0 right-0 md:w-1/2" aria-hidden="true">
|
|
||||||
<img className="object-cover object-center w-full h-full" src={AuthImage} width="760" height="1024" alt="Authentication" />
|
|
||||||
<img className="absolute top-1/4 left-0 transform -translate-x-1/2 ml-8 hidden lg:block" src={AuthDecoration} width="218" height="224" alt="Authentication decoration" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</main>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Signup;
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
|
|
||||||
import Sidebar from '../../partials/Sidebar';
|
|
||||||
import Header from '../../partials/Header';
|
|
||||||
import FeedLeftContent from '../../partials/community/FeedLeftContent';
|
|
||||||
import FeedPosts from '../../partials/community/FeedPosts';
|
|
||||||
import FeedRightContent from '../../partials/community/FeedRightContent';
|
|
||||||
|
|
||||||
import Avatar from '../../images/user-40-02.jpg';
|
|
||||||
|
|
||||||
function Feed() {
|
|
||||||
|
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex h-screen overflow-hidden">
|
|
||||||
{/* Sidebar */}
|
|
||||||
<Sidebar sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
{/* Content area */}
|
|
||||||
<div className="relative flex flex-col flex-1 overflow-y-auto overflow-x-hidden">
|
|
||||||
{/* Site header */}
|
|
||||||
<Header sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div className="px-4 sm:px-6 lg:px-8 py-8 md:py-0 w-full max-w-9xl mx-auto">
|
|
||||||
|
|
||||||
<div className="xl:flex">
|
|
||||||
|
|
||||||
{/* Left + Middle content */}
|
|
||||||
<div className="md:flex flex-1">
|
|
||||||
|
|
||||||
{/* Left content */}
|
|
||||||
<FeedLeftContent />
|
|
||||||
|
|
||||||
{/* Middle content */}
|
|
||||||
<div className="flex-1 md:ml-8 xl:mx-4 2xl:mx-8">
|
|
||||||
<div className="md:py-8">
|
|
||||||
|
|
||||||
{/* Blocks */}
|
|
||||||
<div className="space-y-4">
|
|
||||||
|
|
||||||
{/* Post Block */}
|
|
||||||
<div className="bg-white shadow-md rounded border border-slate-200 p-5">
|
|
||||||
<div className="flex items-center space-x-3 mb-5">
|
|
||||||
<img className="rounded-full shrink-0" src={Avatar} width="40" height="40" alt="User 02" />
|
|
||||||
<div className="grow">
|
|
||||||
<label htmlFor="status-input" className="sr-only">
|
|
||||||
What's happening, Mark?
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
id="status-input"
|
|
||||||
className="form-input w-full bg-slate-100 border-transparent focus:bg-white focus:border-slate-300 placeholder-slate-500"
|
|
||||||
type="text"
|
|
||||||
placeholder="What's happening, Mark?"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-between items-center">
|
|
||||||
<div className="grow flex space-x-5">
|
|
||||||
<button className="inline-flex items-center text-sm font-medium text-slate-600 hover:text-slate-700">
|
|
||||||
<svg className="w-4 h-4 fill-indigo-400 mr-2" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M0 0h2v16H0V0Zm14 0h2v16h-2V0Zm-3 7H5c-.6 0-1-.4-1-1V1c0-.6.4-1 1-1h6c.6 0 1 .4 1 1v5c0 .6-.4 1-1 1ZM6 5h4V2H6v3Zm5 11H5c-.6 0-1-.4-1-1v-5c0-.6.4-1 1-1h6c.6 0 1 .4 1 1v5c0 .6-.4 1-1 1Zm-5-2h4v-3H6v3Z" />
|
|
||||||
</svg>
|
|
||||||
<span>Media</span>
|
|
||||||
</button>
|
|
||||||
<button className="inline-flex items-center text-sm font-medium text-slate-600 hover:text-slate-700">
|
|
||||||
<svg className="w-4 h-4 fill-indigo-400 mr-2" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M6.974 14c-.3 0-.7-.2-.9-.5l-2.2-3.7-2.1 2.8c-.3.4-1 .5-1.4.2-.4-.3-.5-1-.2-1.4l3-4c.2-.3.5-.4.9-.4.3 0 .6.2.8.5l2 3.3 3.3-8.1c0-.4.4-.7.8-.7s.8.2.9.6l4 8c.2.5 0 1.1-.4 1.3-.5.2-1.1 0-1.3-.4l-3-6-3.2 7.9c-.2.4-.6.6-1 .6Z" />
|
|
||||||
</svg>
|
|
||||||
<span>GIF</span>
|
|
||||||
</button>
|
|
||||||
<button className="inline-flex items-center text-sm font-medium text-slate-600 hover:text-slate-700">
|
|
||||||
<svg className="w-4 h-4 fill-indigo-400 mr-2" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M9.793 10.002a.5.5 0 0 1 .353.853l-1.792 1.793a.5.5 0 0 1-.708 0l-1.792-1.793a.5.5 0 0 1 .353-.853h3.586Zm5.014-4.63c1.178 2.497 1.833 5.647.258 7.928-1.238 1.793-3.615 2.702-7.065 2.702S2.173 15.092.935 13.3c-1.575-2.28-.92-5.431.258-7.927A2.962 2.962 0 0 1 0 3.002a3 3 0 0 1 3-3c.787 0 1.496.309 2.029.806a5.866 5.866 0 0 1 5.942 0A2.96 2.96 0 0 1 13 .002a3 3 0 0 1 3 3c0 .974-.472 1.827-1.193 2.37Zm-1.387 6.79c1.05-1.522.417-3.835-.055-5.078C12.915 5.89 11.192 2.002 8 2.002s-4.914 3.89-5.365 5.082c-.472 1.243-1.106 3.556-.055 5.079.843 1.22 2.666 1.839 5.42 1.839s4.577-.62 5.42-1.84ZM6.67 6.62c.113.443.102.68-.433 1.442-.535.761-1.06 1.297-1.658 1.297-.597 0-1.08-.772-1.07-1.483.01-.71.916-2.306 1.997-2.306.784 0 1.05.607 1.163 1.05Zm3.824-1.05c1.08 0 1.987 1.596 1.997 2.306.01.71-.473 1.483-1.07 1.483-.598 0-1.123-.536-1.658-1.297-.535-.762-.546-1-.432-1.442.113-.443.38-1.05 1.163-1.05Z" />
|
|
||||||
</svg>
|
|
||||||
<span>Emoji</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<button type="submit" className="btn-sm bg-indigo-500 hover:bg-indigo-600 text-white whitespace-nowrap">
|
|
||||||
Send ->
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Posts */}
|
|
||||||
<FeedPosts />
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Right content */}
|
|
||||||
<FeedRightContent />
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Feed;
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
|
|
||||||
import Sidebar from '../../partials/Sidebar';
|
|
||||||
import Header from '../../partials/Header';
|
|
||||||
import ForumLeftContent from '../../partials/community/ForumLeftContent';
|
|
||||||
import ForumEntries from '../../partials/community/ForumEntries';
|
|
||||||
import ForumRightContent from '../../partials/community/ForumRightContent';
|
|
||||||
|
|
||||||
import Avatar from '../../images/user-40-02.jpg';
|
|
||||||
|
|
||||||
function Forum() {
|
|
||||||
|
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex h-screen overflow-hidden">
|
|
||||||
{/* Sidebar */}
|
|
||||||
<Sidebar sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
{/* Content area */}
|
|
||||||
<div className="relative flex flex-col flex-1 overflow-y-auto overflow-x-hidden">
|
|
||||||
{/* Site header */}
|
|
||||||
<Header sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div className="px-4 sm:px-6 lg:px-8 py-8 md:py-0 w-full max-w-9xl mx-auto">
|
|
||||||
|
|
||||||
<div className="xl:flex">
|
|
||||||
|
|
||||||
{/* Left + Middle content */}
|
|
||||||
<div className="md:flex flex-1">
|
|
||||||
|
|
||||||
{/* Left content */}
|
|
||||||
<ForumLeftContent />
|
|
||||||
|
|
||||||
{/* Middle content */}
|
|
||||||
<div className="flex-1 md:ml-8 xl:mx-4 2xl:mx-8">
|
|
||||||
<div className="md:py-8">
|
|
||||||
|
|
||||||
{/* Buttons group */}
|
|
||||||
<div className="mb-4">
|
|
||||||
<div className="w-full flex flex-wrap -space-x-px">
|
|
||||||
<button className="btn grow bg-white border-slate-200 text-indigo-500 rounded-none first:rounded-l last:rounded-r">Popular</button>
|
|
||||||
<button className="btn grow bg-white border-slate-200 hover:bg-slate-50 text-slate-600 rounded-none first:rounded-l last:rounded-r">Newest</button>
|
|
||||||
<button className="btn grow bg-white border-slate-200 hover:bg-slate-50 text-slate-600 rounded-none first:rounded-l last:rounded-r">Following</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Forum Entries */}
|
|
||||||
<div className="space-y-2">
|
|
||||||
<ForumEntries />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Pagination */}
|
|
||||||
<div className="mt-6 text-right">
|
|
||||||
<nav className="inline-flex" role="navigation" aria-label="Navigation">
|
|
||||||
<ul className="flex justify-center">
|
|
||||||
<li className="ml-3 first:ml-0">
|
|
||||||
<a className="btn bg-white border-slate-200 text-slate-300 cursor-not-allowed" href="#0" disabled><- Previous</a>
|
|
||||||
</li>
|
|
||||||
<li className="ml-3 first:ml-0">
|
|
||||||
<a className="btn bg-white border-slate-200 hover:border-slate-300 text-indigo-500" href="#0">Next -></a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Right content */}
|
|
||||||
<ForumRightContent />
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Forum;
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
|
|
||||||
import Sidebar from '../../partials/Sidebar';
|
|
||||||
import Header from '../../partials/Header';
|
|
||||||
import ForumLeftContent from '../../partials/community/ForumLeftContent';
|
|
||||||
import ForumEntry from '../../partials/community/ForumEntry';
|
|
||||||
import ForumRightContent from '../../partials/community/ForumPostRightContent';
|
|
||||||
|
|
||||||
function ForumPost() {
|
|
||||||
|
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex h-screen overflow-hidden">
|
|
||||||
{/* Sidebar */}
|
|
||||||
<Sidebar sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
{/* Content area */}
|
|
||||||
<div className="relative flex flex-col flex-1 overflow-y-auto overflow-x-hidden">
|
|
||||||
{/* Site header */}
|
|
||||||
<Header sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div className="px-4 sm:px-6 lg:px-8 py-8 md:py-0 w-full max-w-9xl mx-auto">
|
|
||||||
|
|
||||||
<div className="xl:flex">
|
|
||||||
|
|
||||||
{/* Left + Middle content */}
|
|
||||||
<div className="md:flex flex-1">
|
|
||||||
|
|
||||||
{/* Left content */}
|
|
||||||
<ForumLeftContent />
|
|
||||||
|
|
||||||
{/* Middle content */}
|
|
||||||
<div className="flex-1 md:ml-8 xl:mx-4 2xl:mx-8">
|
|
||||||
<div className="md:py-8">
|
|
||||||
|
|
||||||
{/* Forum entry */}
|
|
||||||
<ForumEntry />
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Right content */}
|
|
||||||
<ForumRightContent />
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ForumPost;
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
|
|
||||||
import Sidebar from '../../partials/Sidebar';
|
|
||||||
import Header from '../../partials/Header';
|
|
||||||
import SearchForm from '../../partials/actions/SearchForm';
|
|
||||||
import MeetupsPosts from '../../partials/community/MeetupsPosts';
|
|
||||||
import PaginationNumeric from '../../components/PaginationNumeric';
|
|
||||||
|
|
||||||
function Meetups() {
|
|
||||||
|
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex h-screen overflow-hidden">
|
|
||||||
{/* Sidebar */}
|
|
||||||
<Sidebar sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
{/* Content area */}
|
|
||||||
<div className="relative flex flex-col flex-1 overflow-y-auto overflow-x-hidden">
|
|
||||||
|
|
||||||
{/* Site header */}
|
|
||||||
<Header sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div className="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
|
|
||||||
|
|
||||||
{/* Page header */}
|
|
||||||
<div className="sm:flex sm:justify-between sm:items-center mb-5">
|
|
||||||
|
|
||||||
{/* Left: Title */}
|
|
||||||
<div className="mb-4 sm:mb-0">
|
|
||||||
<h1 className="text-2xl md:text-3xl text-slate-800 font-bold">Discover Meetups ✨</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Right: Actions */}
|
|
||||||
<div className="grid grid-flow-col sm:auto-cols-max justify-start sm:justify-end gap-2">
|
|
||||||
|
|
||||||
{/* Search form */}
|
|
||||||
<SearchForm placeholder="Search…" />
|
|
||||||
|
|
||||||
{/* Add meetup button */}
|
|
||||||
<button className="btn bg-indigo-500 hover:bg-indigo-600 text-white">
|
|
||||||
<svg className="w-4 h-4 fill-current opacity-50 shrink-0" viewBox="0 0 16 16">
|
|
||||||
<path d="M15 7H9V1c0-.6-.4-1-1-1S7 .4 7 1v6H1c-.6 0-1 .4-1 1s.4 1 1 1h6v6c0 .6.4 1 1 1s1-.4 1-1V9h6c.6 0 1-.4 1-1s-.4-1-1-1z" />
|
|
||||||
</svg>
|
|
||||||
<span className="hidden xs:block ml-2">Add Meetup</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Filters */}
|
|
||||||
<div className="mb-5">
|
|
||||||
<ul className="flex flex-wrap -m-1">
|
|
||||||
<li className="m-1">
|
|
||||||
<button className="inline-flex items-center justify-center text-sm font-medium leading-5 rounded-full px-3 py-1 border border-transparent shadow-sm bg-indigo-500 text-white duration-150 ease-in-out">
|
|
||||||
View All
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li className="m-1">
|
|
||||||
<button className="inline-flex items-center justify-center text-sm font-medium leading-5 rounded-full px-3 py-1 border border-slate-200 hover:border-slate-300 shadow-sm bg-white text-slate-500 duration-150 ease-in-out">
|
|
||||||
Online
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li className="m-1">
|
|
||||||
<button className="inline-flex items-center justify-center text-sm font-medium leading-5 rounded-full px-3 py-1 border border-slate-200 hover:border-slate-300 shadow-sm bg-white text-slate-500 duration-150 ease-in-out">
|
|
||||||
Local
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li className="m-1">
|
|
||||||
<button className="inline-flex items-center justify-center text-sm font-medium leading-5 rounded-full px-3 py-1 border border-slate-200 hover:border-slate-300 shadow-sm bg-white text-slate-500 duration-150 ease-in-out">
|
|
||||||
This Week
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li className="m-1">
|
|
||||||
<button className="inline-flex items-center justify-center text-sm font-medium leading-5 rounded-full px-3 py-1 border border-slate-200 hover:border-slate-300 shadow-sm bg-white text-slate-500 duration-150 ease-in-out">
|
|
||||||
This Month
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li className="m-1">
|
|
||||||
<button className="inline-flex items-center justify-center text-sm font-medium leading-5 rounded-full px-3 py-1 border border-slate-200 hover:border-slate-300 shadow-sm bg-white text-slate-500 duration-150 ease-in-out">
|
|
||||||
Following
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div className="text-sm text-slate-500 italic mb-4">289 Meetups</div>
|
|
||||||
|
|
||||||
{/* Content */}
|
|
||||||
<MeetupsPosts />
|
|
||||||
|
|
||||||
{/* Pagination */}
|
|
||||||
<div className="mt-8">
|
|
||||||
<PaginationNumeric />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Meetups;
|
|
||||||
@@ -1,431 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
import Sidebar from '../../partials/Sidebar';
|
|
||||||
import Header from '../../partials/Header';
|
|
||||||
|
|
||||||
import MeetupImage from '../../images/meetup-image.jpg';
|
|
||||||
import MeetupPhoto01 from '../../images/meetup-photo-01.jpg';
|
|
||||||
import MeetupPhoto02 from '../../images/meetup-photo-02.jpg';
|
|
||||||
import MeetupPhoto03 from '../../images/meetup-photo-03.jpg';
|
|
||||||
import MeetupThumb from '../../images/meetups-thumb-02.jpg';
|
|
||||||
import UserImage01 from '../../images/user-32-01.jpg';
|
|
||||||
import UserImage02 from '../../images/user-32-02.jpg';
|
|
||||||
import UserImage03 from '../../images/user-32-03.jpg';
|
|
||||||
import UserImage04 from '../../images/user-32-04.jpg';
|
|
||||||
import UserImage05 from '../../images/user-32-05.jpg';
|
|
||||||
import UserImage06 from '../../images/user-32-06.jpg';
|
|
||||||
import UserImage07 from '../../images/user-32-07.jpg';
|
|
||||||
import UserImage08 from '../../images/user-32-08.jpg';
|
|
||||||
import Avatar02 from '../../images/avatar-02.jpg';
|
|
||||||
import Avatar03 from '../../images/avatar-03.jpg';
|
|
||||||
import Avatar04 from '../../images/avatar-04.jpg';
|
|
||||||
|
|
||||||
function MeetupsPost() {
|
|
||||||
|
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex h-screen overflow-hidden">
|
|
||||||
|
|
||||||
{/* Sidebar */}
|
|
||||||
<Sidebar sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
{/* Content area */}
|
|
||||||
<div className="relative flex flex-col flex-1 overflow-y-auto overflow-x-hidden">
|
|
||||||
{/* Site header */}
|
|
||||||
<Header sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div className="px-4 sm:px-6 lg:px-8 py-8 w-full">
|
|
||||||
{/* Page content */}
|
|
||||||
<div className="max-w-5xl mx-auto flex flex-col lg:flex-row lg:space-x-8 xl:space-x-16">
|
|
||||||
{/* Content */}
|
|
||||||
<div>
|
|
||||||
<div className="mb-6">
|
|
||||||
<Link className="btn-sm px-3 bg-white border-slate-200 hover:border-slate-300 text-slate-600" to="/community/meetups">
|
|
||||||
<svg className="fill-current text-slate-400 mr-2" width="7" height="12" viewBox="0 0 7 12">
|
|
||||||
<path d="M5.4.6 6.8 2l-4 4 4 4-1.4 1.4L0 6z" />
|
|
||||||
</svg>
|
|
||||||
<span>Back To Meetups</span>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
<div className="text-sm font-semibold text-indigo-500 uppercase mb-2">Mon 27 Dec, 2021 - 9:00 PM -> 10:00 PM</div>
|
|
||||||
<header className="mb-4">
|
|
||||||
{/* Title */}
|
|
||||||
<h1 className="text-2xl md:text-3xl text-slate-800 font-bold mb-2">The World of AI and Machine Learning — Open Chat</h1>
|
|
||||||
<p>Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts.</p>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
{/* Meta */}
|
|
||||||
<div className="space-y-3 sm:flex sm:items-center sm:justify-between sm:space-y-0 mb-6">
|
|
||||||
{/* Author */}
|
|
||||||
<div className="flex items-center sm:mr-4">
|
|
||||||
<a className="block mr-2 shrink-0" href="#0">
|
|
||||||
<img className="rounded-full" src={UserImage07} width="32" height="32" alt="User 04" />
|
|
||||||
</a>
|
|
||||||
<div className="text-sm whitespace-nowrap">
|
|
||||||
Hosted by{' '}
|
|
||||||
<a className="font-semibold text-slate-800" href="#0">
|
|
||||||
Monica Fishkin
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/* Right side */}
|
|
||||||
<div className="flex flex-wrap items-center sm:justify-end space-x-2">
|
|
||||||
{/* Tags */}
|
|
||||||
<div className="text-xs inline-flex items-center font-medium bg-white text-slate-600 rounded-full text-center px-2.5 py-1">
|
|
||||||
<svg className="w-4 h-3 fill-slate-400 mr-2" viewBox="0 0 16 12">
|
|
||||||
<path d="m16 2-4 2.4V2a2 2 0 0 0-2-2H2a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7.6l4 2.4V2ZM2 10V2h8v8H2Z" />
|
|
||||||
</svg>
|
|
||||||
<span>Online Event</span>
|
|
||||||
</div>
|
|
||||||
<div className="text-xs inline-flex font-medium uppercase bg-emerald-100 text-emerald-600 rounded-full text-center px-2.5 py-1">
|
|
||||||
Free
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Image */}
|
|
||||||
<figure className="mb-6">
|
|
||||||
<img className="w-full rounded-sm" src={MeetupImage} width="640" height="360" alt="Meetup" />
|
|
||||||
</figure>
|
|
||||||
|
|
||||||
{/* Post content */}
|
|
||||||
<div>
|
|
||||||
<h2 className="text-xl leading-snug text-slate-800 font-bold mb-2">Meetup Details</h2>
|
|
||||||
<p className="mb-6">In the world of AI, behavioural predictions are leading the charge to better machine learning.</p>
|
|
||||||
<p className="mb-6">
|
|
||||||
There is so much happening in the AI space. Advances in the economic sectors have seen automated business practices rapidly
|
|
||||||
increasing economic value. While the realm of the human sciences has used the power afforded by computational capabilities to
|
|
||||||
solve many human based dilemmas. Even the art scene has adopted carefully selected ML applications to usher in the technological
|
|
||||||
movement.
|
|
||||||
</p>
|
|
||||||
<p className="mb-6">
|
|
||||||
Join us every second Wednesday as we host an open discussion about the amazing things happening in the world of AI and machine
|
|
||||||
learning. Feel free to share your experiences, ask questions, ponder the possibilities, or just listen as we explore new topics
|
|
||||||
and revisit old ones.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<hr className="my-6 border-t border-slate-200" />
|
|
||||||
|
|
||||||
{/* Photos */}
|
|
||||||
<div>
|
|
||||||
<h2 className="text-xl leading-snug text-slate-800 font-bold mb-2">Photos (3)</h2>
|
|
||||||
<div className="grid grid-cols-3 gap-4 my-6">
|
|
||||||
<a className="block" href="#0">
|
|
||||||
<img className="w-full rounded-sm" src={MeetupPhoto01} width="203" height="152" alt="Meetup photo 01" />
|
|
||||||
</a>
|
|
||||||
<a className="block" href="#0">
|
|
||||||
<img className="w-full rounded-sm" src={MeetupPhoto02} width="203" height="152" alt="Meetup photo 02" />
|
|
||||||
</a>
|
|
||||||
<a className="block" href="#0">
|
|
||||||
<img className="w-full rounded-sm" src={MeetupPhoto03} width="203" height="152" alt="Meetup photo 03" />
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr className="my-6 border-t border-slate-200" />
|
|
||||||
|
|
||||||
{/* Comments */}
|
|
||||||
<div>
|
|
||||||
<h2 className="text-xl leading-snug text-slate-800 font-bold mb-2">Comments (3)</h2>
|
|
||||||
<ul className="space-y-5 my-6">
|
|
||||||
{/* Comment */}
|
|
||||||
<li className="flex items-start">
|
|
||||||
<a className="block mr-3 shrink-0" href="#0">
|
|
||||||
<img className="rounded-full" src={UserImage07} width="32" height="32" alt="User 07" />
|
|
||||||
</a>
|
|
||||||
<div className="grow">
|
|
||||||
<div className="text-sm font-semibold text-slate-800 mb-2">Taylor Nieman</div>
|
|
||||||
<div className="italic">
|
|
||||||
“Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
|
||||||
Ut enim ad minim veniam.”
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
{/* Comment */}
|
|
||||||
<li className="flex items-start">
|
|
||||||
<a className="block mr-3 shrink-0" href="#0">
|
|
||||||
<img className="rounded-full" src={UserImage08} width="32" height="32" alt="User 08" />
|
|
||||||
</a>
|
|
||||||
<div className="grow">
|
|
||||||
<div className="text-sm font-semibold text-slate-800 mb-2">Meagan Loyst</div>
|
|
||||||
<div className="italic">
|
|
||||||
“Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
|
||||||
Ut enim ad minim veniam.”
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
{/* Comment */}
|
|
||||||
<li className="flex items-start">
|
|
||||||
<a className="block mr-3 shrink-0" href="#0">
|
|
||||||
<img className="rounded-full" src={UserImage02} width="32" height="32" alt="User 02" />
|
|
||||||
</a>
|
|
||||||
<div className="grow">
|
|
||||||
<div className="text-sm font-semibold text-slate-800 mb-2">Frank Malik</div>
|
|
||||||
<div className="italic">
|
|
||||||
“Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
|
||||||
Ut enim ad minim veniam.”
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr className="my-6 border-t border-slate-200" />
|
|
||||||
|
|
||||||
{/* Similar Meetups */}
|
|
||||||
<div>
|
|
||||||
<h2 className="text-xl leading-snug text-slate-800 font-bold mb-2">Similar Meetups</h2>
|
|
||||||
<div className="space-y-8 sm:space-y-5 my-6 lg:mb-0">
|
|
||||||
{/* Related item */}
|
|
||||||
<article className="flex bg-white shadow-lg rounded-sm border border-slate-200 overflow-hidden">
|
|
||||||
{/* Image */}
|
|
||||||
<a className="relative block w-24 sm:w-56 lg:sidebar-expanded:w-20 xl:sidebar-expanded:w-56 shrink-0" href="#0">
|
|
||||||
<img
|
|
||||||
className="absolute object-cover object-center w-full h-full"
|
|
||||||
src={MeetupThumb}
|
|
||||||
width="220"
|
|
||||||
height="236"
|
|
||||||
alt="Meetup 02"
|
|
||||||
/>
|
|
||||||
{/* Like button */}
|
|
||||||
<button className="absolute top-0 right-0 mt-4 mr-4">
|
|
||||||
<div className="text-slate-100 bg-slate-900 bg-opacity-60 rounded-full">
|
|
||||||
<span className="sr-only">Like</span>
|
|
||||||
<svg className="h-8 w-8 fill-current" viewBox="0 0 32 32">
|
|
||||||
<path d="M22.682 11.318A4.485 4.485 0 0019.5 10a4.377 4.377 0 00-3.5 1.707A4.383 4.383 0 0012.5 10a4.5 4.5 0 00-3.182 7.682L16 24l6.682-6.318a4.5 4.5 0 000-6.364zm-1.4 4.933L16 21.247l-5.285-5A2.5 2.5 0 0112.5 12c1.437 0 2.312.681 3.5 2.625C17.187 12.681 18.062 12 19.5 12a2.5 2.5 0 011.785 4.251h-.003z" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
</a>
|
|
||||||
{/* Content */}
|
|
||||||
<div className="grow p-5 flex flex-col">
|
|
||||||
<div className='grow'>
|
|
||||||
<div className="text-sm font-semibold text-indigo-500 uppercase mb-2">Mon 27 Dec, 2021</div>
|
|
||||||
<a className="inline-flex mb-2" href="#0">
|
|
||||||
<h3 className="text-lg font-bold text-slate-800">New York & New Jersey Virtual Retreat 2021</h3>
|
|
||||||
</a>
|
|
||||||
<div className="text-sm">
|
|
||||||
Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/* Footer */}
|
|
||||||
<div className="flex justify-between mt-3">
|
|
||||||
{/* Tag */}
|
|
||||||
<div className="text-xs inline-flex items-center font-medium bg-slate-100 text-slate-600 rounded-full text-center px-2.5 py-1">
|
|
||||||
<svg className="w-4 h-3 fill-slate-400 mr-2" viewBox="0 0 16 12">
|
|
||||||
<path d="m16 2-4 2.4V2a2 2 0 0 0-2-2H2a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7.6l4 2.4V2ZM2 10V2h8v8H2Z" />
|
|
||||||
</svg>
|
|
||||||
<span>Online Event</span>
|
|
||||||
</div>
|
|
||||||
{/* Avatars */}
|
|
||||||
<div className="flex items-center space-x-2">
|
|
||||||
<div className="flex -space-x-3 -ml-0.5">
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar02} width="28" height="28" alt="User 02" />
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar03} width="28" height="28" alt="User 03" />
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar04} width="28" height="28" alt="User 04" />
|
|
||||||
</div>
|
|
||||||
<div className="text-xs font-medium text-slate-400 italic">+132</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</article>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Sidebar */}
|
|
||||||
<div className="space-y-4">
|
|
||||||
{/* 1st block */}
|
|
||||||
<div className="bg-white p-5 shadow-lg rounded-sm border border-slate-200 lg:w-72 xl:w-80">
|
|
||||||
<div className="space-y-2">
|
|
||||||
<button className="btn w-full bg-indigo-500 hover:bg-indigo-600 text-white">
|
|
||||||
<svg className="w-4 h-4 fill-current shrink-0" viewBox="0 0 16 16">
|
|
||||||
<path d="m2.457 8.516.969-.99 2.516 2.481 5.324-5.304.985.989-6.309 6.284z" />
|
|
||||||
</svg>
|
|
||||||
<span className="ml-1">Attending</span>
|
|
||||||
</button>
|
|
||||||
<button className="btn w-full border-slate-200 hover:border-slate-300 text-slate-600">
|
|
||||||
<svg className="w-4 h-4 fill-rose-500 shrink-0" viewBox="0 0 16 16">
|
|
||||||
<path d="M14.682 2.318A4.485 4.485 0 0 0 11.5 1 4.377 4.377 0 0 0 8 2.707 4.383 4.383 0 0 0 4.5 1a4.5 4.5 0 0 0-3.182 7.682L8 15l6.682-6.318a4.5 4.5 0 0 0 0-6.364Zm-1.4 4.933L8 12.247l-5.285-5A2.5 2.5 0 0 1 4.5 3c1.437 0 2.312.681 3.5 2.625C9.187 3.681 10.062 3 11.5 3a2.5 2.5 0 0 1 1.785 4.251h-.003Z" />
|
|
||||||
</svg>
|
|
||||||
<span className="ml-2">Favorite</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 2nd block */}
|
|
||||||
<div className="bg-white p-5 shadow-lg rounded-sm border border-slate-200 lg:w-72 xl:w-80">
|
|
||||||
<div className="flex justify-between space-x-1 mb-5">
|
|
||||||
<div className="text-sm text-slate-800 font-semibold">Attendees (127)</div>
|
|
||||||
<a className="text-sm font-medium text-indigo-500 hover:text-indigo-600" href="#0">
|
|
||||||
View All
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<ul className="space-y-3">
|
|
||||||
<li>
|
|
||||||
<div className="flex justify-between">
|
|
||||||
<div className="grow flex items-center">
|
|
||||||
<div className="relative mr-3">
|
|
||||||
<img className="w-8 h-8 rounded-full" src={UserImage08} width="32" height="32" alt="User 08" />
|
|
||||||
</div>
|
|
||||||
<div className="truncate">
|
|
||||||
<span className="text-sm font-medium text-slate-800">Carolyn McNeail</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button className="text-slate-400 hover:text-slate-500 rounded-full">
|
|
||||||
<span className="sr-only">Menu</span>
|
|
||||||
<svg className="w-8 h-8 fill-current" viewBox="0 0 32 32">
|
|
||||||
<circle cx="16" cy="16" r="2" />
|
|
||||||
<circle cx="10" cy="16" r="2" />
|
|
||||||
<circle cx="22" cy="16" r="2" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<div className="flex justify-between">
|
|
||||||
<div className="grow flex items-center">
|
|
||||||
<div className="relative mr-3">
|
|
||||||
<img className="w-8 h-8 rounded-full" src={UserImage01} width="32" height="32" alt="User 01" />
|
|
||||||
</div>
|
|
||||||
<div className="truncate">
|
|
||||||
<span className="text-sm font-medium text-slate-800">Dominik Lamakani</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button className="text-slate-400 hover:text-slate-500 rounded-full">
|
|
||||||
<span className="sr-only">Menu</span>
|
|
||||||
<svg className="w-8 h-8 fill-current" viewBox="0 0 32 32">
|
|
||||||
<circle cx="16" cy="16" r="2" />
|
|
||||||
<circle cx="10" cy="16" r="2" />
|
|
||||||
<circle cx="22" cy="16" r="2" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<div className="flex justify-between">
|
|
||||||
<div className="grow flex items-center">
|
|
||||||
<div className="relative mr-3">
|
|
||||||
<img className="w-8 h-8 rounded-full" src={UserImage03} width="32" height="32" alt="User 03" />
|
|
||||||
</div>
|
|
||||||
<div className="truncate">
|
|
||||||
<span className="text-sm font-medium text-slate-800">Ivan Mesaros</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button className="text-slate-400 hover:text-slate-500 rounded-full">
|
|
||||||
<span className="sr-only">Menu</span>
|
|
||||||
<svg className="w-8 h-8 fill-current" viewBox="0 0 32 32">
|
|
||||||
<circle cx="16" cy="16" r="2" />
|
|
||||||
<circle cx="10" cy="16" r="2" />
|
|
||||||
<circle cx="22" cy="16" r="2" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<div className="flex justify-between">
|
|
||||||
<div className="grow flex items-center">
|
|
||||||
<div className="relative mr-3">
|
|
||||||
<img className="w-8 h-8 rounded-full" src={UserImage05} width="32" height="32" alt="User 05" />
|
|
||||||
</div>
|
|
||||||
<div className="truncate">
|
|
||||||
<span className="text-sm font-medium text-slate-800">Maria Martinez</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button className="text-slate-400 hover:text-slate-500 rounded-full">
|
|
||||||
<span className="sr-only">Menu</span>
|
|
||||||
<svg className="w-8 h-8 fill-current" viewBox="0 0 32 32">
|
|
||||||
<circle cx="16" cy="16" r="2" />
|
|
||||||
<circle cx="10" cy="16" r="2" />
|
|
||||||
<circle cx="22" cy="16" r="2" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 3rd block */}
|
|
||||||
<div className="bg-white p-5 shadow-lg rounded-sm border border-slate-200 lg:w-72 xl:w-80">
|
|
||||||
<div className="flex justify-between space-x-1 mb-5">
|
|
||||||
<div className="text-sm text-slate-800 font-semibold">Invite Friends</div>
|
|
||||||
<a className="text-sm font-medium text-indigo-500 hover:text-indigo-600" href="#0">
|
|
||||||
View All
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<ul className="space-y-3">
|
|
||||||
<li>
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<div className="grow flex items-center">
|
|
||||||
<div className="relative mr-3">
|
|
||||||
<img className="w-8 h-8 rounded-full" src={UserImage02} width="32" height="32" alt="User 02" />
|
|
||||||
</div>
|
|
||||||
<div className="truncate">
|
|
||||||
<span className="text-sm font-medium text-slate-800">Haruki Masuno</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button className="text-xs inline-flex font-medium bg-indigo-100 text-indigo-600 rounded-full text-center px-2.5 py-1">
|
|
||||||
Invite
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<div className="grow flex items-center">
|
|
||||||
<div className="relative mr-3">
|
|
||||||
<img className="w-8 h-8 rounded-full" src={UserImage04} width="32" height="32" alt="User 04" />
|
|
||||||
</div>
|
|
||||||
<div className="truncate">
|
|
||||||
<span className="text-sm font-medium text-slate-800">Joe Huang</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button className="text-xs inline-flex font-medium bg-indigo-100 text-indigo-600 rounded-full text-center px-2.5 py-1">
|
|
||||||
Invite
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<div className="grow flex items-center">
|
|
||||||
<div className="relative mr-3">
|
|
||||||
<img className="w-8 h-8 rounded-full" src={UserImage06} width="32" height="32" alt="User 06" />
|
|
||||||
</div>
|
|
||||||
<div className="truncate">
|
|
||||||
<span className="text-sm font-medium text-slate-800">Carolyn McNeail</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button className="text-xs inline-flex font-medium bg-indigo-100 text-indigo-600 rounded-full text-center px-2.5 py-1">
|
|
||||||
Invite
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<div className="grow flex items-center">
|
|
||||||
<div className="relative mr-3">
|
|
||||||
<img className="w-8 h-8 rounded-full" src={UserImage08} width="32" height="32" alt="User 08" />
|
|
||||||
</div>
|
|
||||||
<div className="truncate">
|
|
||||||
<span className="text-sm font-medium text-slate-800">Lisa Sitwala</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button className="text-xs inline-flex font-medium bg-indigo-100 text-indigo-600 rounded-full text-center px-2.5 py-1">
|
|
||||||
Invite
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default MeetupsPost;
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
|
|
||||||
import Sidebar from '../../partials/Sidebar';
|
|
||||||
import Header from '../../partials/Header';
|
|
||||||
import ProfileSidebar from '../../partials/community/ProfileSidebar';
|
|
||||||
import ProfileBody from '../../partials/community/ProfileBody';
|
|
||||||
|
|
||||||
function Profile() {
|
|
||||||
|
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
||||||
const [profileSidebarOpen, setProfileSidebarOpen] = useState(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex h-screen overflow-hidden">
|
|
||||||
|
|
||||||
{/* Sidebar */}
|
|
||||||
<Sidebar sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
{/* Content area */}
|
|
||||||
<div className="relative flex flex-col flex-1 overflow-y-auto overflow-x-hidden bg-white">
|
|
||||||
|
|
||||||
{/* Site header */}
|
|
||||||
<Header sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div className="relative flex">
|
|
||||||
|
|
||||||
{/* Profile sidebar */}
|
|
||||||
<ProfileSidebar profileSidebarOpen={profileSidebarOpen} setProfileSidebarOpen={setProfileSidebarOpen} />
|
|
||||||
|
|
||||||
{/* Profile body */}
|
|
||||||
<ProfileBody profileSidebarOpen={profileSidebarOpen} setProfileSidebarOpen={setProfileSidebarOpen} />
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Profile;
|
|
||||||
@@ -1,196 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
|
|
||||||
import Sidebar from '../../partials/Sidebar';
|
|
||||||
import Header from '../../partials/Header';
|
|
||||||
import SearchForm from '../../partials/actions/SearchForm';
|
|
||||||
import UsersTabsCard from '../../partials/community/UsersTabsCard';
|
|
||||||
import PaginationNumeric from '../../components/PaginationNumeric';
|
|
||||||
|
|
||||||
import Image01 from '../../images/user-64-01.jpg';
|
|
||||||
import Image02 from '../../images/user-64-02.jpg';
|
|
||||||
import Image03 from '../../images/user-64-03.jpg';
|
|
||||||
import Image04 from '../../images/user-64-04.jpg';
|
|
||||||
import Image05 from '../../images/user-64-05.jpg';
|
|
||||||
import Image06 from '../../images/user-64-06.jpg';
|
|
||||||
import Image07 from '../../images/user-64-07.jpg';
|
|
||||||
import Image08 from '../../images/user-64-08.jpg';
|
|
||||||
import Image09 from '../../images/user-64-09.jpg';
|
|
||||||
import Image10 from '../../images/user-64-10.jpg';
|
|
||||||
import Image11 from '../../images/user-64-11.jpg';
|
|
||||||
import Image12 from '../../images/user-64-12.jpg';
|
|
||||||
|
|
||||||
function UsersTabs() {
|
|
||||||
|
|
||||||
const items = [
|
|
||||||
{
|
|
||||||
id: 0,
|
|
||||||
name: 'Dominik McNeail',
|
|
||||||
image: Image01,
|
|
||||||
link: '#0',
|
|
||||||
location: '🇮🇹',
|
|
||||||
content: 'Fitness Fanatic, Design Enthusiast, Mentor, Meetup Organizer & PHP Lover.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: 'Ivan Mesaros',
|
|
||||||
image: Image02,
|
|
||||||
link: '#0',
|
|
||||||
location: '🇫🇷',
|
|
||||||
content: 'Fitness Fanatic, Design Enthusiast, Mentor, Meetup Organizer & PHP Lover.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: 'Tisha Yanchev',
|
|
||||||
image: Image03,
|
|
||||||
link: '#0',
|
|
||||||
location: '🇩🇪',
|
|
||||||
content: 'Fitness Fanatic, Design Enthusiast, Mentor, Meetup Organizer & PHP Lover.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
name: 'Sergio Gonnelli',
|
|
||||||
image: Image04,
|
|
||||||
link: '#0',
|
|
||||||
location: '🇮🇹',
|
|
||||||
content: 'Fitness Fanatic, Design Enthusiast, Mentor, Meetup Organizer & PHP Lover.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
name: 'Jerzy Wierzy',
|
|
||||||
image: Image05,
|
|
||||||
link: '#0',
|
|
||||||
location: '🇪🇸',
|
|
||||||
content: 'Fitness Fanatic, Design Enthusiast, Mentor, Meetup Organizer & PHP Lover.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
name: 'Mirko Grubisic',
|
|
||||||
image: Image06,
|
|
||||||
link: '#0',
|
|
||||||
location: '🇩🇪',
|
|
||||||
content: 'Fitness Fanatic, Design Enthusiast, Mentor, Meetup Organizer & PHP Lover.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 6,
|
|
||||||
name: 'Alisha Acharya',
|
|
||||||
image: Image07,
|
|
||||||
link: '#0',
|
|
||||||
location: '🇬🇧',
|
|
||||||
content: 'Fitness Fanatic, Design Enthusiast, Mentor, Meetup Organizer & PHP Lover.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 7,
|
|
||||||
name: 'Brian Halligan',
|
|
||||||
image: Image08,
|
|
||||||
link: '#0',
|
|
||||||
location: '🇺🇸',
|
|
||||||
content: 'Fitness Fanatic, Design Enthusiast, Mentor, Meetup Organizer & PHP Lover.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 8,
|
|
||||||
name: 'Patricia Semklo',
|
|
||||||
image: Image09,
|
|
||||||
link: '#0',
|
|
||||||
location: '🇮🇳',
|
|
||||||
content: 'Fitness Fanatic, Design Enthusiast, Mentor, Meetup Organizer & PHP Lover.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 9,
|
|
||||||
name: 'Maria Martinez',
|
|
||||||
image: Image10,
|
|
||||||
link: '#0',
|
|
||||||
location: '🇮🇹',
|
|
||||||
content: 'Fitness Fanatic, Design Enthusiast, Mentor, Meetup Organizer & PHP Lover.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 10,
|
|
||||||
name: 'Vedad Siljak',
|
|
||||||
image: Image11,
|
|
||||||
link: '#0',
|
|
||||||
location: '🇮🇹🇨🇦',
|
|
||||||
content: 'Fitness Fanatic, Design Enthusiast, Mentor, Meetup Organizer & PHP Lover.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 11,
|
|
||||||
name: 'Dominik Lamakani',
|
|
||||||
image: Image12,
|
|
||||||
link: '#0',
|
|
||||||
location: '🇧🇪',
|
|
||||||
content: 'Fitness Fanatic, Design Enthusiast, Mentor, Meetup Organizer & PHP Lover.',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex h-screen overflow-hidden">
|
|
||||||
|
|
||||||
{/* Sidebar */}
|
|
||||||
<Sidebar sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
{/* Content area */}
|
|
||||||
<div className="relative flex flex-col flex-1 overflow-y-auto overflow-x-hidden">
|
|
||||||
|
|
||||||
{/* Site header */}
|
|
||||||
<Header sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div className="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
|
|
||||||
|
|
||||||
{/* Page header */}
|
|
||||||
<div className="sm:flex sm:justify-between sm:items-center mb-8">
|
|
||||||
|
|
||||||
{/* Left: Title */}
|
|
||||||
<div className="mb-4 sm:mb-0">
|
|
||||||
<h1 className="text-2xl md:text-3xl text-slate-800 font-bold">Acme Inc. ✨</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Right: Actions */}
|
|
||||||
<div className="grid grid-flow-col sm:auto-cols-max justify-start sm:justify-end gap-2">
|
|
||||||
{/* Search form */}
|
|
||||||
<SearchForm />
|
|
||||||
{/* Add member button */}
|
|
||||||
<button className="btn bg-indigo-500 hover:bg-indigo-600 text-white">
|
|
||||||
<svg className="w-4 h-4 fill-current opacity-50 shrink-0" viewBox="0 0 16 16">
|
|
||||||
<path d="M15 7H9V1c0-.6-.4-1-1-1S7 .4 7 1v6H1c-.6 0-1 .4-1 1s.4 1 1 1h6v6c0 .6.4 1 1 1s1-.4 1-1V9h6c.6 0 1-.4 1-1s-.4-1-1-1z" />
|
|
||||||
</svg>
|
|
||||||
<span className="hidden xs:block ml-2">Add Member</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Cards */}
|
|
||||||
<div className="grid grid-cols-12 gap-6">
|
|
||||||
{
|
|
||||||
items.map(item => {
|
|
||||||
return (
|
|
||||||
<UsersTabsCard
|
|
||||||
key={item.id}
|
|
||||||
id={item.id}
|
|
||||||
name={item.name}
|
|
||||||
image={item.image}
|
|
||||||
link={item.link}
|
|
||||||
location={item.location}
|
|
||||||
content={item.content}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Pagination */}
|
|
||||||
<div className="mt-8">
|
|
||||||
<PaginationNumeric />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default UsersTabs;
|
|
||||||
@@ -1,196 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
|
|
||||||
import Sidebar from '../../partials/Sidebar';
|
|
||||||
import Header from '../../partials/Header';
|
|
||||||
import SearchForm from '../../partials/actions/SearchForm';
|
|
||||||
import UsersTilesCard from '../../partials/community/UsersTilesCard';
|
|
||||||
import PaginationNumeric from '../../components/PaginationNumeric';
|
|
||||||
|
|
||||||
import Image01 from '../../images/user-64-01.jpg';
|
|
||||||
import Image02 from '../../images/user-64-02.jpg';
|
|
||||||
import Image03 from '../../images/user-64-03.jpg';
|
|
||||||
import Image04 from '../../images/user-64-04.jpg';
|
|
||||||
import Image05 from '../../images/user-64-05.jpg';
|
|
||||||
import Image06 from '../../images/user-64-06.jpg';
|
|
||||||
import Image07 from '../../images/user-64-07.jpg';
|
|
||||||
import Image08 from '../../images/user-64-08.jpg';
|
|
||||||
import Image09 from '../../images/user-64-09.jpg';
|
|
||||||
import Image10 from '../../images/user-64-10.jpg';
|
|
||||||
import Image11 from '../../images/user-64-11.jpg';
|
|
||||||
import Image12 from '../../images/user-64-12.jpg';
|
|
||||||
|
|
||||||
function UsersTiles() {
|
|
||||||
|
|
||||||
const items = [
|
|
||||||
{
|
|
||||||
id: 0,
|
|
||||||
name: 'Dominik McNeail',
|
|
||||||
image: Image01,
|
|
||||||
link: '#0',
|
|
||||||
location: '🇮🇹',
|
|
||||||
content: 'Fitness Fanatic, Design Enthusiast, Mentor, Meetup Organizer & PHP Lover.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: 'Ivan Mesaros',
|
|
||||||
image: Image02,
|
|
||||||
link: '#0',
|
|
||||||
location: '🇫🇷',
|
|
||||||
content: 'Fitness Fanatic, Design Enthusiast, Mentor, Meetup Organizer & PHP Lover.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: 'Tisha Yanchev',
|
|
||||||
image: Image03,
|
|
||||||
link: '#0',
|
|
||||||
location: '🇩🇪',
|
|
||||||
content: 'Fitness Fanatic, Design Enthusiast, Mentor, Meetup Organizer & PHP Lover.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
name: 'Sergio Gonnelli',
|
|
||||||
image: Image04,
|
|
||||||
link: '#0',
|
|
||||||
location: '🇮🇹',
|
|
||||||
content: 'Fitness Fanatic, Design Enthusiast, Mentor, Meetup Organizer & PHP Lover.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
name: 'Jerzy Wierzy',
|
|
||||||
image: Image05,
|
|
||||||
link: '#0',
|
|
||||||
location: '🇪🇸',
|
|
||||||
content: 'Fitness Fanatic, Design Enthusiast, Mentor, Meetup Organizer & PHP Lover.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
name: 'Mirko Grubisic',
|
|
||||||
image: Image06,
|
|
||||||
link: '#0',
|
|
||||||
location: '🇩🇪',
|
|
||||||
content: 'Fitness Fanatic, Design Enthusiast, Mentor, Meetup Organizer & PHP Lover.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 6,
|
|
||||||
name: 'Alisha Acharya',
|
|
||||||
image: Image07,
|
|
||||||
link: '#0',
|
|
||||||
location: '🇬🇧',
|
|
||||||
content: 'Fitness Fanatic, Design Enthusiast, Mentor, Meetup Organizer & PHP Lover.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 7,
|
|
||||||
name: 'Brian Halligan',
|
|
||||||
image: Image08,
|
|
||||||
link: '#0',
|
|
||||||
location: '🇺🇸',
|
|
||||||
content: 'Fitness Fanatic, Design Enthusiast, Mentor, Meetup Organizer & PHP Lover.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 8,
|
|
||||||
name: 'Patricia Semklo',
|
|
||||||
image: Image09,
|
|
||||||
link: '#0',
|
|
||||||
location: '🇮🇳',
|
|
||||||
content: 'Fitness Fanatic, Design Enthusiast, Mentor, Meetup Organizer & PHP Lover.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 9,
|
|
||||||
name: 'Maria Martinez',
|
|
||||||
image: Image10,
|
|
||||||
link: '#0',
|
|
||||||
location: '🇮🇹',
|
|
||||||
content: 'Fitness Fanatic, Design Enthusiast, Mentor, Meetup Organizer & PHP Lover.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 10,
|
|
||||||
name: 'Vedad Siljak',
|
|
||||||
image: Image11,
|
|
||||||
link: '#0',
|
|
||||||
location: '🇮🇹🇨🇦',
|
|
||||||
content: 'Fitness Fanatic, Design Enthusiast, Mentor, Meetup Organizer & PHP Lover.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 11,
|
|
||||||
name: 'Dominik Lamakani',
|
|
||||||
image: Image12,
|
|
||||||
link: '#0',
|
|
||||||
location: '🇧🇪',
|
|
||||||
content: 'Fitness Fanatic, Design Enthusiast, Mentor, Meetup Organizer & PHP Lover.',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex h-screen overflow-hidden">
|
|
||||||
|
|
||||||
{/* Sidebar */}
|
|
||||||
<Sidebar sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
{/* Content area */}
|
|
||||||
<div className="relative flex flex-col flex-1 overflow-y-auto overflow-x-hidden">
|
|
||||||
|
|
||||||
{/* Site header */}
|
|
||||||
<Header sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div className="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
|
|
||||||
|
|
||||||
{/* Page header */}
|
|
||||||
<div className="sm:flex sm:justify-between sm:items-center mb-8">
|
|
||||||
|
|
||||||
{/* Left: Title */}
|
|
||||||
<div className="mb-4 sm:mb-0">
|
|
||||||
<h1 className="text-2xl md:text-3xl text-slate-800 font-bold">Acme Inc. ✨</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Right: Actions */}
|
|
||||||
<div className="grid grid-flow-col sm:auto-cols-max justify-start sm:justify-end gap-2">
|
|
||||||
{/* Search form */}
|
|
||||||
<SearchForm />
|
|
||||||
{/* Add member button */}
|
|
||||||
<button className="btn bg-indigo-500 hover:bg-indigo-600 text-white">
|
|
||||||
<svg className="w-4 h-4 fill-current opacity-50 shrink-0" viewBox="0 0 16 16">
|
|
||||||
<path d="M15 7H9V1c0-.6-.4-1-1-1S7 .4 7 1v6H1c-.6 0-1 .4-1 1s.4 1 1 1h6v6c0 .6.4 1 1 1s1-.4 1-1V9h6c.6 0 1-.4 1-1s-.4-1-1-1z" />
|
|
||||||
</svg>
|
|
||||||
<span className="hidden xs:block ml-2">Add Member</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Cards */}
|
|
||||||
<div className="grid grid-cols-12 gap-6">
|
|
||||||
{
|
|
||||||
items.map(item => {
|
|
||||||
return (
|
|
||||||
<UsersTilesCard
|
|
||||||
key={item.id}
|
|
||||||
id={item.id}
|
|
||||||
name={item.name}
|
|
||||||
image={item.image}
|
|
||||||
link={item.link}
|
|
||||||
location={item.location}
|
|
||||||
content={item.content}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Pagination */}
|
|
||||||
<div className="mt-8">
|
|
||||||
<PaginationNumeric />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default UsersTiles;
|
|
||||||
@@ -1,151 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
|
|
||||||
import Sidebar from '../../partials/Sidebar';
|
|
||||||
import Header from '../../partials/Header';
|
|
||||||
import AccordionBasic from '../../components/AccordionBasic';
|
|
||||||
import AccordionTableItem from '../../components/AccordionTableItem';
|
|
||||||
import AccordionTableRichItem from '../../components/AccordionTableRichItem';
|
|
||||||
|
|
||||||
import Image01 from '../../images/user-40-07.jpg';
|
|
||||||
|
|
||||||
function AccordionPage() {
|
|
||||||
|
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
||||||
|
|
||||||
const items = [
|
|
||||||
{
|
|
||||||
id: '0',
|
|
||||||
image: Image01,
|
|
||||||
customer: 'Mark Cameron',
|
|
||||||
total: '$129.00',
|
|
||||||
status: 'Refunded',
|
|
||||||
items: '1',
|
|
||||||
location: '🇲🇽 New Mexico, MX',
|
|
||||||
type: 'Subscription',
|
|
||||||
description: 'Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const items2 = [
|
|
||||||
{
|
|
||||||
id: '0',
|
|
||||||
image: Image01,
|
|
||||||
customer: 'Mark Cameron',
|
|
||||||
email: 'mark.cameron@app.com',
|
|
||||||
location: '🇬🇧 London, UK',
|
|
||||||
date: '22/01/2021',
|
|
||||||
amount: '+249.88',
|
|
||||||
descriptionTitle: 'Excepteur sint occaecat cupidatat.',
|
|
||||||
descriptionBody: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam quis. Ut enim ad minim veniam quis. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex h-screen overflow-hidden">
|
|
||||||
|
|
||||||
{/* Sidebar */}
|
|
||||||
<Sidebar sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
{/* Content area */}
|
|
||||||
<div className="relative flex flex-col flex-1 overflow-y-auto overflow-x-hidden bg-white">
|
|
||||||
|
|
||||||
{/* Site header */}
|
|
||||||
<Header sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div className="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
|
|
||||||
|
|
||||||
{/* Page header */}
|
|
||||||
<div className="mb-8">
|
|
||||||
<h1 className="text-2xl md:text-3xl text-slate-800 font-bold">Accordion ✨</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="border-t border-slate-200">
|
|
||||||
|
|
||||||
{/* Components */}
|
|
||||||
<div className="space-y-8 mt-8">
|
|
||||||
|
|
||||||
{/* Basic Accordion */}
|
|
||||||
<div>
|
|
||||||
<h2 className="text-2xl text-slate-800 font-bold mb-6">Basic Accordion</h2>
|
|
||||||
<AccordionBasic title="Accordion Title">
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam quis. Ut enim ad minim veniam quis. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
|
||||||
</AccordionBasic>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Table Row with Accordion */}
|
|
||||||
<div>
|
|
||||||
<h2 className="text-2xl text-slate-800 font-bold mb-6">Table Row with Accordion</h2>
|
|
||||||
{/* Start */}
|
|
||||||
<div className="rounded-sm border border-slate-200">
|
|
||||||
<div className="overflow-x-auto">
|
|
||||||
<table className="table-auto w-full divide-y divide-slate-200">
|
|
||||||
{
|
|
||||||
items.map(item => {
|
|
||||||
return (
|
|
||||||
<AccordionTableItem
|
|
||||||
key={item.id}
|
|
||||||
id={item.id}
|
|
||||||
image={item.image}
|
|
||||||
customer={item.customer}
|
|
||||||
total={item.total}
|
|
||||||
status={item.status}
|
|
||||||
items={item.items}
|
|
||||||
location={item.location}
|
|
||||||
type={item.type}
|
|
||||||
description={item.description}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/* End */}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Rich Table Row with Accordion */}
|
|
||||||
<div>
|
|
||||||
<h2 className="text-2xl text-slate-800 font-bold mb-6">Rich Table Row with Accordion</h2>
|
|
||||||
{/* Start */}
|
|
||||||
<div className="rounded-sm border border-slate-200">
|
|
||||||
<div className="overflow-x-auto">
|
|
||||||
<table className="table-auto w-full divide-y divide-slate-200">
|
|
||||||
{
|
|
||||||
items2.map(item => {
|
|
||||||
return (
|
|
||||||
<AccordionTableRichItem
|
|
||||||
key={item.id}
|
|
||||||
id={item.id}
|
|
||||||
image={item.image}
|
|
||||||
customer={item.customer}
|
|
||||||
email={item.email}
|
|
||||||
location={item.location}
|
|
||||||
date={item.date}
|
|
||||||
amount={item.amount}
|
|
||||||
descriptionTitle={item.descriptionTitle}
|
|
||||||
descriptionBody={item.descriptionBody}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/* End */}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AccordionPage;
|
|
||||||
@@ -1,226 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
|
|
||||||
import Sidebar from '../../partials/Sidebar';
|
|
||||||
import Header from '../../partials/Header';
|
|
||||||
import Banner from '../../components/Banner';
|
|
||||||
import Banner2 from '../../components/Banner2';
|
|
||||||
import Toast from '../../components/Toast';
|
|
||||||
import Toast2 from '../../components/Toast2';
|
|
||||||
import Toast3 from '../../components/Toast3';
|
|
||||||
import Notification from '../../components/Notification';
|
|
||||||
|
|
||||||
function AlertPage() {
|
|
||||||
|
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
||||||
const [bannerWarningOpen, setBannerWarningOpen] = useState(true);
|
|
||||||
const [bannerErrorOpen, setBannerErrorOpen] = useState(true);
|
|
||||||
const [bannerSuccessOpen, setBannerSuccessOpen] = useState(true);
|
|
||||||
const [bannerInfoOpen, setBannerInfoOpen] = useState(true);
|
|
||||||
const [banner2WarningOpen, setBanner2WarningOpen] = useState(true);
|
|
||||||
const [banner2ErrorOpen, setBanner2ErrorOpen] = useState(true);
|
|
||||||
const [banner2SuccessOpen, setBanner2SuccessOpen] = useState(true);
|
|
||||||
const [banner2InfoOpen, setBanner2InfoOpen] = useState(true);
|
|
||||||
const [toastWarningOpen, setToastWarningOpen] = useState(true);
|
|
||||||
const [toastErrorOpen, setToastErrorOpen] = useState(true);
|
|
||||||
const [toastSuccessOpen, setToastSuccessOpen] = useState(true);
|
|
||||||
const [toastInfoOpen, setToastInfoOpen] = useState(true);
|
|
||||||
const [toast2WarningOpen, setToast2WarningOpen] = useState(true);
|
|
||||||
const [toast2ErrorOpen, setToast2ErrorOpen] = useState(true);
|
|
||||||
const [toast2SuccessOpen, setToast2SuccessOpen] = useState(true);
|
|
||||||
const [toast2InfoOpen, setToast2InfoOpen] = useState(true);
|
|
||||||
const [toast3WarningOpen, setToast3WarningOpen] = useState(true);
|
|
||||||
const [toast3ErrorOpen, setToast3ErrorOpen] = useState(true);
|
|
||||||
const [toast3SuccessOpen, setToast3SuccessOpen] = useState(true);
|
|
||||||
const [toast3InfoOpen, setToast3InfoOpen] = useState(true);
|
|
||||||
const [notificationWarningOpen, setNotificationWarningOpen] = useState(true);
|
|
||||||
const [notificationErrorOpen, setNotificationErrorOpen] = useState(true);
|
|
||||||
const [notificationSuccessOpen, setNotificationSuccessOpen] = useState(true);
|
|
||||||
const [notificationInfoOpen, setNotificationInfoOpen] = useState(true);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex h-screen overflow-hidden">
|
|
||||||
|
|
||||||
{/* Sidebar */}
|
|
||||||
<Sidebar sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
{/* Content area */}
|
|
||||||
<div className="relative flex flex-col flex-1 overflow-y-auto overflow-x-hidden bg-white">
|
|
||||||
|
|
||||||
{/* Site header */}
|
|
||||||
<Header sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div className="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
|
|
||||||
|
|
||||||
{/* Page header */}
|
|
||||||
<div className="mb-8">
|
|
||||||
<h1 className="text-2xl md:text-3xl text-slate-800 font-bold">Alert & Banner ✨</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="border-t border-slate-200">
|
|
||||||
|
|
||||||
{/* Components */}
|
|
||||||
<div className="space-y-8 mt-8">
|
|
||||||
|
|
||||||
{/* Banner */}
|
|
||||||
<div>
|
|
||||||
<h2 className="text-2xl text-slate-800 font-bold mb-6">Banner</h2>
|
|
||||||
<div className="space-y-3">
|
|
||||||
|
|
||||||
<Banner type="warning" open={bannerWarningOpen} setOpen={setBannerWarningOpen}>
|
|
||||||
We’re currently experiencing an increase in inquiries. There may be a delay in responses from the Support.
|
|
||||||
</Banner>
|
|
||||||
|
|
||||||
<Banner type="success" open={bannerSuccessOpen} setOpen={setBannerSuccessOpen}>
|
|
||||||
We’re currently experiencing an increase in inquiries. There may be a delay in responses from the Support.
|
|
||||||
</Banner>
|
|
||||||
|
|
||||||
<Banner type="error" open={bannerErrorOpen} setOpen={setBannerErrorOpen}>
|
|
||||||
We’re currently experiencing an increase in inquiries. There may be a delay in responses from the Support.
|
|
||||||
</Banner>
|
|
||||||
|
|
||||||
<Banner open={bannerInfoOpen} setOpen={setBannerInfoOpen}>
|
|
||||||
We’re currently experiencing an increase in inquiries. There may be a delay in responses from the Support.
|
|
||||||
</Banner>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Banner 2 */}
|
|
||||||
<div>
|
|
||||||
<h2 className="text-2xl text-slate-800 font-bold mb-6">Banner 2</h2>
|
|
||||||
<div className="space-y-3">
|
|
||||||
|
|
||||||
<Banner2 type="warning" open={banner2WarningOpen} setOpen={setBanner2WarningOpen}>
|
|
||||||
We’re currently experiencing an increase in inquiries. There may be a delay in responses from the Support.
|
|
||||||
</Banner2>
|
|
||||||
|
|
||||||
<Banner2 type="success" open={banner2SuccessOpen} setOpen={setBanner2SuccessOpen}>
|
|
||||||
We’re currently experiencing an increase in inquiries. There may be a delay in responses from the Support.
|
|
||||||
</Banner2>
|
|
||||||
|
|
||||||
<Banner2 type="error" open={banner2ErrorOpen} setOpen={setBanner2ErrorOpen}>
|
|
||||||
We’re currently experiencing an increase in inquiries. There may be a delay in responses from the Support.
|
|
||||||
</Banner2>
|
|
||||||
|
|
||||||
<Banner2 open={banner2InfoOpen} setOpen={setBanner2InfoOpen}>
|
|
||||||
We’re currently experiencing an increase in inquiries. There may be a delay in responses from the Support.
|
|
||||||
</Banner2>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Toast */}
|
|
||||||
<div>
|
|
||||||
<h2 className="text-2xl text-slate-800 font-bold mb-6">Toast</h2>
|
|
||||||
<div className="space-y-3">
|
|
||||||
|
|
||||||
<Toast type="warning" open={toastWarningOpen} setOpen={setToastWarningOpen}>
|
|
||||||
A warning toast.
|
|
||||||
</Toast>
|
|
||||||
|
|
||||||
<Toast type="success" open={toastSuccessOpen} setOpen={setToastSuccessOpen}>
|
|
||||||
A successful toast.
|
|
||||||
</Toast>
|
|
||||||
|
|
||||||
<Toast type="error" open={toastErrorOpen} setOpen={setToastErrorOpen}>
|
|
||||||
A dangerous toast.
|
|
||||||
</Toast>
|
|
||||||
|
|
||||||
<Toast open={toastInfoOpen} setOpen={setToastInfoOpen}>
|
|
||||||
An informational toast.
|
|
||||||
</Toast>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Toast 2 */}
|
|
||||||
<div>
|
|
||||||
<h2 className="text-2xl text-slate-800 font-bold mb-6">Toast 2</h2>
|
|
||||||
<div className="space-y-3">
|
|
||||||
|
|
||||||
<Toast2 type="warning" open={toast2WarningOpen} setOpen={setToast2WarningOpen}>
|
|
||||||
A warning toast.
|
|
||||||
</Toast2>
|
|
||||||
|
|
||||||
<Toast2 type="success" open={toast2SuccessOpen} setOpen={setToast2SuccessOpen}>
|
|
||||||
A successful toast.
|
|
||||||
</Toast2>
|
|
||||||
|
|
||||||
<Toast2 type="error" open={toast2ErrorOpen} setOpen={setToast2ErrorOpen}>
|
|
||||||
A dangerous toast.
|
|
||||||
</Toast2>
|
|
||||||
|
|
||||||
<Toast2 open={toast2InfoOpen} setOpen={setToast2InfoOpen}>
|
|
||||||
An informational toast.
|
|
||||||
</Toast2>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Toast 3 */}
|
|
||||||
<div>
|
|
||||||
<h2 className="text-2xl text-slate-800 font-bold mb-6">Toast 3</h2>
|
|
||||||
<div className="space-y-3">
|
|
||||||
|
|
||||||
<Toast3 type="warning" open={toast3WarningOpen} setOpen={setToast3WarningOpen}>
|
|
||||||
A warning toast.
|
|
||||||
</Toast3>
|
|
||||||
|
|
||||||
<Toast3 type="success" open={toast3SuccessOpen} setOpen={setToast3SuccessOpen}>
|
|
||||||
A successful toast.
|
|
||||||
</Toast3>
|
|
||||||
|
|
||||||
<Toast3 type="error" open={toast3ErrorOpen} setOpen={setToast3ErrorOpen}>
|
|
||||||
A dangerous toast.
|
|
||||||
</Toast3>
|
|
||||||
|
|
||||||
<Toast3 open={toast3InfoOpen} setOpen={setToast3InfoOpen}>
|
|
||||||
An informational toast.
|
|
||||||
</Toast3>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Notification */}
|
|
||||||
<div>
|
|
||||||
<h2 className="text-2xl text-slate-800 font-bold mb-6">Notification</h2>
|
|
||||||
<div className="space-y-3">
|
|
||||||
|
|
||||||
<Notification type="warning" open={notificationWarningOpen} setOpen={setNotificationWarningOpen}>
|
|
||||||
<div className="font-medium text-slate-800 mb-1">Merged Pull Request</div>
|
|
||||||
<div>Lorem ipsum dolor sit amet, consectetur adipiscing sed do eiusmod tempor incididunt ut labore et dolore.</div>
|
|
||||||
</Notification>
|
|
||||||
|
|
||||||
<Notification type="success" open={notificationSuccessOpen} setOpen={setNotificationSuccessOpen}>
|
|
||||||
<div className="font-medium text-slate-800 mb-1">Merged Pull Request</div>
|
|
||||||
<div>Lorem ipsum dolor sit amet, consectetur adipiscing sed do eiusmod tempor incididunt ut labore et dolore.</div>
|
|
||||||
</Notification>
|
|
||||||
|
|
||||||
<Notification type="error" open={notificationErrorOpen} setOpen={setNotificationErrorOpen}>
|
|
||||||
<div className="font-medium text-slate-800 mb-1">Merged Pull Request</div>
|
|
||||||
<div>Lorem ipsum dolor sit amet, consectetur adipiscing sed do eiusmod tempor incididunt ut labore et dolore.</div>
|
|
||||||
</Notification>
|
|
||||||
|
|
||||||
<Notification open={notificationInfoOpen} setOpen={setNotificationInfoOpen}>
|
|
||||||
<div className="font-medium text-slate-800 mb-1">Merged Pull Request</div>
|
|
||||||
<div>Lorem ipsum dolor sit amet, consectetur adipiscing sed do eiusmod tempor incididunt ut labore et dolore.</div>
|
|
||||||
</Notification>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AlertPage;
|
|
||||||
@@ -1,228 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
|
|
||||||
import Sidebar from '../../partials/Sidebar';
|
|
||||||
import Header from '../../partials/Header';
|
|
||||||
|
|
||||||
import Avatar01 from '../../images/avatar-01.jpg';
|
|
||||||
import Avatar02 from '../../images/avatar-02.jpg';
|
|
||||||
import Avatar03 from '../../images/avatar-03.jpg';
|
|
||||||
import Avatar04 from '../../images/avatar-04.jpg';
|
|
||||||
import Avatar05 from '../../images/avatar-05.jpg';
|
|
||||||
import Avatar06 from '../../images/avatar-06.jpg';
|
|
||||||
|
|
||||||
function AvatarPage() {
|
|
||||||
|
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex h-screen overflow-hidden">
|
|
||||||
|
|
||||||
{/* Sidebar */}
|
|
||||||
<Sidebar sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
{/* Content area */}
|
|
||||||
<div className="relative flex flex-col flex-1 overflow-y-auto overflow-x-hidden bg-white">
|
|
||||||
|
|
||||||
{/* Site header */}
|
|
||||||
<Header sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div className="px-4 sm:px-6 lg:px-8 py-8 w-full max-w-9xl mx-auto">
|
|
||||||
|
|
||||||
{/* Page header */}
|
|
||||||
<div className="mb-8">
|
|
||||||
<h1 className="text-2xl md:text-3xl text-slate-800 font-bold">Avatar ✨</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="border-t border-slate-200">
|
|
||||||
|
|
||||||
{/* Components */}
|
|
||||||
<div className="space-y-8 mt-8">
|
|
||||||
|
|
||||||
{/* Basic Avatars */}
|
|
||||||
<div>
|
|
||||||
<h2 className="text-2xl text-slate-800 font-bold mb-6">Basic Avatars</h2>
|
|
||||||
<div className="flex flex-wrap items-center -m-1.5">
|
|
||||||
<div className="m-1.5">
|
|
||||||
{/* Start */}
|
|
||||||
<img className="rounded-full" src={Avatar01} width="24" height="24" alt="Avatar" />
|
|
||||||
{/* End */}
|
|
||||||
</div>
|
|
||||||
<div className="m-1.5">
|
|
||||||
{/* Start */}
|
|
||||||
<img className="rounded-full" src={Avatar01} width="28" height="28" alt="Avatar" />
|
|
||||||
{/* End */}
|
|
||||||
</div>
|
|
||||||
<div className="m-1.5">
|
|
||||||
{/* Start */}
|
|
||||||
<img className="rounded-full" src={Avatar01} width="32" height="32" alt="Avatar" />
|
|
||||||
{/* End */}
|
|
||||||
</div>
|
|
||||||
<div className="m-1.5">
|
|
||||||
{/* Start */}
|
|
||||||
<img className="rounded-full" src={Avatar01} width="40" height="40" alt="Avatar" />
|
|
||||||
{/* End */}
|
|
||||||
</div>
|
|
||||||
<div className="m-1.5">
|
|
||||||
{/* Start */}
|
|
||||||
<img className="rounded-full" src={Avatar01} width="64" height="64" alt="Avatar" />
|
|
||||||
{/* End */}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Avatars with Notification */}
|
|
||||||
<div>
|
|
||||||
<h2 className="text-2xl text-slate-800 font-bold mb-6">Avatars with Notification</h2>
|
|
||||||
<div className="flex flex-wrap items-center -m-1.5">
|
|
||||||
<div className="m-1.5">
|
|
||||||
{/* Start */}
|
|
||||||
<div className="relative">
|
|
||||||
<img className="rounded-full" src={Avatar01} width="24" height="24" alt="Avatar" />
|
|
||||||
<div className="absolute top-0 right-0 w-2 h-2 bg-rose-500 border-2 border-white rounded-full"></div>
|
|
||||||
</div>
|
|
||||||
{/* End */}
|
|
||||||
</div>
|
|
||||||
<div className="m-1.5">
|
|
||||||
{/* Start */}
|
|
||||||
<div className="relative">
|
|
||||||
<img className="rounded-full" src={Avatar01} width="28" height="28" alt="Avatar" />
|
|
||||||
<div className="absolute top-0 right-0 w-2.5 h-2.5 bg-emerald-500 border-2 border-white rounded-full"></div>
|
|
||||||
</div>
|
|
||||||
{/* End */}
|
|
||||||
</div>
|
|
||||||
<div className="m-1.5">
|
|
||||||
{/* Start */}
|
|
||||||
<div className="relative">
|
|
||||||
<img className="rounded-full" src={Avatar01} width="32" height="32" alt="Avatar" />
|
|
||||||
<div className="absolute top-0 right-0 w-2.5 h-2.5 bg-rose-500 border-2 border-white rounded-full"></div>
|
|
||||||
</div>
|
|
||||||
{/* End */}
|
|
||||||
</div>
|
|
||||||
<div className="m-1.5">
|
|
||||||
{/* Start */}
|
|
||||||
<div className="relative">
|
|
||||||
<img className="rounded-full" src={Avatar01} width="40" height="40" alt="Avatar" />
|
|
||||||
<div className="absolute top-0 right-0 w-3 h-3 bg-emerald-500 border-2 border-white rounded-full"></div>
|
|
||||||
</div>
|
|
||||||
{/* End */}
|
|
||||||
</div>
|
|
||||||
<div className="m-1.5">
|
|
||||||
{/* Start */}
|
|
||||||
<div className="relative">
|
|
||||||
<img className="rounded-full" src={Avatar01} width="64" height="64" alt="Avatar" />
|
|
||||||
<div className="absolute top-1 right-1 w-3 h-3 bg-rose-500 border-2 border-white rounded-full"></div>
|
|
||||||
</div>
|
|
||||||
{/* End */}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Avatars with Placeholder Icon */}
|
|
||||||
<div>
|
|
||||||
<h2 className="text-2xl text-slate-800 font-bold mb-6">Avatars with Placeholder Icon</h2>
|
|
||||||
<div className="flex flex-wrap items-center -m-1.5">
|
|
||||||
<div className="m-1.5">
|
|
||||||
{/* Start */}
|
|
||||||
<div className="flex items-center justify-center bg-slate-100 rounded-full w-6 h-6 text-[10px] font-semibold uppercase text-slate-500">MS</div>
|
|
||||||
{/* End */}
|
|
||||||
</div>
|
|
||||||
<div className="m-1.5">
|
|
||||||
{/* Start */}
|
|
||||||
<div className="flex items-center justify-center bg-slate-100 rounded-full w-7 h-7 text-[10px] font-semibold uppercase text-slate-500">MS</div>
|
|
||||||
{/* End */}
|
|
||||||
</div>
|
|
||||||
<div className="m-1.5">
|
|
||||||
{/* Start */}
|
|
||||||
<div className="flex items-center justify-center bg-slate-100 rounded-full w-8 h-8 text-xs font-semibold uppercase text-slate-500">MS</div>
|
|
||||||
{/* End */}
|
|
||||||
</div>
|
|
||||||
<div className="m-1.5">
|
|
||||||
{/* Start */}
|
|
||||||
<div className="flex items-center justify-center bg-slate-100 rounded-full w-10 h-10 text-sm font-semibold uppercase text-slate-500">MS</div>
|
|
||||||
{/* End */}
|
|
||||||
</div>
|
|
||||||
<div className="m-1.5">
|
|
||||||
{/* Start */}
|
|
||||||
<div className="flex items-center justify-center bg-slate-100 rounded-full w-16 h-16 text-lg font-semibold uppercase text-slate-500">MS</div>
|
|
||||||
{/* End */}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Avatars Groups */}
|
|
||||||
<div>
|
|
||||||
<h2 className="text-2xl text-slate-800 font-bold mb-6">Avatars Groups</h2>
|
|
||||||
<div className="flex flex-wrap items-center -m-1.5">
|
|
||||||
<div className="m-1.5">
|
|
||||||
{/* Start */}
|
|
||||||
<div className="flex -space-x-3 -ml-0.5">
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar02} width="24" height="24" alt="Avatar" />
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar03} width="24" height="24" alt="Avatar" />
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar04} width="24" height="24" alt="Avatar" />
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar05} width="24" height="24" alt="Avatar" />
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar06} width="24" height="24" alt="Avatar" />
|
|
||||||
</div>
|
|
||||||
{/* End */}
|
|
||||||
</div>
|
|
||||||
<div className="m-1.5">
|
|
||||||
{/* Start */}
|
|
||||||
<div className="flex -space-x-3 -ml-0.5">
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar02} width="28" height="28" alt="Avatar" />
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar03} width="28" height="28" alt="Avatar" />
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar04} width="28" height="28" alt="Avatar" />
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar05} width="28" height="28" alt="Avatar" />
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar06} width="28" height="28" alt="Avatar" />
|
|
||||||
</div>
|
|
||||||
{/* End */}
|
|
||||||
</div>
|
|
||||||
<div className="m-1.5">
|
|
||||||
{/* Start */}
|
|
||||||
<div className="flex -space-x-3 -ml-0.5">
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar02} width="32" height="32" alt="Avatar" />
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar03} width="32" height="32" alt="Avatar" />
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar04} width="32" height="32" alt="Avatar" />
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar05} width="32" height="32" alt="Avatar" />
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar06} width="32" height="32" alt="Avatar" />
|
|
||||||
</div>
|
|
||||||
{/* End */}
|
|
||||||
</div>
|
|
||||||
<div className="m-1.5">
|
|
||||||
{/* Start */}
|
|
||||||
<div className="flex -space-x-4 -ml-0.5">
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar02} width="40" height="40" alt="Avatar" />
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar03} width="40" height="40" alt="Avatar" />
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar04} width="40" height="40" alt="Avatar" />
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar05} width="40" height="40" alt="Avatar" />
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar06} width="40" height="40" alt="Avatar" />
|
|
||||||
</div>
|
|
||||||
{/* End */}
|
|
||||||
</div>
|
|
||||||
<div className="m-1.5">
|
|
||||||
{/* Start */}
|
|
||||||
<div className="flex -space-x-7 -ml-0.5">
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar02} width="64" height="64" alt="Avatar" />
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar03} width="64" height="64" alt="Avatar" />
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar04} width="64" height="64" alt="Avatar" />
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar05} width="64" height="64" alt="Avatar" />
|
|
||||||
<img className="rounded-full border-2 border-white box-content" src={Avatar06} width="64" height="64" alt="Avatar" />
|
|
||||||
</div>
|
|
||||||
{/* End */}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AvatarPage;
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user