Commit d87f28c1 authored by Sachin Kodagoda's avatar Sachin Kodagoda

main stream updated

parent 9242e32b
No preview for this file type
// .babelrc
{
"presets": ["next/babel"],
"plugins": []
}
node_modules
__generated__
next.config.js
{
"root": true,
"env": {
"browser": true,
"es6": true,
"node": true,
"jest": true
},
"parser": "@typescript-eslint/parser",
"parserOptions": {
"tsconfigRootDir": ".",
"project": "./tsconfig.json", // for sepecial path to work
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 12,
"sourceType": "module"
},
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"extends": [
"next",
"next/core-web-vitals",
"airbnb",
"eslint:recommended",
"plugin:import/recommended",
"plugin:import/typescript",
"plugin:react/recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended",
"prettier"
],
"plugins": ["react", "prettier", "@typescript-eslint", "react-hooks", "sort-destructure-keys", "json"],
"rules": {
"no-console": "warn",
"react/react-in-jsx-scope": "off", // next js handles it
"no-use-before-define": "off", // Because of Hoisting
// JSON - [FACEPALM] had to list all props to simulate 'recommended'
// as overriding doesn't work :(
// More info - https://www.npmjs.com/package/eslint-plugin-json
"json/undefined": "error",
"json/enum-value-mismatch": "error",
"json/unexpected-end-of-comment": "error",
"json/unexpected-end-of-string": "error",
"json/unexpected-end-of-number": "error",
"json/invalid-unicode": "error",
"json/invalid-escape-character": "error",
"json/invalid-character": "error",
"json/property-expected": "error",
"json/comma-expected": "error",
"json/colon-expected": "error",
"json/value-expected": "error",
"json/comma-or-close-backet-expected": "error",
"json/comma-or-close-brace-expected": "error",
"json/trailing-comma": 1,
"json/duplicate-key": "error",
"json/comment-not-permitted": "error",
"json/schema-resolve-error": "error",
"json/unknown": 1,
"import/no-extraneous-dependencies": [
"error",
{ "devDependencies": false, "optionalDependencies": false, "peerDependencies": false }
],
// So that .ts and .tsx should not be in imports
"import/extensions": [
"error",
{
"json": "always",
"ts": "never",
"tsx": "never",
"css": "always"
}
],
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
// So that Type Definitions which have /// don't throw an error
"spaced-comment": ["error", "always", { "markers": ["/"] }],
// So that typescript files can't have JSX
"react/jsx-filename-extension": [1, { "extensions": [".tsx"] }],
"@typescript-eslint/naming-convention": [
"error",
{
"selector": "interface",
"format": ["PascalCase"],
"custom": {
"regex": "^I[A-Z][a-zA-Z0-9]+$",
"match": true
}
},
{
"selector": "typeAlias",
"format": ["PascalCase"],
"custom": {
"regex": "^T[A-Z][a-zA-Z0-9]+$",
"match": true
}
}
],
"import/prefer-default-export": "off",
"sort-destructure-keys/sort-destructure-keys": 2,
"sort-keys": [0, "asc", { "natural": true, "minKeys": 3 }], // For later
"react/require-default-props": 0,
"@typescript-eslint/no-use-before-define": 0,
"@typescript-eslint/camelcase": 0, // Turn this on later, airbnb hadn't updated this yet
"camelcase": [0, { "properties": "always" }],
// Disable base rule as it can report incorrect errors https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-shadow.md#how-to-use
"no-shadow": "off",
"@typescript-eslint/no-shadow": ["error"],
"@next/next/no-img-element": "off"
},
"settings": {
"import/parsers": {
"@typescript-eslint/parser": [".ts", ".tsx"]
},
"import/resolver": {
"typescript": {
"alwaysTryTypes": true,
"project": "./tsconfig.json"
}
}
}
}
name: ci
on:
push:
branches:
- main
- master
pull_request:
branches:
- main
- master
jobs:
ci:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
node: [15]
steps:
- name: Checkout
uses: actions/checkout@master
- name: Setup node env
uses: actions/setup-node@v2.1.2
with:
node-version: ${{ matrix.node }}
- name: Cache node_modules
uses: actions/cache@v2
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Install dependencies
run: yarn
- name: Run code style check
run: yarn da:all
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
# yarn lint
yarn da:all
node_modules
__generated__
.next
{
"arrowParens": "avoid",
"jsxBracketSameLine": true,
"jsxSingleQuote": true,
"printWidth": 120,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5"
}
{
"recommendations": [
"blanu.vscode-styled-jsx",
"coenraads.bracket-pair-colorizer-2",
"dbaeumer.vscode-eslint",
"dzannotti.vscode-babel-coloring",
"jpoissonnier.vscode-styled-components",
"qcz.text-power-tools"
],
"unwantedRecommendations": [
"esbenp.prettier-vscode",
"ms-vscode.vscode-typescript-tslint-plugin"
]
}
{
"search.exclude": {
"**/.dev_assets/**": true,
"**/.git/**": true,
"**/.github/**": true,
"**/.next/**": true,
"**/.vscode/**": true,
"**/build/**": true,
"**/node_modules/**": true
},
"files.watcherExclude": {
"**/.dev_assets/**": true,
"**/.git/**": true,
"**/.github/**": true,
"**/.next/**": true,
"**/.vscode/**": true,
"**/build/**": true,
"**/node_modules/**": true
},
"cSpell.words": [
"Abinaya",
"Kumarasinghe",
"Thilina",
"handpose",
"tfjs"
]
}
TensorFlow.js
1. https://www.youtube.com/watch?v=CM92pIh1Unw
2. https://www.youtube.com/watch?v=3MqJzMvHE3E
https://www.tensorflow.org/js/guide/nodejs
https://levelup.gitconnected.com/build-ad-dog-classifier-with-react-and-tensorflow-js-in-minutes-f08e98608a65
https://experiments.withgoogle.com/collection/ai
https://teachablemachine.withgoogle.com/
https://www.npmjs.com/package/ml5
https://p5js.org/
## Main objective
- creating a web tool which is capable of doing video & audio conferencing while adding new features to traditional teaching methods
## Main Research questions
- How to make E-learning more interactive efficient and powerful
## Individual research quesiton
- What can be added to get students attractions
- How can we force students to use Q&A systems
- How to track students attention
- Keep un neccessary students out from sessions
## Individual objectives
- Using 3D visualization methods in teaching
- Advance Q and A
- Tracking students attention
- High security features
## Other necessary Information
# Running the project
## Getting Started
First, run the development server:
......@@ -31,3 +7,5 @@ npm run dev
# or
yarn dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
/// <reference types="next" />
/// <reference types="next/types/global" />
/// <reference types="next/image-types/global" />
const path = require('path');
module.exports = {
env: {
appName: 'com',
dev_url: 'http://localhost:3000',
host_url: 'https://noon-interview.vercel.app',
hosting: false,
FIREBASE_PROJECT_ID: "noon-4a6cf",
FIREBASE_CLIENT_EMAIL: "firebase-adminsdk-au73o@noon-4a6cf.iam.gserviceaccount.com",
FIREBASE_PRIVATE_KEY: "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDMly3SvQ3pgobE\naZDDFfjfcoYTsTmfpP8MDFJRw4MHYL45ejg8YeB8joBiHn0xgfkd0Tza6+Cse4gl\nos2vA2PJZ9zg10W64b5CecAlvB6yoNj2T8Vc6S+uRqEfx+4Ab6KQ4DyV79za2AUD\nmLML9j/swYojP92TzcxFkIs3e1x0IaB3L7HqhDaCotVICNs+HHLghOHFmOHPTZVt\nST0wFxbiAxG/IhGVFk6JybEc9fpy2bWL9125jW2Q81TYTDZNHS2oLBiY0yhVuUtQ\nSdiVsPYTrgygDRjC59+QI0uKrMhIvYZ3ZogDgntHFOk1mA29g9LdRDWD7i1oMylo\n7nMEdS71AgMBAAECggEAOkYZZDw7OTbXghx7gkXA5IxvSi6htio+B0V/MRDaQoC4\nzhBU8kYCthe0073RdQeLWIXfqo+jKB3rkqTDp0T06EowLM7Eas2f7rlVFKp3p/OO\nuOHR2nwE+8PcYvwEe5VQnalxOFfg9WiwTOzymsaiQKKD4TRwvYfR1kKslLoLhHwI\nglL/wPopWGPb2PAoc/Yh/Ai3mriMxMLN2V5r/CIoZjggbYIEobnkNONQ2I2z4bd1\nJ6363VRgBp6ZmhC4VnaXNuqZfOKfwQmi1rzcdTMn5DhZySeWVmJ6cExkHvkMz6Ji\nEfP2tA9ssfZKaghywLT5cYmr33OQdV+1OtYXBhgfxQKBgQD8ixKxOzcGXxr893Sj\nsLYwIMGpYAXCl5OVNr+XdjXwh3o3q1PQvidheHyTKR/jxUKcQgI1KksVcREX5oLW\nmFVtFApcloAVZv8zoNTCRywXA8toxQJcsqinTmzNwjYbn68ICgJtkqZLc6Ph45h7\nDoNWC3/hwGLcsTD1JloBQ8QtQwKBgQDPZBOmDItgdaJBRWbmg7ISnEnXn973tAlX\nhyioJVc77zOHJ1CMaE8FcMHsUrrcORy667L+k6FyPHSJUpNuVieFlmywl6Q2Dw8t\nFn69OC8kw+8CklMxX65jYG9EwU1wdcbzpntr/3h9NX9CNDacQP3aN/1ivOaOWLxr\nN+7x+fkTZwKBgBSgo2k4hfkOQZ0R9UP9hhQOSOM1xaKsUNCqRSHw9Nzto+zyIIl3\nTq4mcj5u6HzpOtSai6WeC733m0bRfDRdAvVC4snHPTUCUav84gPwXkiO9clb9iJu\nMVphDIAN8e91ro1AjAw5Iz4cdvFXbrf2aoHXtJ1S4oBWNMKBXG6oA1kTAoGASHAx\nOL+K8z9DVD8UiRGY4k06sZkCvUxiMvNfrROV27ZaLiv6Q4CvkTvoUE45PHCqa1Om\naqtQKeGZ5tkz68cl+NAo2Kmuzr8F0v7Xd+om9VWGp0RK0KUV+VoWo1JNZSmOO058\nL6XFBR7pe0tXg85jnJQP6iwG79NoxJ591IE2kaMCgYEAzOw4Bfhctj5ipWfB/May\nFsiihBsDKA2Qo74XOrxpjtJJ9t1mjLuPeyZgPP6CIqIIrPDUktwnsw2AGc2S9ovu\npKtkn4E5vd9W1mGx91uUuY9OUIjjDVV+ToH4gELXhhAlz9a6pevv1Fx5ULNuszLo\n9t95t+XCkuqRyytTbDLYY6w=\n-----END PRIVATE KEY-----\n",
},
i18n: {
locales: ['en','jp','sin'],
defaultLocale: 'en'
},
reactStrictMode: true,
}
env: {
APP_NAME: 'Davinci',
API_KEY: 'AIzaSyBCC6ZG9rLWUyEWsMvKbISBJj61zKY8sS8',
AUTH_DOMAIN: 'davinci-33f41.firebaseapp.com',
PROJECT_ID: 'davinci-33f41',
STORAGE_BUCKET: 'davinci-33f41.appspot.com',
MESSAGING_SENDER_ID: '543136869191',
APP_ID: '1:543136869191:web:8e80d6b3618c9d08997a62',
MEASUREMENT_ID: 'G-SCD4TJGBHV',
},
i18n: {
locales: ['en', 'de'],
defaultLocale: 'en',
},
reactStrictMode: true,
sassOptions: {
includePaths: [path.join(__dirname, './src/common/styles')],
},
images: {
domains: ['google.com'],
},
// webpack: (config, { isServer }) => {
// if (isServer) {
// require("scripts/generate-sitemap");
// }
// return config;
// },
};
This diff is collapsed.
......@@ -5,31 +5,51 @@
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
"start": "next start",
"lint": "next lint",
"da:all": "tsc && yarn da:lint && yarn da:check",
"da:lint": "eslint '**/*.{js,jsx,ts,tsx}'",
"da:check": "prettier --check '**/*.{js,jsx,ts,tsx}'",
"da:fix": "prettier --write '**/*.{js,jsx,ts,tsx}'",
"prepare": "husky install"
},
"dependencies": {
"@tensorflow-models/handpose": "^0.0.7",
"@tensorflow/tfjs": "^3.2.0",
"@tensorflow/tfjs-backend-webgl": "3.3.0",
"@tensorflow/tfjs-converter": "3.3.0",
"@tensorflow/tfjs-core": "3.3.0",
"@tensorflow/tfjs": "^3.7.0",
"@tensorflow/tfjs-backend-webgl": "3.7.0",
"@tensorflow/tfjs-converter": "3.7.0",
"@tensorflow/tfjs-core": "3.7.0",
"fingerpose": "^0.0.2",
"next": "10.0.7",
"react": "17.0.1",
"react-dom": "17.0.1",
"react-webcam": "^5.2.3",
"styled-components": "^5.2.1"
"firebase": "^8.6.8",
"next": "^11.0.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-firebase-hooks": "^3.0.4",
"react-select": "^4.3.1",
"react-webcam": "^5.2.4",
"sass": "^1.35.1",
"three": "^0.129.0"
},
"devDependencies": {
"@types/node": "^14.14.31",
"@types/react": "^17.0.2",
"@types/styled-components": "^5.1.7",
"babel-plugin-styled-components": "^1.12.0",
"prettier": "^2.2.1",
"tslib": "2.1.0",
"typescript": "^4.2.2"
},
"resolutions": {
"styled-components": "^5"
"@types/react": "^17.0.11",
"@types/react-select": "^4.0.16",
"@types/three": "^0.129.1",
"@typescript-eslint/eslint-plugin": "^4.28.0",
"@typescript-eslint/parser": "^4.28.0",
"eslint": "^7.29.0",
"eslint-config-airbnb": "^18.2.1",
"eslint-config-next": "^11.0.1",
"eslint-config-prettier": "^8.3.0",
"eslint-import-resolver-typescript": "^2.4.0",
"eslint-plugin-import": "^2.23.4",
"eslint-plugin-json": "^3.0.0",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-prettier": "^3.4.0",
"eslint-plugin-react": "^7.24.0",
"eslint-plugin-react-hooks": "^4.2.0",
"eslint-plugin-sort-destructure-keys": "^1.3.5",
"husky": "^6.0.0",
"prettier": "^2.3.2",
"typescript": "^4.3.4"
}
}
No preview for this file type
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<g>
<g>
<polygon points="357.871,391.592 287.48,381.364 256,317.577 224.52,381.364 154.129,391.592 205.064,441.242 193.04,511.349
256,478.249 318.96,511.349 306.936,441.242 "/>
</g>
</g>
<g>
<g>
<polygon points="512,346.347 451.058,337.491 423.805,282.269 396.55,337.491 335.608,346.347 379.706,389.332 369.296,450.028
423.805,421.372 478.313,450.028 467.902,389.332 "/>
</g>
</g>
<g>
<g>
<polygon points="176.392,346.347 115.45,337.491 88.195,282.269 60.942,337.491 0,346.347 44.098,389.332 33.688,450.028
88.195,421.372 142.704,450.028 132.294,389.332 "/>
</g>
</g>
<g>
<g>
<path d="M308.507,182.256c8.547-11.146,13.643-25.07,13.643-40.17c0-36.476-29.675-66.15-66.15-66.15s-66.15,29.674-66.15,66.15
c0,15.1,5.096,29.024,13.644,40.17c-26.469,9.845-45.379,35.362-45.379,65.219v59.184h195.771v-59.184
C353.886,217.619,334.976,192.102,308.507,182.256z"/>
</g>
</g>
<g>
<g>
<rect x="240.839" y="0.651" width="30.321" height="50.019"/>
</g>
</g>
<g>
<g>
<rect x="158.511" y="34.748" transform="matrix(0.7071 -0.7071 0.7071 0.7071 8.6121 140.3069)" width="30.321" height="50.019"/>
</g>
</g>
<g>
<g>
<rect x="114.562" y="126.923" width="50.019" height="30.321"/>
</g>
</g>
<g>
<g>
<rect x="347.416" y="126.923" width="50.019" height="30.321"/>
</g>
</g>
<g>
<g>
<rect x="313.313" y="44.603" transform="matrix(0.7071 -0.7071 0.7071 0.7071 56.8332 256.7344)" width="50.019" height="30.321"/>
</g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>
This diff is collapsed.
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<path style="fill:#FBBB00;" d="M113.47,309.408L95.648,375.94l-65.139,1.378C11.042,341.211,0,299.9,0,256
c0-42.451,10.324-82.483,28.624-117.732h0.014l57.992,10.632l25.404,57.644c-5.317,15.501-8.215,32.141-8.215,49.456
C103.821,274.792,107.225,292.797,113.47,309.408z"/>
<path style="fill:#518EF8;" d="M507.527,208.176C510.467,223.662,512,239.655,512,256c0,18.328-1.927,36.206-5.598,53.451
c-12.462,58.683-45.025,109.925-90.134,146.187l-0.014-0.014l-73.044-3.727l-10.338-64.535
c29.932-17.554,53.324-45.025,65.646-77.911h-136.89V208.176h138.887L507.527,208.176L507.527,208.176z"/>
<path style="fill:#28B446;" d="M416.253,455.624l0.014,0.014C372.396,490.901,316.666,512,256,512
c-97.491,0-182.252-54.491-225.491-134.681l82.961-67.91c21.619,57.698,77.278,98.771,142.53,98.771
c28.047,0,54.323-7.582,76.87-20.818L416.253,455.624z"/>
<path style="fill:#F14336;" d="M419.404,58.936l-82.933,67.896c-23.335-14.586-50.919-23.012-80.471-23.012
c-66.729,0-123.429,42.957-143.965,102.724l-83.397-68.276h-0.014C71.23,56.123,157.06,0,256,0
C318.115,0,375.068,22.126,419.404,58.936z"/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>
<svg height="512pt" viewBox="0 -64 512.01547 512" width="512pt" xmlns="http://www.w3.org/2000/svg"><path d="m503.457031 144.890625h-90.214843c-.84375 0-1.679688.035156-2.507813.074219-.8125.042968-2.015625.113281-2.363281.011718l-104.175782-28.425781 42.4375-42.4375c4.988282-4.992187 9.980469-9.984375 14.972657-14.976562 3.492187-3.488281 7.03125-6.925781 10.472656-10.46875 4.207031-4.328125 8.515625-7.945313 10.792969-13.765625 1.035156-2.636719 1.640625-5.433594 1.765625-8.257813.992187-22.871093-27.398438-35.542969-43.613281-19.328125l-93.796876 93.796875-41.386718-11.1875c-30.386719-8.6875-62.695313-3.34375-88.679688 14.636719l-41.972656 29.054688c-21.839844 15.121093-34.230469 40.976562-32.34375 67.472656.042969.574218.144531 1.144531.300781 1.699218l18.257813 64.9375c1.300781 4.617188 3.75 8.765626 6.921875 12.28125l-14.992188 15-25.234375 25.234376c-.621094.621093-1.152344 1.339843-1.550781 2.132812l-25.601563 49.742188c-1.699218 3.292968-1.066406 7.3125 1.554688 9.941406 1.636719 1.636718 3.820312 2.5 6.039062 2.5 1.324219 0 2.664063-.308594 3.902344-.949219l49.730469-25.597656c.75-.386719 1.441406-.890625 2.046875-1.46875l27.070312-26.335938c.664063-.648437 1.109376-1.449219 1.527344-2.25 0 0 32.628906-32.632812 32.851563-32.554687 6.554687 2.320312 13.519531 3.523437 20.4375 2.363281 6.902343-1.152344 13.550781-3.191406 20.609375-3.492187 27.699218-1.140626 54.6875.316406 80.210937 4.386718 15.019531 2.40625 34.449219 6.171875 51.585938 14.027344l2.378906 1.09375c9.867187 4.546875 20.0625 9.257812 32.417969 10.410156 2.375.222656 4.753906.332032 7.152344.332032 8.082031 0 16.308593-1.253907 24.535156-3.746094 15.171875-4.589844 30.027344-13.15625 42.988281-24.777344 4.257813-3.839844 9.285156-6.042969 13.808594-6.042969h81.6875c4.710937 0 8.535156-3.824219 8.535156-8.535156v-128c-.027344-4.710937-3.847656-8.53125-8.558594-8.53125zm-338.21875 77.285156c-.417969.019531-.835937.035157-1.246093.050781-2.875.113282-5.683594.273438-8.429688.5625-2.398438.257813-4.710938.609376-6.9375 1.058594l167.832031-167.832031 12.066407 12.066406-153.984376 153.984375c-.316406 0-.582031.007813-.894531.007813-2.9375-.007813-5.734375.023437-8.40625.101562zm42.546875-9.214843 12.332032 8.40625c-2.21875.261718-4.96875.503906-8.363282.691406l-1.511718.082031c-3.824219.242187-7.832032.230469-11.84375.214844zm-92.46875-6.9375c1.078125-8.378907 6.582032-16.382813 12.820313-18.46875.125-.039063.246093-.082032.363281-.132813l18.03125-6.972656c5.691406-1.914063 11.828125-1.085938 16.761719 2.210937l1.414062.960938-46.199219 46.199218zm-30.734375 106-12.792969-11.347657 38.792969-38.792969c-.179687.851563-.324219 1.671876-.476562 2.5-.703125 3.832032-1.1875 7.6875-1.476563 11.570313-.273437 3.558594-.929687 7.277344 1.109375 10.480469.058594.085937.074219.195312.136719.28125zm0 0"/></svg>
\ No newline at end of file
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 462.522 462.522" style="enable-background:new 0 0 462.522 462.522;" xml:space="preserve">
<path d="M432.958,222.262c-1.452-0.305-2.823-0.592-4.042-0.909c-13.821-3.594-20.129-5.564-24.793-14.569l-17.667-35.768
c-5.678-10.961-20.339-19.879-32.682-19.879h-31.453v-41.303c0-7.416-6.034-13.45-13.452-13.45l-219.07,0.22
c-7.218,0-12.661,5.736-12.661,13.343v12.208H21.018C9.429,122.156,0,131.584,0,143.174s9.429,21.018,21.018,21.018h56.119v20.145
H40.394c-11.589,0-21.018,9.429-21.018,21.018s9.429,21.018,21.018,21.018h36.743v20.145H59.77
c-11.589,0-21.018,9.429-21.018,21.018s9.429,21.018,21.018,21.018h17.367v21.07c0,7.416,6.034,13.45,13.45,13.45h22.788
c3.549,24.323,24.542,43.064,49.837,43.064c25.297,0,46.291-18.741,49.841-43.064h92.224c0.479,0,0.97-0.032,1.46-0.064
c3.522,24.354,24.528,43.128,49.845,43.128c25.297,0,46.291-18.741,49.841-43.064h32.732c12.885,0,23.368-10.482,23.368-23.366
v-39.648C462.522,228.465,444.73,224.732,432.958,222.262z M356.582,297.46c10.1,0,18.317,8.214,18.317,18.311
s-8.217,18.311-18.317,18.311c-10.096,0-18.31-8.214-18.31-18.311S346.486,297.46,356.582,297.46z M322.321,219.414v-48.77h24.036
c9.238,0,20.634,6.932,24.864,15.094l15.721,31.829c0.333,0.644,0.679,1.258,1.038,1.846H322.321z M181.529,315.77
c0,10.096-8.217,18.311-18.317,18.311c-10.096,0-18.309-8.214-18.309-18.311s8.213-18.311,18.309-18.311
C173.312,297.46,181.529,305.674,181.529,315.77z"/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="80.13px" height="80.13px" viewBox="0 0 80.13 80.13" style="enable-background:new 0 0 80.13 80.13;" xml:space="preserve">
<g>
<path d="M48.355,17.922c3.705,2.323,6.303,6.254,6.776,10.817c1.511,0.706,3.188,1.112,4.966,1.112
c6.491,0,11.752-5.261,11.752-11.751c0-6.491-5.261-11.752-11.752-11.752C53.668,6.35,48.453,11.517,48.355,17.922z M40.656,41.984
c6.491,0,11.752-5.262,11.752-11.752s-5.262-11.751-11.752-11.751c-6.49,0-11.754,5.262-11.754,11.752S34.166,41.984,40.656,41.984
z M45.641,42.785h-9.972c-8.297,0-15.047,6.751-15.047,15.048v12.195l0.031,0.191l0.84,0.263
c7.918,2.474,14.797,3.299,20.459,3.299c11.059,0,17.469-3.153,17.864-3.354l0.785-0.397h0.084V57.833
C60.688,49.536,53.938,42.785,45.641,42.785z M65.084,30.653h-9.895c-0.107,3.959-1.797,7.524-4.47,10.088
c7.375,2.193,12.771,9.032,12.771,17.11v3.758c9.77-0.358,15.4-3.127,15.771-3.313l0.785-0.398h0.084V45.699
C80.13,37.403,73.38,30.653,65.084,30.653z M20.035,29.853c2.299,0,4.438-0.671,6.25-1.814c0.576-3.757,2.59-7.04,5.467-9.276
c0.012-0.22,0.033-0.438,0.033-0.66c0-6.491-5.262-11.752-11.75-11.752c-6.492,0-11.752,5.261-11.752,11.752
C8.283,24.591,13.543,29.853,20.035,29.853z M30.589,40.741c-2.66-2.551-4.344-6.097-4.467-10.032
c-0.367-0.027-0.73-0.056-1.104-0.056h-9.971C6.75,30.653,0,37.403,0,45.699v12.197l0.031,0.188l0.84,0.265
c6.352,1.983,12.021,2.897,16.945,3.185v-3.683C17.818,49.773,23.212,42.936,30.589,40.741z"/>
</g>
</svg>
This diff is collapsed.
<svg width="283" height="64" viewBox="0 0 283 64" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path d="M141.04 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.46 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM248.72 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.45 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM200.24 34c0 6 3.92 10 10 10 4.12 0 7.21-1.87 8.8-4.92l7.68 4.43c-3.18 5.3-9.14 8.49-16.48 8.49-11.05 0-19-7.2-19-18s7.96-18 19-18c7.34 0 13.29 3.19 16.48 8.49l-7.68 4.43c-1.59-3.05-4.68-4.92-8.8-4.92-6.07 0-10 4-10 10zm82.48-29v46h-9V5h9zM36.95 0L73.9 64H0L36.95 0zm92.38 5l-27.71 48L73.91 5H84.3l17.32 30 17.32-30h10.39zm58.91 12v9.69c-1-.29-2.06-.49-3.2-.49-5.81 0-10 4-10 10V51h-9V17h9v9.2c0-5.08 5.91-9.2 13.2-9.2z" fill="#000"/>
</svg>
\ No newline at end of file
import { IFigurePackageObj, IPaperPackageObj, TCurrency, TPaperSize } from '@ts/common';
import React, { useEffect, useState } from 'react';
type TProps = {
children: JSX.Element;
};
interface IContext {
totalPrice: number;
figureCount: number;
currency: TCurrency;
paperSize: TPaperSize;
setTotalPrice: React.Dispatch<React.SetStateAction<number>>;
setFigureCount: React.Dispatch<React.SetStateAction<number>>;
setCurrency: React.Dispatch<React.SetStateAction<TCurrency>>;
setPaperSize: React.Dispatch<React.SetStateAction<TPaperSize>>;
figurePackageObj: IFigurePackageObj;
paperPackageObj: IPaperPackageObj;
}
const initContext: IContext = {
totalPrice: 79,
figureCount: 1,
currency: 'euro',
paperSize: 'A4',
setTotalPrice: () => null,
setFigureCount: () => null,
setCurrency: () => null,
setPaperSize: () => null,
figurePackageObj: {
figure1: {
prev: 109,
now: 79,
imgUrl: '/images/sample1.jpeg',
},
figure2: {
prev: 139,
now: 109,
imgUrl: '/images/sample2.jpeg',
},
figure3: {
prev: 149,
now: 139,
imgUrl: '/images/sample3.jpeg',
},
figure4: {
prev: 199,
now: 169,
imgUrl: '/images/sample4.jpeg',
},
figure5: {
prev: 229,
now: 199,
imgUrl: '/images/sample5.jpeg',
},
figure6: {
prev: 259,
now: 229,
imgUrl: '/images/sample6.jpeg',
},
},
paperPackageObj: {
paperA4: {
prev: 259,
now: 229,
imgUrl: '/images/sample6.jpeg',
},
},
};
export const CartContext = React.createContext<IContext>(initContext);
export const CartContextProvider = ({ children }: TProps): React.ReactElement => {
const [totalPrice, setTotalPrice] = useState(initContext.totalPrice);
const [currency, setCurrency] = useState(initContext.currency);
const [figureCount, setFigureCount] = useState(initContext.figureCount);
const [paperSize, setPaperSize] = useState(initContext.paperSize);
const [figurePackageObj] = useState(initContext.figurePackageObj);
const [paperPackageObj] = useState(initContext.paperPackageObj);
useEffect(() => {
const figurePrice = figurePackageObj[`figure${figureCount}`]?.now;
const paperPrice = 30;
setTotalPrice(figurePrice + paperPrice);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [figureCount]);
const contextValue = {
totalPrice,
figureCount,
currency,
paperSize,
setTotalPrice,
setFigureCount,
setCurrency,
setPaperSize,
figurePackageObj,
paperPackageObj,
};
return <CartContext.Provider value={contextValue}>{children}</CartContext.Provider>;
};
import { auth, firestore, googleAuthProvider } from '@lib/firebase';
import { useRouter } from 'next/router';
import React, { useCallback, useEffect, useState } from 'react';
type TProps = {
children: JSX.Element;
};
export type TBasicData = null | string;
export type TUser = {
displayName: TBasicData;
email: TBasicData;
photoURL: TBasicData;
type: TBasicData;
uid: TBasicData;
};
const initialUserData = {
displayName: null,
email: null,
photoURL: null,
type: null,
uid: null,
};
interface IContext {
isLogged: boolean;
loading: boolean;
userData: TUser;
signOut: () => void;
signIn: () => void;
adminRoute: () => void;
}
const initContext: IContext = {
isLogged: false,
loading: true,
userData: initialUserData,
signOut: () => null,
signIn: () => null,
adminRoute: () => null,
};
export const UserContext = React.createContext<IContext>(initContext);
export const UserContextProvider = ({ children }: TProps): React.ReactElement => {
const [userData, setUserData] = useState(initContext.userData);
const [loading, setLoading] = useState(initContext.loading);
const [isLogged, setIsLogged] = useState(initContext.isLogged);
const router = useRouter();
const signInWithGoogle = async () => {
await auth.signInWithPopup(googleAuthProvider);
};
const signOut = () => {
auth.signOut();
setIsLogged(false);
router.push('/login');
};
const signIn = () => {
setLoading(true);
signInWithGoogle();
};
const adminRoute = useCallback(async () => {
if (isLogged) {
if (userData.type === 'admin') {
router.push(
{
pathname: '/admin/[uid]/panel',
query: {
order: userData.uid,
},
},
`/admin/${userData.uid}/panel`
);
} else if (userData.type === 'editor') {
router.push('/editor');
} else if (userData.type === 'artist') {
router.push('/artist');
} else {
router.push('/');
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isLogged, userData]);
useEffect(() => {
let referenceSubscription: () => void;
const authStateSubscription = auth.onAuthStateChanged(user => {
if (!user) {
setLoading(false);
return;
}
try {
if (user) {
const ref = firestore.collection('users').doc(user.uid);
referenceSubscription = ref.onSnapshot(doc => {
if (!doc) {
setLoading(false);
return;
}
setUserData({
displayName: doc.data()?.userName || user.displayName,
email: user.email,
photoURL: doc.data()?.photoURL || user.photoURL,
type: doc.data()?.type,
uid: user.uid,
});
setIsLogged(true);
setLoading(false);
});
} else {
setUserData(initialUserData);
setLoading(false);
}
} catch (error) {
// eslint-disable-next-line no-console
console.log('subscription_error: =-->', error);
setLoading(false);
}
});
// turn off realtime subscription
return () => {
referenceSubscription();
authStateSubscription();
};
}, []);
const contextValue = {
loading,
isLogged,
userData,
signOut,
signIn,
adminRoute,
};
return <UserContext.Provider value={contextValue}>{children}</UserContext.Provider>;
};
import { useEffect, useState } from 'react';
const useDebounce = (value: string | number | boolean, delay = 250): string | number | boolean => {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(handler);
};
}, [value, delay]);
return debouncedValue;
};
export default useDebounce;
/* eslint-disable import/no-duplicates */
// import firebase from 'firebase/app';
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
import 'firebase/storage';
const firebaseConfig = {
apiKey: process.env.API_KEY, // for auth
authDomain: process.env.AUTH_DOMAIN, // for auth
projectId: process.env.PROJECT_ID, // for auth
storageBucket: process.env.STORAGE_BUCKET,
messagingSenderId: process.env.MESSAGING_SENDER_ID,
appId: process.env.APP_ID,
measurementId: process.env.MEASUREMENT_ID,
};
// if a Firebase instance doesn't exist, create one
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
}
// Auth exports
export const auth = firebase.auth();
export const googleAuthProvider = new firebase.auth.GoogleAuthProvider();
// Firestore exports
export const firestore = firebase.firestore();
export const { serverTimestamp } = firebase.firestore.FieldValue;
export const { fromMillis } = firebase.firestore.Timestamp;
export const { increment } = firebase.firestore.FieldValue;
// Storage exports
export const storage = firebase.storage();
export const { STATE_CHANGED } = firebase.storage.TaskEvent;
// --- Breakpoints
const maxMobile = 576; // (for phones)
const minTablet = 576; // (for tablet)
const minTabletLC = 769; // (landscape of tablet)
const minDesktopSM = 992; // (for small Laptop)
const minDesktopLG = 1201; // (for large laptop)
const min4K = 1441; // (for 4k)
export const breakpoints = {
maxMobile: `only screen and (max-width: ${maxMobile}px)`,
minTablet: `only screen and (min-width: ${minTablet}px)`,
minTabletLC: `only screen and (min-width: ${minTabletLC}px)`,
minDesktopSM: `only screen and (min-width: ${minDesktopSM}px)`,
minDesktopLG: `only screen and (min-width: ${minDesktopLG}px)`,
min4K: `only screen and (min-width: ${min4K}px)`,
};
export const clearfix = `
&:after,
&:before{
content: "";
display: table;
}
&:after {
clear: both;
}
`;
export const noSelect = `
-webkit-touch-callout: none;
user-select: none;
`;
export const noCallout = `
-webkit-touch-callout: none;
`;
export const noAction = `
touch-action: none;
`;
export const imgNoClick = `
position: relative;
`;
export const imgNoClickCover = `
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
height: 100%;
width: 100%;
`;
export const focusRingIssue = `
outline: -webkit-focus-ring-color auto 5px;
`;
export const tapHighlightIssue = `
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-webkit-tap-highlight-color: transparent;
`;
export const breakWords = `
word-wrap: break-word;
`;
export const wrapWords = `
overflow-wrap: break-word;
word-wrap: break-word;
hyphens: auto;
`;
This diff is collapsed.
export const DavinciLogo = (): JSX.Element => {
return (
<svg
width='121'
height='17'
viewBox='0 0 121 17'
fill='none'
xmlns='http://www.w3.org/2000/svg'
className='davinci_logo'>
<path
d='M0.04599 16V0.379992H5.23799C6.88066 0.379992 8.25199 0.731992 9.35199 1.43599C10.452 2.12533 11.2733 3.06399 11.816 4.25199C12.3733 5.42533 12.652 6.73066 12.652 8.16799C12.652 9.75199 12.344 11.1307 11.728 12.304C11.1267 13.4773 10.2687 14.3867 9.15399 15.032C8.05399 15.6773 6.74866 16 5.23799 16H0.04599ZM11.53 8.16799C11.53 6.86266 11.2807 5.70399 10.782 4.69199C10.298 3.66533 9.58666 2.85866 8.64799 2.27199C7.70932 1.68533 6.57266 1.39199 5.23799 1.39199H1.16799V14.988H5.23799C6.60199 14.988 7.75332 14.6873 8.69199 14.086C9.63066 13.4847 10.3347 12.6707 10.804 11.644C11.288 10.6173 11.53 9.45866 11.53 8.16799Z'
fill='black'
/>
<path
d='M26.457 0.379992H27.425L34.025 16H32.837L30.659 10.852H23.201L21.023 16H19.813L26.457 0.379992ZM30.351 9.92799L26.941 1.74399L23.465 9.92799H30.351Z'
fill='black'
/>
ß
<path
d='M40.9381 0.379992L46.8781 14.592L52.8181 0.379992H54.0061L47.4282 16H46.3501L39.7501 0.379992H40.9381Z'
fill='black'
/>
<path d='M62.7778 16V0.379992H63.8998V16H62.7778Z' fill='black' />
<path
d='M75.5005 2.46999V16H74.3785V0.379992H75.3025L86.1925 14.13V0.379992H87.3145V16H86.2145L75.5005 2.46999Z'
fill='black'
/>
<path
d='M96.6961 8.07999C96.6961 7.14133 96.8574 6.20999 97.1801 5.28599C97.5174 4.36199 98.0015 3.52599 98.6321 2.77799C99.2628 2.02999 100.033 1.42866 100.942 0.973993C101.866 0.519326 102.915 0.291992 104.088 0.291992C105.481 0.291992 106.669 0.614659 107.652 1.25999C108.635 1.89066 109.368 2.70466 109.852 3.70199L108.928 4.22999C108.561 3.51133 108.107 2.93933 107.564 2.51399C107.036 2.08866 106.464 1.78799 105.848 1.61199C105.232 1.42133 104.616 1.32599 104 1.32599C103.017 1.32599 102.137 1.52399 101.36 1.91999C100.597 2.31599 99.9521 2.84399 99.4241 3.50399C98.8961 4.16399 98.4928 4.89733 98.2141 5.70399C97.9501 6.51066 97.8181 7.32466 97.8181 8.14599C97.8181 9.06999 97.9794 9.94999 98.3021 10.786C98.6248 11.6073 99.0648 12.348 99.6221 13.008C100.194 13.6533 100.854 14.1667 101.602 14.548C102.365 14.9147 103.186 15.098 104.066 15.098C104.697 15.098 105.335 14.9953 105.98 14.79C106.64 14.57 107.256 14.24 107.828 13.8C108.4 13.3453 108.862 12.7587 109.214 12.04L110.182 12.502C109.83 13.2793 109.317 13.9393 108.642 14.482C107.982 15.0247 107.241 15.4353 106.42 15.714C105.599 15.9927 104.785 16.132 103.978 16.132C102.922 16.132 101.947 15.9047 101.052 15.45C100.157 14.9807 99.3875 14.3647 98.7421 13.602C98.0968 12.8247 97.5908 11.9593 97.2241 11.006C96.8721 10.038 96.6961 9.06266 96.6961 8.07999Z'
fill='black'
/>
<path d='M119.344 16V0.379992H120.466V16H119.344Z' fill='black' />
</svg>
);
};
import { Ttranslations } from "../types/localize"
import { TTranslations } from '@ts/localize';
export const en : Ttranslations = {
login: "help"
}
const en: TTranslations = {
howItWorks: 'how it works',
gallery: 'gallery',
prices: 'prices',
shipping: 'shipping',
numberOfPeople: 'number of people / animals',
quantity: 'quantity',
size: 'size',
upload: 'upload',
shippingCart: 'shopping cart',
personsAnimals: 'persons / animals',
expressDeliveryIn: 'express delivery in',
just7Days: 'just 7 days',
expressDeliveryDays: '7 Days express delivery',
handmade: '100% handmade',
satisfactionGuarantee: '100% satisfaction guarantee',
};
export default en;
import { TTranslations } from '@ts/localize';
const de: TTranslations = {
howItWorks: 'so funktioniert es',
gallery: 'galerie',
prices: 'preise',
shipping: 'versand',
numberOfPeople: 'anzahl menschen / tiere',
quantity: 'anzahl',
size: 'gröss',
upload: 'upload',
shippingCart: 'warenkorb',
personsAnimals: 'personen / tiere',
expressDeliveryIn: 'expresslieferung in',
just7Days: 'nur 7 Tagen',
expressDeliveryDays: '7 Tage Expressversand',
handmade: '100% handgemacht',
satisfactionGuarantee: '100% Zufriedenheitsgarantie',
};
export default de;
import { Ttranslations } from "../types/localize"
export const jp : Ttranslations = {
login: "助けて"
}
import { Ttranslations } from "../types/localize"
export const sin : Ttranslations = {
login: "උදව්"
}
export type TTab = 'quantity' | 'size' | 'upload' | 'cart';
export type TInputValue = string | number | null;
export type TCurrency = 'dollar' | 'euro';
export type TPaperSize = 'A4' | 'A3' | 'A2' | 'A1';
export type TPaper = {
prev: number;
now: number;
imgUrl: string;
};
export type TFigure = {
prev: number;
now: number;
imgUrl: string;
};
export interface IFigurePackageObj {
[key: string]: TFigure;
}
export interface IPaperPackageObj {
[key: string]: TPaper;
}
export type TMenuItem = 'artists' | 'editors' | 'customers' | 'analytics' | 'settings';
export type TMenuItemArr = {
name: TMenuItem;
icon: string;
}[];
type TNumberArr = [number, number, number, number];
type TLandmarks = [number, number, number];
export type THand = [
annotations: {
indexFinger: TNumberArr[];
middleFinger: TNumberArr[];
palmBase: TNumberArr[];
pinky: TNumberArr[];
ringFinger: TNumberArr[];
thumb: TNumberArr[];
},
boundingBox: {
bottomRight: [number, number];
topLeft: [number, number];
},
handInViewConfidence: number,
landmarks: TLandmarks
];
// This will receive an object with target field that is of type HTMLInputElement
export interface IHtmlSelectedElement {
target: HTMLSelectElement;
}
export interface IHtmlInputElement {
target: HTMLInputElement;
}
export interface IHTMLVideoElement {
target: HTMLVideoElement;
}
export interface IHTMLCanvasElement {
target: HTMLCanvasElement;
}
export type TLocale = 'en' | 'de';
export type TTranslations = {
howItWorks: string;
gallery: string;
prices: string;
shipping: string;
numberOfPeople: string;
quantity: string;
size: string;
upload: string;
shippingCart: string;
personsAnimals: string;
expressDeliveryIn: string;
just7Days: string;
expressDeliveryDays: string;
handmade: string;
satisfactionGuarantee: string;
};
export type Tlocale = 'en' | 'sin' | 'jp';
export type Ttranslations = {
login : string
};
import styles from '@components_style/Button.module.sass';
import React from 'react';
type TProps = { text: string; onClickHandler: () => void; isDisabled: boolean; type: 'normal' | 'submit' };
const Button = ({ isDisabled, onClickHandler, text, type = 'normal' }: TProps): JSX.Element => {
return (
<>
{type === 'normal' && (
<button
className={`${styles.container} ${isDisabled ? styles.disabled : ''}`}
onClick={() => {
if (!isDisabled) {
onClickHandler();
}
}}
type='button'>
{text}
</button>
)}
{type === 'submit' && (
<input
type='submit'
className={`${styles.submitBtn} ${isDisabled ? styles.disabled : ''}`}
onClick={e => {
e.preventDefault();
if (!isDisabled) {
onClickHandler();
}
}}
value={text}
/>
)}
</>
);
};
export default Button;
import styles from '@components_style/Cross.module.sass';
import React from 'react';
type TProps = {
menuOpened: boolean;
clickHandler: React.Dispatch<React.SetStateAction<boolean>>;
};
const Cross = ({ clickHandler, menuOpened }: TProps): JSX.Element => {
return (
<button
className={`${styles.container} ${menuOpened ? styles.open : ''}`}
type='button'
onClick={() => clickHandler(state => !state)}>
<span />
<span />
<span />
<span />
</button>
);
};
export default Cross;
import styles from '@components_style/EllipsisAnimator.module.sass';
import React from 'react';
type TProps = { text?: string };
const EllipsisAnimator = ({ text = 'Checking' }: TProps): JSX.Element => {
return <div className={styles.container}>{text}</div>;
};
export default EllipsisAnimator;
import styles from '@components_style/Input.module.sass';
import { IHtmlInputElement } from '@ts/interfaces';
import React from 'react';
type TProp = {
placeholder: string;
label: string;
errorMsg?: string;
onChange: (val: string) => void;
value: string;
type: 'text' | 'password' | 'hidden';
required?: boolean;
autoComplete?: 'new-password' | 'current-password' | 'username' | 'off' | 'on';
};
const Input = ({
autoComplete = 'on',
errorMsg,
label,
onChange,
placeholder = '',
required = false,
type,
value,
}: TProp): JSX.Element => {
if (type === 'hidden') {
return <input type='hidden' />;
}
return (
<div className={styles.container}>
{label && (
<label htmlFor={placeholder} className={styles.labelElement}>
{label}
</label>
)}
<div className={styles.inputElementCtr}>
<input
className={`${styles.inputElement} ${errorMsg ? styles.error : ''}`}
type={type}
placeholder={placeholder}
aria-describedby={placeholder}
onChange={(e: IHtmlInputElement) => onChange(e.target.value)}
value={value}
required={required}
autoComplete={autoComplete}
/>
{value && <div className={styles.cross} onClick={() => onChange('')} aria-hidden='true' />}
</div>
{errorMsg && <div className={`${styles.errorMsg} ${errorMsg ? styles.error : ''}`}>{errorMsg}</div>}
</div>
);
};
export default Input;
import styles from '@components_style/LetterImg.module.sass';
import { fistCapitalLetter } from '@util/normalize';
import React from 'react';
import { colors } from 'styles/baseStyles';
type TProps = {
text: string;
size?: string;
color?: string;
background?: string;
fontSize?: string;
};
const LetterImg = ({
background = colors.grayLight,
color = colors.black,
size = '50px',
fontSize = '1.5rem',
text,
}: TProps): JSX.Element => {
return (
<div
className={styles.container}
style={{ fontSize, background, color, width: size, height: size, lineHeight: size }}>
{fistCapitalLetter(text)}
</div>
);
};
export default LetterImg;
import styles from '@components_style/Loader.module.sass';
import React from 'react';
type TProps = { show: boolean };
const Loader = ({ show }: TProps): JSX.Element => {
const ctrClass = `${styles.container} ${show ? styles.show : ''}`;
return <div className={ctrClass} />;
};
export default Loader;
import { TInputValue } from '@ts/common';
import React, { useRef } from 'react';
import Select, { OptionTypeBase } from 'react-select';
import { colors } from 'styles/baseStyles';
type TProp = {
placeholder?: string;
isDisabled?: boolean;
onChange: (selected: OptionTypeBase) => void;
options: OptionTypeBase[];
selectedValue: TInputValue;
};
const SelectBox = ({ isDisabled = false, onChange, options, placeholder = '', selectedValue }: TProp): JSX.Element => {
const ref = useRef();
return (
<Select
isDisabled={isDisabled}
placeholder={placeholder}
isSearchable={false}
styles={{
control: styles => {
return {
...styles,
border: 'none',
boxShadow: 'none',
width: 'auto',
display: 'flex',
cursor: 'pointer',
background: 'transparent',
};
},
indicatorSeparator: styles => ({
...styles,
display: 'none',
}),
valueContainer: styles => ({
...styles,
display: 'flex',
justifyContent: 'center',
position: 'static',
alignItems: 'center',
lineHeight: 'auto',
width: '20px',
padding: '0',
margin: '0',
marginRight: '4px',
flex: 'none',
}),
singleValue: styles => ({
...styles,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
margin: '0',
padding: '0',
color: `${colors.white}`,
fontWeight: 'normal',
}),
dropdownIndicator: (styles, state) => ({
...styles,
transition: 'all .2s ease',
padding: '0',
margin: '0',
transform: state.selectProps.menuIsOpen ? 'rotate(180deg)' : 'rotate(0deg)',
color: `${colors.grayDark}`,
':hover': {
...styles[':hover'],
color: `${colors.grayDark}`,
},
}),
menuList: styles => ({
...styles,
margin: '0',
padding: '0',
}),
menu: styles => ({
...styles,
marginTop: '2px',
padding: '0',
}),
option: (styles, state) => {
return {
...styles,
backgroundColor: 'transparent',
color: state.isDisabled ? '#ebecf0' : `${colors.black}`,
pointerEvents: state.isDisabled ? 'none' : 'auto',
textAlign: 'center',
cursor: 'pointer',
':hover': {
...styles[':hover'],
background: `${colors.black}`,
color: `${colors.white}`,
borderRadius: '0',
},
':active': {
...styles[':active'],
background: `${colors.black}`,
borderRadius: '0',
},
':first-of-type:hover': {
...styles[':hover'],
borderRadius: '3px 3px 0 0',
},
':first-of-type:active': {
...styles[':active'],
borderRadius: '3px 3px 0 0',
},
':last-of-type:hover': {
...styles[':hover'],
borderRadius: '0 0 3px 3px',
},
':last-of-type:active': {
...styles[':active'],
borderRadius: '0 0 3px 3px',
},
};
},
}}
value={options.find(option => `${option.value}` === `${selectedValue}`) || options[0]}
onChange={val => onChange(val)}
options={options}
id={`${ref}`}
instanceId={`${ref}`}
inputId={`${ref}`}
/>
);
};
export default SelectBox;
import { UserContext } from '@ctx/UserContext';
import React, { useContext } from 'react';
import ErrorPages from 'src/common/ui/layouts/ErrorPages';
import WaitingPage from 'src/common/ui/layouts/WaitingPage';
type TProps = {
children: React.ReactElement;
fallback?: React.ReactElement;
};
const AuthCheck = ({ children, fallback = <ErrorPages /> }: TProps): JSX.Element => {
const { isLogged, loading } = useContext(UserContext);
if (loading) return <WaitingPage />;
return isLogged ? children : fallback;
};
export default AuthCheck;
import Button from '@components/Button';
import workspace from '@images/workspace.svg';
import styles from '@layouts_style/ErrorPages.module.sass';
import Image from 'next/image';
import { useRouter } from 'next/router';
import React from 'react';
const ErrorPages = (): JSX.Element => {
const router = useRouter();
return (
<div className={styles.container}>
<div className={styles.imageCover}>
<Image src={workspace} alt='workspace' layout='intrinsic' />
</div>
<div className={styles.message}>This page could not be found.</div>
<div className={styles.btnCtr}>
<Button
type='normal'
isDisabled={false}
text='GO HOME'
onClickHandler={() => {
router.push('/');
}}
/>
</div>
</div>
);
};
export default ErrorPages;
import LetterImg from '@components/LetterImg';
import { UserContext } from '@ctx/UserContext';
import styles from '@layouts_style/LeftMenu.module.sass';
import { Log, MenuIcons, ZoomIn } from '@svg/Common';
import { TMenuItem } from '@ts/common';
import React, { useContext, useState } from 'react';
import ErrorPages from 'src/common/ui/layouts/ErrorPages';
import { colors } from 'styles/baseStyles';
const menuHeight = 60;
const LeftMenu = (): JSX.Element | null => {
const { signOut, userData } = useContext(UserContext);
const menuItemsArr: TMenuItem[] = ['analytics', 'artists', 'editors', 'customers', 'settings'];
const [selectedIndex, setSelectedIndex] = useState(0);
const [smallMenu, setSmallMenu] = useState(true);
const top = `${menuHeight * selectedIndex}px`;
const { isLogged } = useContext(UserContext);
if (isLogged === false) {
return <ErrorPages />;
}
return (
<div className={styles.container} style={{ width: smallMenu ? '70px' : '200px' }}>
<div className={styles.profileCover} style={{ paddingBottom: smallMenu ? '0' : '16px' }}>
{userData.photoURL ? (
<img src={userData.photoURL} alt='user' style={{ width: smallMenu ? '56px' : '80px' }} />
) : (
<LetterImg
text={userData.photoURL || ''}
size={smallMenu ? '56px' : '80px'}
fontSize='3rem'
background={colors.grayDark}
/>
)}
</div>
{!smallMenu && <div className={styles.profileName}>{userData.displayName}</div>}
{!smallMenu && userData.type && <div className={styles.type}>({userData.type})</div>}
<div className={styles.separator} />
<div className={styles.menuCover}>
<span className={styles.backgroundSelection} style={{ top }} />
{menuItemsArr.map((item, i) => {
return (
<button
type='button'
className={`${styles.menuItem} ${selectedIndex === i ? styles.active : ''}`}
onClick={() => setSelectedIndex(i)}
key={`menu-${i + 1}`}>
<MenuIcons type={item} />
{!smallMenu && item}
</button>
);
})}
<span className={styles.topArrow} style={{ top }} />
</div>
<div className={styles.bottomContainer}>
<div className={styles.separator} />
<button type='button' className={styles.logoutCtr} onClick={() => signOut()}>
{smallMenu ? <Log /> : <div className={styles.logoutText}>Log out</div>}
</button>
<div className={styles.separator} />
<button type='button' className={styles.zoomCtr} onClick={() => setSmallMenu(val => !val)}>
{smallMenu ? <ZoomIn /> : <div className={styles.zoomOutText}>Small Menu</div>}
</button>
</div>
</div>
);
};
export default LeftMenu;
import Cross from '@components/Cross';
import SelectBox from '@components/SelectBox';
import styles from '@layouts_style/NavBar.module.sass';
import { DavinciLogo } from '@svg/Logo';
import { TInputValue } from '@ts/common';
import { Translations } from '@util/localize';
import { useRouter } from 'next/router';
import { useState } from 'react';
const NavBar = (): JSX.Element => {
const t = Translations();
const router = useRouter();
const { asPath, locale, pathname } = router;
const [menuOpened, setMenuOpened] = useState(false);
const ToggleLanguage = (val: TInputValue) => {
switch (val) {
case 'en':
router.push(pathname, asPath, { locale: 'en' });
break;
case 'de':
router.push(pathname, asPath, { locale: 'de' });
break;
default:
break;
}
};
return (
<div className={styles.container}>
<div className={styles.middleContainer}>
<div className={styles.title}>
<DavinciLogo />
</div>
<div className={styles.menu}>
<div className={styles.menuItem}>{t.howItWorks}</div>
<div className={styles.menuItem}>{t.gallery}</div>
<div className={styles.menuItem}>{t.prices}</div>
<div className={styles.menuItem}>{t.shipping}</div>
<div className={styles.langBar}>
<SelectBox
options={[
{ label: 'EN', value: 'en' },
{ label: 'DE', value: 'de' },
]}
onChange={selected => {
ToggleLanguage(selected.value || null);
}}
selectedValue={locale || 'en'}
placeholder=''
/>
</div>
</div>
<Cross menuOpened={menuOpened} clickHandler={setMenuOpened} />
</div>
</div>
);
};
export default NavBar;
import { CartContext } from '@ctx/CartContext';
import styles from '@layouts_style/Quantity.module.sass';
import { Translations } from '@util/localize';
import { normalizedCurrency } from '@util/normalize';
import React, { useContext } from 'react';
const Quantity = (): JSX.Element => {
const t = Translations();
const { currency, figureCount, figurePackageObj, setFigureCount, totalPrice } = useContext(CartContext);
const selectedPackage = figurePackageObj[`figure${figureCount}`];
return (
<div className={styles.container}>
<div className={styles.leftContainer}>
<img src={selectedPackage?.imgUrl} alt='sample_1' className={styles.sample} />
</div>
<div className={styles.rightContainer}>
<div>
<div className={styles.topic}>{t.numberOfPeople}</div>
<div className={styles.figureCount}>
<button
className={`${styles.figureCountItem} ${figureCount === 1 ? styles.selected : ''}`}
type='button'
onClick={() => {
setFigureCount(1);
}}>
1
</button>
<button
className={`${styles.figureCountItem} ${figureCount === 2 ? styles.selected : ''}`}
type='button'
onClick={() => {
setFigureCount(2);
}}>
2
</button>
<button
className={`${styles.figureCountItem} ${figureCount === 3 ? styles.selected : ''}`}
type='button'
onClick={() => {
setFigureCount(3);
}}>
3
</button>
<button
className={`${styles.figureCountItem} ${figureCount === 4 ? styles.selected : ''}`}
type='button'
onClick={() => {
setFigureCount(4);
}}>
4
</button>
<button
className={`${styles.figureCountItem} ${figureCount === 5 ? styles.selected : ''}`}
type='button'
onClick={() => {
setFigureCount(5);
}}>
5
</button>
<button
className={`${styles.figureCountItem} ${figureCount === 6 ? styles.selected : ''}`}
type='button'
onClick={() => {
setFigureCount(6);
}}>
6
</button>
</div>
</div>
<div>
<div className={styles.priceTable}>
<div className={styles.priceDesc}>
{figureCount} {t.personsAnimals}
</div>
<div className={styles.price}>
<div className={styles.previousPrice}>{normalizedCurrency(selectedPackage?.prev, currency)}</div>
<div className={styles.nowPrice}>{normalizedCurrency(selectedPackage?.now, currency)}</div>
</div>
</div>
<div className={styles.totalPriceCover}>
<span className={styles.totalPrice}>{normalizedCurrency(totalPrice, currency)}</span>
</div>
<div className={styles.expressDelivery}>
<div className={styles.blink} />
<span className='delivery_in'>{t.expressDeliveryIn}</span>
&nbsp;
<span className='delivery_days'>{t.just7Days}</span>
</div>
<div className={styles.controlBtn}>
<div className={styles.backBtn}>Back</div>
<div className={styles.nextBtn}>Next</div>
</div>
</div>
</div>
</div>
);
};
export default Quantity;
import EllipsisAnimator from '@components/EllipsisAnimator';
import styles from '@layouts_style/WaitingPage.module.sass';
import React from 'react';
const WaitingPage = (): JSX.Element => {
return (
<div className={styles.container}>
<div className={styles.ellipsisCtr}>
<EllipsisAnimator text='Checking' />
</div>
</div>
);
};
export default WaitingPage;
import en from '@translations/english';
import de from '@translations/german';
import { TTranslations } from '@ts/localize';
import { useRouter } from 'next/router';
export const Translations = (): TTranslations => {
const router = useRouter();
switch (router.locale) {
case 'en':
return en;
case 'de': // German
return de;
default:
return en;
}
};
export { en as english, de as german };
export const normalizedCurrency = (value: number, type = 'euro'): string => {
if (type === 'euro') {
return `${value},00 €`;
}
return `${value},00 $`;
};
export const addCurrency = (value: number, type = 'euro'): string => {
if (type === 'euro') {
return `${value} €`;
}
return `${value} $`;
};
export const intoString = (value: string | number): string => `${value}`;
export const userNameValidator = (userName: string): string => {
if (userName.trim().length === 0) {
return '';
}
if (/\W+/g.test(userName)) {
return 'Has invalid characters';
}
if (userName.length < 6) {
return 'Length should be above 6';
}
if (userName.length > 15) {
return `Maximum only 15 character, now(${userName.length})`;
}
return '';
};
export const passwordValidator = (password: string): string => {
if (password.trim().length === 0) {
return '';
}
if (password.length > 0 && password.length < 8) {
return 'Need at least 8 characters';
}
if (!/(?=.*?[A-Z])/g.test(password)) {
return 'Need at least one uppercase letter';
}
if (!/(?=.*?[a-z])/g.test(password)) {
return 'Need at least one lowercase letter';
}
if (!/(?=.*?[0-9])/g.test(password)) {
return 'Need at least one number';
}
if (!/(?=.*?[#?!@$%^&*-])/g.test(password)) {
return 'Need at least one special character';
}
if (password.length > 15) {
return `Maximum only 15 character, now(${password.length})`;
}
return '';
};
export const isEmpty = (val: string): boolean => val.trim().length === 0;
export const userNameValidatorBoolean = (userName: string): boolean => {
if (userName.trim().length === 0) {
return false;
}
if (/\W+/g.test(userName)) {
return false;
}
if (userName.length < 6) {
return false;
}
if (userName.length > 15) {
return false;
}
return true;
};
export const fistCapitalLetter = (val: string): string => (val.length > 0 ? val.charAt(0).toUpperCase() : 'A');
import { AnnotatedPrediction } from '@tensorflow-models/handpose';
type TFingerJoints = {
thumb: number[];
indexFinger: number[];
middleFinger: number[];
ringFinger: number[];
pinky: number[];
};
// Points for finger
const fingerJoints: TFingerJoints = {
thumb: [0, 1, 2, 3, 4],
indexFinger: [0, 5, 6, 7, 8],
middleFinger: [0, 9, 10, 11, 12],
ringFinger: [0, 13, 14, 15, 16],
pinky: [0, 17, 18, 19, 20],
};
// Infinity Gauntlet Style
const style = {
0: { color: 'yellow', size: 15 },
1: { color: 'gold', size: 6 },
2: { color: 'green', size: 10 }, // green
3: { color: 'gold', size: 6 },
4: { color: 'gold', size: 6 },
5: { color: 'purple', size: 10 }, // purple
6: { color: 'gold', size: 6 },
7: { color: 'gold', size: 6 },
8: { color: 'gold', size: 6 },
9: { color: 'blue', size: 10 }, // blue
10: { color: 'gold', size: 6 },
11: { color: 'gold', size: 6 },
12: { color: 'gold', size: 6 },
13: { color: 'red', size: 10 }, // red
14: { color: 'gold', size: 6 },
15: { color: 'gold', size: 6 },
16: { color: 'gold', size: 6 },
17: { color: 'orange', size: 10 }, // orange
18: { color: 'gold', size: 6 },
19: { color: 'gold', size: 6 },
20: { color: 'gold', size: 6 },
};
export const drawHand = (predictions: AnnotatedPrediction[], ctx: CanvasRenderingContext2D): void => {
if (predictions.length > 0) {
// predictions.forEach((prediction: AnnotatedPrediction) => {
// const { landmarks } = prediction;
// for (let j = 0; j < Object.keys(fingerJoints).length; j += 1) {
// const finger = Object.keys(fingerJoints)[j];
// for (let k = 0; k < fingerJoints[finger].length - 1; k += 1) {
// const firstJointIndex = fingerJoints[finger][k];
// const secondJointIndex = fingerJoints[finger][k + 1];
// ctx.beginPath();
// ctx.moveTo(landmarks[firstJointIndex][0], landmarks[firstJointIndex][1]);
// ctx.lineTo(landmarks[secondJointIndex][0], landmarks[secondJointIndex][1]);
// ctx.strokeStyle = 'plum';
// ctx.lineWidth = 4;
// ctx.stroke();
// }
// }
// for (let i = 0; i < landmarks.length; i += 1) {
// const x = landmarks[i][0];
// const y = landmarks[i][1];
// ctx.beginPath();
// ctx.arc(x, y, style[i].size, 0, 3 * Math.PI);
// ctx.fillStyle = style[i].color;
// ctx.fill();
// }
// });
if (predictions.length > 0) {
const predicted = predictions[0].landmarks;
if (predicted.length > 0) {
const xMidSum = predicted[0][0] + predicted[5][0] + predicted[17][0];
const yMidSum = predicted[0][1] + predicted[5][1] + predicted[17][1];
ctx.beginPath();
ctx.arc(parseFloat((xMidSum / 3).toFixed(4)), parseFloat((yMidSum / 3).toFixed(4)), 10, 0, 3 * Math.PI);
ctx.fillStyle = 'red';
ctx.fill();
}
}
}
};
import { useRouter } from "next/router";
import { Tlocale, Ttranslations } from "../types/localize";
import { en } from "../translations/english"
import { jp } from "../translations/japanese"
import { sin } from "../translations/sinhala"
export const selectedLocale = (): Ttranslations => {
const router = useRouter();
switch (router.locale) {
case "en":
return en;
case "jp":
return jp;
case "sin":
return sin;
default:
return en;
}
};
export const toggleLanguage = (locale: Tlocale) => {
const router = useRouter();
switch (locale) {
case "en":
router.push("/", "/", { locale: "en" });
break;
case "sin":
router.push("/", "/", { locale: "sin" });
break;
case "jp":
router.push("/", "/", { locale: "jp" });
break;
default:
break;
}
};
export {en as english, jp as japanese, sin as sinhala}
type TFingerJoints = {
thumb: number[];
indexFinger: number[];
middleFinger: number[];
ringFinger: number[];
pinky: number[];
};
// Points for finger
const fingerJoints: TFingerJoints = {
thumb: [0, 1, 2, 3, 4],
indexFinger: [0, 5, 6, 7, 8],
middleFinger: [0, 9, 10, 11, 12],
ringFinger: [0, 13, 14, 15, 16],
pinky: [0, 17, 18, 19, 20],
};
// Infinity Gauntlet Style
const style = {
0: { color: "yellow", size: 15 },
1: { color: "gold", size: 6 },
2: { color: "green", size: 10 },
3: { color: "gold", size: 6 },
4: { color: "gold", size: 6 },
5: { color: "purple", size: 10 },
6: { color: "gold", size: 6 },
7: { color: "gold", size: 6 },
8: { color: "gold", size: 6 },
9: { color: "blue", size: 10 },
10: { color: "gold", size: 6 },
11: { color: "gold", size: 6 },
12: { color: "gold", size: 6 },
13: { color: "red", size: 10 },
14: { color: "gold", size: 6 },
15: { color: "gold", size: 6 },
16: { color: "gold", size: 6 },
17: { color: "orange", size: 10 },
18: { color: "gold", size: 6 },
19: { color: "gold", size: 6 },
20: { color: "gold", size: 6 },
};
// Drawing function
export const drawHand = (predictions: any, ctx: any) => {
// Check if we have predictions
if (predictions.length > 0) {
// Loop through each prediction
predictions.forEach((prediction: any) => {
// Grab landmarks
const landmarks = prediction.landmarks;
// Loop through fingers
for (let j = 0; j < Object.keys(fingerJoints).length; j++) {
let finger = Object.keys(fingerJoints)[j];
// Loop through pairs of joints
for (let k = 0; k < fingerJoints[finger].length - 1; k++) {
// Get pairs of joints
const firstJointIndex = fingerJoints[finger][k];
const secondJointIndex = fingerJoints[finger][k + 1];
// Draw path
ctx.beginPath();
ctx.moveTo(
landmarks[firstJointIndex][0],
landmarks[firstJointIndex][1]
);
ctx.lineTo(
landmarks[secondJointIndex][0],
landmarks[secondJointIndex][1]
);
ctx.strokeStyle = "plum";
ctx.lineWidth = 4;
ctx.stroke();
}
}
// Loop through landmarks and draw em
for (let i = 0; i < landmarks.length; i++) {
// Get x point
const x = landmarks[i][0];
// Get y point
const y = landmarks[i][1];
// Start drawing
ctx.beginPath();
ctx.arc(x, y, style[i]["size"], 0, 3 * Math.PI);
// Set line color
ctx.fillStyle = style[i]["color"];
ctx.fill();
}
});
}
};
import Button from '@components/Button';
import styles from '@pages_style/404.module.sass';
import Image from 'next/image';
import { useRouter } from 'next/router';
import React from 'react';
import error from '../../public/images/error_404.svg';
const ErrorPage404 = (): JSX.Element => {
const router = useRouter();
return (
<div className={styles.container}>
<div className={styles.imageCover}>
<Image src={error} alt='workspace' layout='intrinsic' />
</div>
<div className={styles.message}>This page could not be found.</div>
<div className={styles.btnCtr}>
<Button
type='normal'
isDisabled={false}
text='GO HOME'
onClickHandler={() => {
router.push('/');
}}
/>
</div>
</div>
);
};
export default ErrorPage404;
import "../styles/common/normalize.css";
import "../styles/common/global.css";
import { AppProps } from "next/app";
import Head from "next/head";
import { CartContextProvider } from '@ctx/CartContext';
import { UserContextProvider } from '@ctx/UserContext';
import '@styles/globals.sass';
import type { AppProps } from 'next/app';
import Head from 'next/head';
import React from 'react';
function MyApp({ Component, pageProps }: AppProps): React.ReactElement {
const MyApp = ({ Component, pageProps }: AppProps): React.ReactElement => {
return (
<>
<Head>
<meta charSet="UTF-8" />
<title>{process.env.appName}</title>
<meta charSet='UTF-8' />
<title>{process.env.APP_NAME}</title>
<meta
name="viewport"
content="width=device-width, maximum-scale=1.0, initial-scale=1.0, user-scalable=no, shrink-to-fit=no"
/>
<meta name="author" content="SLIIT" />
<meta name="keywords" content="audio video conferencing" />
<meta name="description" content="4th year research" />
<meta name="theme-color" content="#000" />
<meta name="apple-mobile-web-app-status-bar-style" content="#000" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link
href="https://fonts.googleapis.com/css2?family=Abel&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Galada&display=swap"
rel="stylesheet"
/>
<link rel="preconnect" href="https://fonts.gstatic.com" />
<link
href="https://fonts.googleapis.com/css2?family=Quicksand:wght@400;600&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css?family=Arima+Madurai&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css?family=Montserrat:600&display=swap"
rel="stylesheet"
name='viewport'
content='width=device-width, maximum-scale=1.0, initial-scale=1.0, user-scalable=no, shrink-to-fit=no'
/>
<meta name='author' content='Duminda Kodagoda' />
<meta name='keywords' content='Davinci Arts' />
<meta name='description' content='Art for everyone' />
<meta name='theme-color' content='#000' />
<meta name='apple-mobile-web-app-status-bar-style' content='#000' />
</Head>
<Component {...pageProps} />
<UserContextProvider>
<CartContextProvider>
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
<Component {...pageProps} />
</CartContextProvider>
</UserContextProvider>
</>
);
}
};
export default MyApp;
// pages/_document.js
import { ServerStyleSheet } from "styled-components";
import Document, { DocumentContext } from "next/document";
export default class MyDocument extends Document {
static async getInitialProps(ctx: DocumentContext) {
const sheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage;
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) =>
sheet.collectStyles(<App {...props} />),
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
),
};
} finally {
sheet.seal();
}
}
}
import React from 'react';
import AuthCheck from 'src/common/ui/layouts/AuthCheck';
import LeftMenu from 'src/common/ui/layouts/LeftMenu';
const AdminPanel = (): JSX.Element => {
return (
<AuthCheck>
<>
<LeftMenu />
</>
</AuthCheck>
);
};
export default AdminPanel;
export default async (req, res) => {
try {
res.status(200).json({
success: true,
type: "success",
message: "successfully added",
});
} catch (error) {
res.status(400).json({
success: false,
type: "error",
message: "internal error",
});
}
};
import React from "react";
import styled from "styled-components";
const Auth = (): JSX.Element => {
return <Container>This is auth page</Container>;
};
const Container = styled.div`
width: 100%;
height: 100vh;
background: #fff;
`;
export default Auth;
import styles from '@pages_style/design.module.sass';
import { TTab } from '@ts/common';
import { Translations } from '@util/localize';
import React, { useState } from 'react';
import Quantity from 'src/common/ui/layouts/Quantity';
const Design = (): JSX.Element => {
const [selectedTab, setSelectedTab] = useState<TTab>('quantity');
const t = Translations();
const getTabBody = () => {
switch (selectedTab) {
case 'cart':
return <Quantity />;
case 'quantity':
return <Quantity />;
case 'size':
return <Quantity />;
case 'upload':
return <Quantity />;
default:
return <Quantity />;
}
};
return (
<div className={styles.container}>
<div className={styles.tabHeader}>
<button
type='button'
className={`${styles.tabHeaderItem} ${selectedTab === 'quantity' ? styles.active : ''}`}
onClick={() => {
setSelectedTab('quantity');
}}>
{t.quantity}
</button>
<button
type='button'
className={`${styles.tabHeaderItem} ${selectedTab === 'size' ? styles.active : ''}`}
onClick={() => {
setSelectedTab('size');
}}>
{t.size}
</button>
<button
type='button'
className={`${styles.tabHeaderItem} ${selectedTab === 'upload' ? styles.active : ''}`}
onClick={() => {
setSelectedTab('upload');
}}>
{t.upload}
</button>
<button
type='button'
className={`${styles.tabHeaderItem} ${selectedTab === 'cart' ? styles.active : ''}`}
onClick={() => {
setSelectedTab('cart');
}}>
{t.shippingCart}
</button>
</div>
<div className={styles.tabBody}>
{getTabBody()}
<div className={styles.deliveryDesc}>
<div className={styles.deliveryDescItem}>
<img className={styles.deliveryDescIcon} src='/images/truck.svg' alt='truck' />
{t.expressDeliveryDays}
</div>
<div className={styles.deliveryDescItem}>
<img className={styles.deliveryDescIcon} src='/images/hand-writing.svg' alt='hand-writing' />
{t.handmade}
</div>
<div className={styles.deliveryDescItem}>
<img className={styles.deliveryDescIcon} src='/images/customer.svg' alt='customer' />
{t.satisfactionGuarantee}
</div>
</div>
</div>
</div>
);
};
export default Design;
This diff is collapsed.
import Link from "next/link";
import React from "react";
import styled from "styled-components";
import Loader from '@components/Loader';
import { UserContext } from '@ctx/UserContext';
import styles from '@pages_style/login.module.sass';
import Image from 'next/image';
import React, { useContext, useEffect } from 'react';
import google from '../../public/images/google.svg';
import workspace from '../../public/images/workspace.svg';
const Login = (): JSX.Element => {
const { adminRoute, loading, signIn } = useContext(UserContext);
useEffect(() => {
adminRoute();
}, [adminRoute]);
return (
<Container>
<form action="" className="form">
<input
type="text"
placeholder="Input your name"
className="input_username"
/>
<Link href="/auth">
<input type="submit" value="Submit" />
</Link>
</form>
</Container>
<div className={styles.container}>
<div className={styles.imageCover}>
<Image src={workspace} alt='workspace' layout='intrinsic' />
</div>
<div className={styles.welcome}>
Welcome to <b>DAVINCI</b>
</div>
<button
onClick={() => {
signIn();
}}
className={styles.loginBtn}
type='button'>
<div className={styles.googleIconCover}>
<Image src={google} alt='googleImg' />
</div>
Login
</button>
<Loader show={loading} />
</div>
);
};
const Container = styled.div`
width: 100%;
height: 100vh;
background: #fff;
display: flex;
align-items: center;
justify-content: center;
.form {
background: #f1f1f1;
border: 1px solid #ccc;
width: 50%;
height: 50%;
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
}
.input_username {
margin-bottom: 16px;
}
`;
export default Login;
import Button from '@components/Button';
import Input from '@components/Input';
import { UserContext } from '@ctx/UserContext';
import useDebounce from '@hooks/useDebounce';
import { firestore } from '@lib/firebase';
import styles from '@pages_style/register.module.sass';
import { isEmpty, passwordValidator, userNameValidator, userNameValidatorBoolean } from '@util/normalize';
import React, { useCallback, useContext, useEffect, useState } from 'react';
import { colors } from 'styles/baseStyles';
type TAvailability = 'checking' | 'available' | 'already_taken' | 'error' | 'initial';
const Register = (): JSX.Element | null => {
const [displayName, setDisplayName] = useState('');
const debouncedDisplayName = useDebounce(displayName, 250) as string;
const [displayNameError, setDisplayNameError] = useState('');
const [password, setPassword] = useState('');
const [passwordError, setPasswordError] = useState('');
const [userNameAvailability, setUserNameAvailability] = useState<TAvailability>('checking');
const isInValid = isEmpty(displayName) || isEmpty(password) || !isEmpty(displayNameError) || !isEmpty(passwordError);
useEffect(() => {
setDisplayNameError(userNameValidator(displayName));
setPasswordError(passwordValidator(password));
}, [displayName, password]);
const { isLogged, userData } = useContext(UserContext);
const checkUsername = useCallback(async () => {
if (userNameValidatorBoolean(debouncedDisplayName)) {
try {
setUserNameAvailability('checking');
const ref = firestore.doc(`usernames/${debouncedDisplayName}`);
const { exists } = await ref.get();
if (!exists) {
setUserNameAvailability('available');
} else {
setUserNameAvailability('already_taken');
}
} catch (error) {
setUserNameAvailability('error');
}
} else {
setUserNameAvailability('initial');
}
}, [debouncedDisplayName]);
useEffect(() => {
checkUsername();
}, [checkUsername]);
useEffect(() => {
if (userData.displayName) {
setDisplayName(userData.displayName);
}
}, [userData]);
let availability = '';
let availability_color = colors.red;
if (userNameAvailability === 'already_taken') {
availability = `${debouncedDisplayName} is already taken!`;
availability_color = colors.red;
} else if (userNameAvailability === 'available') {
availability = `${debouncedDisplayName} is available`;
availability_color = colors.greenDark;
} else if (userNameAvailability === 'checking') {
availability = 'checking...';
availability_color = colors.black;
} else if (userNameAvailability === 'error') {
availability = 'System error type agin!';
availability_color = colors.red;
} else {
availability = '';
availability_color = colors.black;
}
if (!isLogged) return null;
return (
<div className={styles.container}>
<form className={styles.containerInner}>
<Input
placeholder='User Name'
label='User name :'
errorMsg={displayNameError}
value={displayName}
onChange={val => setDisplayName(val)}
type='text'
autoComplete='username'
required
/>
<Input
placeholder='User Name'
label=''
errorMsg=''
value={displayName}
onChange={val => setDisplayName(val)}
type='hidden'
autoComplete='username'
required
/>
<Input
placeholder='Password'
label='Password :'
errorMsg={passwordError}
value={password}
onChange={val => setPassword(val)}
type='password'
autoComplete='new-password'
required
/>
<Button
type='submit'
text='Register'
isDisabled={isInValid}
onClickHandler={() => {
if (!isInValid) {
// eslint-disable-next-line no-console
console.log('test=-->');
}
}}
/>
<div style={{ color: availability_color }}>{availability}</div>
</form>
</div>
);
};
export default Register;
*,
*::after,
*::before {
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-webkit-tap-highlight-color: transparent;
box-sizing: border-box;
}
html,
body {
font-family: "Abel", sans-serif;
font-size: 16px;
line-height: 1.6;
margin: 0;
padding: 0;
background-color: #000;
color: #000;
width: 100%;
height: 100%;
-webkit-touch-callout: none;
user-select: none;
}
html {
overflow-x: hidden;
}
body {
-webkit-font-smoothing: antialiased;
-webkit-text-size-adjust: 100%;
font-weight: 400;
}
h1 {
font-size: 36px;
}
h2 {
font-size: 30px;
}
h3 {
font-size: 24px;
}
h4 {
font-size: 20px;
}
h5 {
font-size: 18px;
}
h6 {
font-size: 16px;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: "Segoe UI", Arial, sans-serif;
font-weight: 400;
margin: 10px 0;
}
hr {
border: 0;
border-top: 1px solid #eee;
margin: 20px 0;
}
a {
color: inherit;
text-decoration: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
td,
th {
padding: 0;
}
em {
font-style: italic;
}
p {
margin: 0 0 20px 0;
font-weight: 400;
font-size: 15px;
}
i {
line-height: 0;
text-align: center;
vertical-align: middle;
}
::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
background-color: #000;
}
::-webkit-scrollbar {
width: 8px;
background-color: #000;
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
background-color: #ccc;
background-clip: content-box;
}
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in iOS.
*/
html {
line-height: 1.15; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers.
*/
body {
margin: 0;
}
/**
* Render the `main` element consistently in IE.
*/
main {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* Remove the gray background on active links in IE 10.
*/
a {
background-color: transparent;
}
/**
* 1. Remove the bottom border in Chrome 57-
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Remove the border on images inside links in IE 10.
*/
img {
border-style: none;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers.
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
margin: 0; /* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input { /* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select { /* 1 */
text-transform: none;
}
/**
* Correct the inability to style clickable types in iOS and Safari.
*/
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
vertical-align: baseline;
}
/**
* Remove the default vertical scrollbar in IE 10+.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10.
* 2. Remove the padding in IE 10.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in Edge, IE 10+, and Firefox.
*/
details {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Misc
========================================================================== */
/**
* Add the correct display in IE 10+.
*/
template {
display: none;
}
/**
* Add the correct display in IE 10.
*/
[hidden] {
display: none;
}
@import './common/_util'
.container
display: flex
align-items: center
justify-content: center
flex-direction: column
gap: 16px
width: 100vw
height: 100vh
.imageCover
width: calc(100% - 32px)
height: auto
display: flex
align-items: center
justify-content: center
+minDesktopSM
width: 400px
.message
font-size: 1.5rem
padding: 1em 0.5em
margin-top: 1em
text-align: center
font-weight: 600
.btnCtr
width: 200px
+minDesktopSM
width: 300px
// --- Breakpoints
export const maxMobile = 576; // (for phones)
export const minTablet = 576; // (for tablet)
export const minTabletLC = 769; // (landscape of tablet)
export const minDesktopSM = 992; // (for small Laptop)
export const minDesktopLG = 1201; // (for large laptop)
export const min4K = 1441; // (for 4k)
export const colors = {
activeText: '#08090a',
backgroundColor: '#eef0f1',
disabledText: '#d3d3d3',
navbarBackground: '#fff',
black: '#08090a',
blue: '#20639b',
blueDark: '#173f5f',
goldenBrown: '#996515',
gray: '#dad8db',
grayDark: '#b5bdc4',
grayLight: '#f7f7f7',
green: '#88d840',
greenDark: '#247209',
greenLight: '#67b826',
orange: '#f77f00',
red: '#e10600',
redDark: '#800500',
royalGold: '#f5bd02',
white: '#fff',
yellow: '#fcbf49',
};
html
line-height: 1.15
-webkit-text-size-adjust: 100%
body
margin: 0
main
display: block
h1
font-size: 2em
margin: 0.67em 0
hr
box-sizing: content-box
height: 0
overflow: visible
pre
font-family: monospace, monospace
font-size: 1em
a
background-color: transparent
abbr[title]
border-bottom: none
text-decoration: underline
text-decoration: underline dotted
b,
strong
font-weight: bolder
code,
kbd,
samp
font-family: monospace, monospace
font-size: 1em
small
font-size: 80%
sub,
sup
font-size: 75%
line-height: 0
position: relative
vertical-align: baseline
sub
bottom: -0.25em
sup
top: -0.5em
img
border-style: none
button,
input,
optgroup,
select,
textarea
font-family: inherit
font-size: 100%
line-height: 1.15
margin: 0
button,
input
overflow: visible
button,
select
text-transform: none
button,
[type='button'],
[type='reset'],
[type='submit']
-webkit-appearance: button
button::-moz-focus-inner,
[type='button']::-moz-focus-inner,
[type='reset']::-moz-focus-inner,
[type='submit']::-moz-focus-inner
border-style: none
padding: 0
button:-moz-focusring,
[type='button']:-moz-focusring,
[type='reset']:-moz-focusring,
[type='submit']:-moz-focusring
outline: 1px dotted ButtonText
fieldset
padding: 0.35em 0.75em 0.625em
legend
box-sizing: border-box
color: inherit
display: table
max-width: 100%
padding: 0
white-space: normal
progress
vertical-align: baseline
textarea
overflow: auto
[type='checkbox'],
[type='radio']
box-sizing: border-box
padding: 0
[type='number']::-webkit-inner-spin-button,
[type='number']::-webkit-outer-spin-button
height: auto
[type='search']
-webkit-appearance: textfield
outline-offset: -2px
[type='search']::-webkit-search-decoration
-webkit-appearance: none
::-webkit-file-upload-button
-webkit-appearance: button
font: inherit
details
display: block
summary
display: list-item
template
display: none
[hidden]
display: none
// Variables -->......................................
$activeText: #08090a
$backgroundColor: #eef0f1
$bg: #eef0f1
$black: #08090a
$black1: #000
$black2: #333
$black3: #444
$black4: #666
$blue: #20639b
$blue_dark: #3b49df
$dark_blue: #173f5f
$dark_gray: #b5bdc4
$dark_green: #247209
$dark_red: #800500
$disabledText: #d3d3d3
$goldenBrown: #996515
$gray: #dad8db
$gray: #b5bdc4
$green: #88d840
$green: #3bdf72
$light_gray: #f7f7f7
$light_green: #67b826
$navbarBackground: #fff
$orange: #f77f00
$red: #e10600
$red: #df3b3b
$royalGold: #f5bd02
$text: #08090a
$white: #fff
$yellow: #fcbf49
$maxMobile: 576 // (for phones)
$minTablet: 576 // (for tablet)
$minTabletLC: 769 // (landscape of tablet)
$minDesktopSM: 992 // (for small Laptop)
$minDesktopLG: 1201 // (for large laptop)
$min4K: 1441 // (for 4k)
$barHeight: 4
$barWidth: $barHeight * 7
$marginTwo: $barHeight * 2
$marginFour: $barHeight * 4
$marginFive: $barHeight * 5
$menuHeight: 60
// Mixins -->......................................
=maxMobile
@media only screen and (max-width: $maxMobile + px)
@content
=minTablet
@media only screen and (min-width: $minTablet + px)
@content
=minTabletLC
@media only screen and (min-width: $minTabletLC + px)
@content
=minDesktopSM
@media only screen and (min-width: $minDesktopSM + px)
@content
=minDesktopLG
@media only screen and (min-width: $minDesktopLG + px)
@content
=min4K
@media only screen and (min-width: $min4K + px)
@content
=keyframes($name)
@-webkit-keyframes #{$name}
@content
@-moz-keyframes #{$name}
@content
@-ms-keyframes #{$name}
@content
@keyframes #{$name}
@content
// COMMON CLASSES -----------------------------------
=clearfix
&:after,
&:before
content: ""
display: table
&:after
clear: both
=flex_center_vertically($height)
display: flex
justify-content: center
flex-direction: column
height: $height
=text_center($line-height)
text-align: center
line-height: $line-height
=absolute_center
position: absolute
top: 50%
left: 50%
transform: translate(-50%, -50%)
=flex_center
display: flex
justify-content: center
align-items: center
=hidden
display: none
=show
display: block
=noSelect
-webkit-touch-callout: none
user-select: none
=noCallout
-webkit-touch-callout: none
=noAction
touch-action: none
=imgNoClick
position: relative
=imgNoClickCover
position: absolute
top: 0
bottom: 0
left: 0
right: 0
height: 100%
width: 100%
=focus_ring_issue
outline: -webkit-focus-ring-color auto 5px
// write this for &:focus
=tap_highlight_issue
-webkit-tap-highlight-color: rgba(0, 0, 0, 0)
-webkit-tap-highlight-color: transparent
=break_words
word-wrap: break-word
=wrap_words
overflow-wrap: break-word
word-wrap: break-word
hyphens: auto
=reset_button
appearance: none
border: none
background: none
@import './common/_util'
.container
display: flex
align-items: center
justify-content: center
flex-wrap: wrap
max-width: $minDesktopLG + px
padding: 0 16px
margin: auto
.tabHeader
display: flex
align-items: center
justify-content: center
column-gap: 32px
row-gap: 8px
width: 100%
flex-wrap: wrap
margin: 32px 0 16px
.tabHeaderItem
cursor: pointer
text-transform: uppercase
color: $disabledText
.active
color: $activeText
.tabBody
width: 100%
.deliveryDesc
margin-top: 0
display: none
+minDesktopSM
margin-top: 60px
display: flex
align-items: center
justify-content: center
gap: 40px
flex-wrap: wrap
.deliveryDescItem
display: flex
align-items: center
justify-content: center
gap: 10px
flex-wrap: wrap
border-bottom: 2px dotted $black
color: $black
width: 300px
height: 60px
.deliveryDescIcon
width: 40px
height: 40px
@import './common/_util'
@import './common/_normalize'
*,
*::after,
*::before
+tap_highlight_issue
box-sizing: border-box
html,
body
font-family: sans-serif
font-size: 16px
line-height: 1.6
margin: 0
padding: 0
background-color: $white
color: $black
width: 100%
height: 100%
-webkit-touch-callout: none
user-select: none
html
overflow-x: hidden
body
-webkit-font-smoothing: antialiased
-webkit-text-size-adjust: 100%
font-weight: 400
h1
font-size: 36px
h2
font-size: 30px
h3
font-size: 24px
h4
font-size: 20px
h5
font-size: 18px
h6
font-size: 16px
h1,
h2,
h3,
h4,
h5,
h6
font-family: 'Segoe UI', Arial, sans-serif
font-weight: bold
margin: 10px 0
hr
border: 0
border-top: 1px solid $gray
margin: 20px 0
a
color: inherit
text-decoration: none
table
border-collapse: collapse
border-spacing: 0
td,
th
padding: 0
p
margin: 0 0 20px 0
font-weight: 400
font-size: 15px
::-webkit-scrollbar-track
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3)
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3)
background-color: $black
::-webkit-scrollbar
width: 8px
background-color: $black
::-webkit-scrollbar-thumb
border-radius: 10px
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3)
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3)
background-color: $gray
background-clip: content-box
input[type='hidden']
margin: 0 !important
line-height: 0 !important
padding: 0 !important
width: 0 !important
height: 0 !important
button
+reset_button
@import './common/_util'
.container
background: $black1
.videoContainer
height: calc(100vh - 60px)
padding: 20px
.videoContainerInner
width: 100%
height: 100%
border-radius: 10px
display: flex
align-items: center
justify-content: center
.videoMenuLeft
flex-grow: 0
flex-shrink: 0
width: 200px
height: 100%
border-radius: 10px
display: flex
flex-direction: column
overflow-y: scroll
&::-webkit-scrollbar
display: none
-ms-overflow-style: none
scrollbar-width: none
.videoItem
flex-shrink: 0
flex-grow: 0
width: 100%
height: 200px
color: $white
background: $black2
border-radius: 10px
margin-bottom: 10px
display: flex
align-items: center
justify-content: center
font-size: 20px
font-weight: 900
.videoMenuMiddle
flex-grow: 1
height: 100%
width: 100%
margin: 0 20px
overflow: hidden
display: flex
align-items: center
justify-content: center
border-radius: 10px
position: relative
.videoObject
width: 100% !important
height: auto !important
transform: scaleX(-1)
.videoPlaceholder
background: $black3
width: 100%
height: 100%
display: flex
align-items: center
justify-content: center
flex-direction: column
color: $white
font-size: 3rem
.canvasObject
position: absolute
width: 100%
height: 100%
transform: scaleX(-1)
.videoMenuRight
flex-grow: 0
flex-shrink: 0
background: $black2
width: 300px
height: 100%
border-radius: 10px
display: flex
justify-content: space-between
flex-direction: column
.chatItemCover
flex-grow: 1
font-size: 18px
display: flex
align-items: flex-start
justify-content: flex-start
flex-direction: column
padding: 15px 15px 0px
.chatItem
display: inline-block
margin-bottom: 15px
border-radius: 10px 20px 20px 0px
color: $white
background: $black4
padding: 0.5em 1em
font-weight: 900
.chatInput
flex-grow: 0
flex-shrink: 0
border-top: 10px solid $black !important
.chatInputItem
opacity: 1
border: none
outline: none
width: 100%
padding: 0.8em
background: $black3!important
background-image: none !important
border-radius: 0 0 10px 10px
font-size: 18px
color: $white
font-weight: 900
.bottomBar
width: 100%
height: 60px
background: $black2
display: flex
align-items: center
justify-content: center
padding: 0 20px
.iconBottomBar
cursor: pointer
height: 40px
width: auto
.left
flex-grow: 1
display: flex
align-items: center
justify-content: flex-start
column-gap: 20px
.leftIcons
cursor: pointer
height: 30px
width: auto
.middle
display: flex
align-items: center
justify-content: center
background: $black1
padding: 10px 20px
border-radius: 10px
column-gap: 20px
.middleIcons
height: 30px
width: auto
cursor: pointer
.right
flex-grow: 1
display: flex
align-items: center
justify-content: flex-end
column-gap: 20px
.rightIcons
cursor: pointer
height: 30px
width: auto
@import './common/_util'
.loaderCover
height: 50px
.container
display: flex
align-items: center
justify-content: center
flex-direction: column
width: 100vw
height: 100vh
.loginBtn
color: $black
cursor: pointer
border: 1px solid $black
display: flex
align-items: center
justify-content: center
width: 200px
height: 60px
border-radius: 50px
font-size: 1.5rem
font-weight: 600
background: $white
margin-bottom: 1rem
.googleIconCover
width: 40px
height: 40px
margin-right: 8px
position: relative
.welcome
font-size: 1.5rem
margin-bottom: 1rem
+minDesktopSM
font-size: 2rem
.imageCover
width: calc(100% - 32px)
height: auto
display: flex
align-items: center
justify-content: center
margin-bottom: 1rem
+minDesktopSM
width: 400px
@import './common/_util'
.container
display: flex
align-items: center
justify-content: center
width: 100vw
height: 100vh
.containerInner
display: flex
align-items: center
justify-content: center
flex: 0 1 auto
width: 250px
flex-direction: column
gap: 16px
@import '../../common/_util'
.container
background: $black
color: $white
height: 40px
width: 100%
display: flex
align-items: center
justify-content: center
border-radius: 4px
margin-top: 16px
cursor: pointer
.disabled
background: $gray
cursor: not-allowed
.submitBtn
appearance: none
outline: none
border: none
background: $black
color: $white
height: 40px
width: 100%
display: flex
align-items: center
justify-content: center
border-radius: 4px
margin-top: 16px
cursor: pointer
.disabled
background: $gray
cursor: not-allowed
@import '../../common/_util'
.container
width: $barWidth +px
height: $marginFive + px
position: relative
margin: 50px 0
transform: rotate(0deg)
transition: 0.5s ease-in-out
cursor: pointer
+minDesktopSM
display: none
& > span
display: block
position: absolute
height: $barHeight + px
width: 100%
background: $black
border-radius: $barHeight + px
opacity: 1
left: 0
transform: rotate(0deg)
transition: 0.25s ease-in-out
& span:nth-child(1)
top: 0px
& span:nth-child(2),
& span:nth-child(3)
top: $marginTwo + px
& span:nth-child(4)
top: $marginFour + px
&.open span:nth-child(1)
top: $marginTwo + px
width: 0%
left: 50%
&.open span:nth-child(2)
transform: rotate(45deg)
&.open span:nth-child(3)
transform: rotate(-45deg)
&.open span:nth-child(4)
top: $marginTwo + px
width: 0%
left: 50%
@import '../../common/_util'
@keyframes ellipsis
0%
content: ''
25%
content: '.'
50%
content: '..'
75%
content: '...'
100%
content: ''
.container
&::after
display: inline-block
animation: ellipsis steps(1, end) 1s infinite
content: ''
@import '../../common/_util'
.container
width: 100%
font-weight: normal
position: relative
.inputElementCtr
position: relative
.labelElement
display: inline-block
margin-bottom: 8px
font-weight: bold
.errorMsg
display: none
margin-top: 8px
font-size: 0.8571rem
color: $red
.error
display: block
.cross
position: absolute
top: 50%
right: 0px
width: 30px
height: 40px
transform: translateY(-50%)
user-select: none
cursor: pointer
&::before,
&::after
position: absolute
left: 50%
top: 50%
content: ''
height: 16px
width: 1px
background-color: $black
&::before
transform: translate(-50%, -50%) rotate(45deg)
&::after
transform: translate(-50%, -50%) rotate(-45deg)
.inputElement
display: block
width: 100%
padding: 0.375rem 0.75rem
padding-right: 30px
font-size: 1rem
font-weight: 400
line-height: 1.5
height: 40px
color: $black
background-color: $white
background-clip: padding-box
border: 1px solid $dark_gray
appearance: none
border-radius: 3px
transition: border-color 0.15s ease-in-out
outline: none
caret-color: $blue
display: block
line-height: 38px
&:focus
border-color: $dark_gray
&, .error
border: 1px solid $red
&:focus
border-color: $red
@import '../../common/_util'
.container
border-radius: 50%
display: flex
align-items: center
justify-content: center
@import '../../common/_util'
@keyframes spin
0%
transform: rotate(0deg)
100%
transform: rotate(360deg)
.container
border: 10px solid $gray
border-top: 10px solid $black
border-radius: 50%
width: 50px
height: 50px
animation: spin 0.5s linear infinite
opacity: 0
.show
opacity: 1
@import '../../common/_util'
.container
display: flex
align-items: center
justify-content: center
flex-direction: column
gap: 16px
width: 100vw
height: 100vh
.imageCover
width: calc(100% - 32px)
height: auto
display: flex
align-items: center
justify-content: center
+minDesktopSM
width: 400px
.message
font-size: 1.5rem
padding: 1em 0.5em
margin-top: 1em
text-align: center
font-weight: 600
.btnCtr
width: 200px
+minDesktopSM
width: 300px
@import '../../common/_util'
.container
height: 100vh
background: $black
color: $white
display: flex
justify-content: flex-start
flex-direction: column
.profileImg
height: auto
border-radius: 50%
border: 2px solid $gray
.profileCover
display: flex
align-items: center
justify-content: center
padding: 16px 0
.profileName
display: flex
align-items: center
justify-content: center
.type
display: flex
align-items: center
justify-content: center
text-transform: uppercase
font-weight: 900
.separator
height: 2px
background: $dark_gray
border-radius: 4px
width: 80%
margin: 16px auto
.menuCover
display: flex
align-items: center
justify-content: center
flex-direction: column
position: relative
.topArrow
content: ''
position: absolute
right: -1px
height: 0
width: 0
border: 30px solid transparent
border-right: 10px solid $white
pointer-events: none
transition: top 0.2s ease-in-out
transform-origin: top right
.backgroundSelection
content: ''
position: absolute
right: 0
height: $menuHeight + px
width: 100%
background: $royalGold
pointer-events: none
transition: top 0.2s ease-in-out
transform-origin: top right
.menuItem
text-transform: uppercase
cursor: pointer
width: 100%
height: $menuHeight + px
display: flex
align-items: center
justify-content: flex-start
padding: 0 20px
color: $white
pointer-events: auto
position: relative
z-index: 1
font-weight: 400
gap: 8px
> svg
flex: none
.active
color: $black
font-weight: 600
.bottomContainer
display: flex
align-items: center
justify-content: flex-end
flex-direction: column
flex-grow: 1
padding: 16px 0
.zoomCtr
text-transform: uppercase
display: flex
align-items: center
justify-content: center
gap: 8px
color: $white
> svg
cursor: pointer
.logoutText
font-weight: 600px
text-transform: uppercase
.zoomOutText
font-weight: 600px
text-transform: uppercase
cursor: pointer
.logoutCtr
color: $white
cursor: pointer
@import '../../common/_util'
.container
height: 60px
width: 100%
background: $navbarBackground
display: flex
align-items: center
justify-content: center
.middleContainer
display: flex
align-items: center
justify-content: space-between
flex: 0 1 ($minDesktopLG + px)
padding: 0 16px
.title
.davinci_logo
height: 20px
width: auto
.menu
display: none
+minDesktopSM
display: flex
align-items: center
justify-content: center
gap: 16px
.menuItem
text-transform: uppercase
.langBar
padding: 0 20px
border-radius: 50px
background: $black
@import '../../common/_util'
.container
display: flex
align-items: stretch
justify-content: center
flex-wrap: wrap
.sample
max-width: 500px
height: auto
display: block
+maxMobile
width: calc(100vw - 32px)
.leftContainer
flex-basis: 100%
display: flex
align-items: center
justify-content: center
+minDesktopSM
flex-basis: 50%
justify-content: flex-end
.rightContainer
flex-basis: 100%
padding: 32px 0
max-width: 500px
display: flex
justify-content: space-between
flex-direction: column
+minDesktopSM
flex-basis: 50%
padding: 0 32px
.topic
text-transform: uppercase
align-self: center
text-align: center
font-size: 1rem
font-weight: 500
position: relative
padding-bottom: 8px
margin-bottom: 32px
&::after
content: ''
position: absolute
left: 50%
bottom: 2px
transform: translate(-50%, -50%)
width: 50%
height: 2px
background: $goldenBrown
border-radius: 6px
+minDesktopSM
font-size: 1.6rem
.figureCount
display: grid
grid-template-columns: repeat(3, 1fr)
gap: 16px
margin: 16px 0
.figureCountItem
padding: 8px
border-radius: 4px
text-align: center
font-weight: 600
cursor: pointer
background: $gray
color: $black
.selected
background: $black
color: $white
.priceTable
border-top: 1px solid $goldenBrown
display: grid
grid-template-columns: repeat(2, auto)
.priceDesc
padding: 16px 0
.price
display: flex
align-items: center
justify-content: flex-end
gap: 8px
.previousPrice
text-decoration: line-through
font-size: 0.8rem
.nowPrice
color: $red
font-weight: 600
.totalPriceCover
border-top: 1px solid $goldenBrown
display: flex
align-items: center
justify-content: flex-end
.totalPrice
border-bottom: 2px solid $goldenBrown
position: relative
padding-bottom: 2px
color: $red
font-weight: 900
margin-bottom: 16px
&::after
content: ''
position: absolute
left: 50%
bottom: 1px
transform: translate(-50%, -50%)
width: 100%
height: 2px
background: $goldenBrown
border-radius: 6px
.controlBtn
width: 100%
display: flex
align-items: center
justify-content: center
flex-wrap: wrap-reverse
margin: 16px 0
gap: 16px
.expressDelivery
display: flex
align-items: center
justify-content: center
.delivery_in
text-transform: capitalize
.delivery_days
color: $green
font-weight: 700
.blink
width: 10px
height: 10px
background: $green
border-radius: 100%
margin-right: 10px
.backBtn
border: 1px solid $goldenBrown
width: 200px
height: 50px
display: flex
align-items: center
justify-content: center
border-radius: 50px
font-weight: 600
color: $goldenBrown
background: $white
text-transform: uppercase
.nextBtn
border: 1px solid $goldenBrown
width: 200px
height: 50px
display: flex
align-items: center
justify-content: center
border-radius: 50px
font-weight: 600
color: $white
background: $goldenBrown
text-transform: uppercase
@import '../../common/_util'
.container
font-size: 1.5rem
font-weight: 600
display: flex
align-items: center
justify-content: center
width: 100vw
height: 100vh
.ellipsisCtr
width: 150px
{
"compilerOptions": {
"baseUrl": ".",
"allowJs": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"importHelpers": true,
"isolatedModules": true,
"jsx": "preserve",
"lib": ["dom", "es7"],
"lib": ["dom", "dom.iterable", "esnext"],
"module": "esnext",
"moduleResolution": "node",
"noEmit": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"plugins": [
{
"name": "@typescript-eslint"
}
],
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"suppressImplicitAnyIndexErrors": true,
"target": "es5"
"target": "es5",
"allowSyntheticDefaultImports": true, // me
"importHelpers": true, // me
"noImplicitAny": true, // me
"noImplicitReturns": true, // me
"noImplicitThis": true, // me
"noUnusedLocals": true, // me
"suppressImplicitAnyIndexErrors": true, // me
"baseUrl": ".", //me
"paths": {
"@components_style/*": ["styles/ui/components/*"],
"@components/*": ["src/common/ui/components/*"],
"@ctx/*": ["src/common/ctx/*"],
"@data/*": ["src/common/data/*"],
"@hooks/*": ["src/common/hooks/*"],
"@images/*": ["public/images/*"],
"@layouts_style/*": ["styles/ui/layouts/*"],
"@layouts/*": ["src/common/ui/layouts/*"],
"@lib/*": ["src/common/lib/*"],
"@pages_style/*": ["styles/*"],
"@styles/*": ["styles/*"],
"@svg/*": ["src/common/svg/*"],
"@translations/*": ["src/common/translations/*"],
"@ts/*": ["src/common/ts/*"],
"@util/*": ["src/common/util/*"],
"@public/*": ["public/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
"exclude": ["node_modules", ".github", ".vscode"],
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
}
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment