init
113
.eslintrc.js
Normal file
|
@ -0,0 +1,113 @@
|
|||
module.exports = {
|
||||
env: {
|
||||
node: true,
|
||||
es6: true
|
||||
},
|
||||
parserOptions: {
|
||||
ecmaVersion: 13,
|
||||
sourceType: 'module',
|
||||
jsx: true,
|
||||
project: './tsconfig.json'
|
||||
},
|
||||
ignorePatterns: ['node_modules/*'],
|
||||
extends: ['eslint:recommended', 'prettier'],
|
||||
overrides: [
|
||||
{
|
||||
files: ['**/*.ts', '**/*.tsx'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
settings: {
|
||||
react: { version: 'detect' },
|
||||
'import/resolver': {
|
||||
typescript: {}
|
||||
}
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
node: true,
|
||||
es6: true
|
||||
},
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:import/errors',
|
||||
'plugin:import/warnings',
|
||||
'plugin:import/typescript',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:react/recommended',
|
||||
'plugin:react-hooks/recommended',
|
||||
'plugin:jsx-a11y/recommended',
|
||||
'prettier'
|
||||
],
|
||||
plugins: ['formatjs'],
|
||||
rules: {
|
||||
curly: ['warn', 'multi-line'],
|
||||
'no-console': ['warn', { allow: ['warn', 'error', 'assert'] }],
|
||||
|
||||
'no-restricted-imports': [
|
||||
'warn',
|
||||
{
|
||||
patterns: ['features/*/*']
|
||||
}
|
||||
],
|
||||
'import/order': [
|
||||
'warn',
|
||||
{
|
||||
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
|
||||
pathGroups: [
|
||||
{
|
||||
pattern: 'react',
|
||||
group: 'external',
|
||||
position: 'before'
|
||||
},
|
||||
{
|
||||
pattern: 'react*',
|
||||
group: 'external',
|
||||
position: 'before'
|
||||
},
|
||||
{
|
||||
pattern: './src/*',
|
||||
group: 'internal',
|
||||
position: 'after'
|
||||
},
|
||||
{
|
||||
pattern: './*.[^(s?)css]',
|
||||
group: 'index',
|
||||
position: 'before'
|
||||
},
|
||||
{
|
||||
pattern: './*.module.scss',
|
||||
group: 'index',
|
||||
position: 'after'
|
||||
}
|
||||
],
|
||||
pathGroupsExcludedImportTypes: ['react']
|
||||
}
|
||||
],
|
||||
'import/default': 'off',
|
||||
'import/no-named-as-default-member': 'off',
|
||||
'import/no-named-as-default': 'off',
|
||||
|
||||
'react/display-name': 'warn',
|
||||
'react/prop-types': 'off',
|
||||
'react/react-in-jsx-scope': 'off',
|
||||
|
||||
'jsx-a11y/anchor-is-valid': 'off',
|
||||
'jsx-a11y/no-static-element-interactions': 'off',
|
||||
'jsx-a11y/click-events-have-key-events': 'off',
|
||||
|
||||
'@typescript-eslint/no-unused-vars': ['warn', { varsIgnorePattern: '^_' }],
|
||||
'@typescript-eslint/no-empty-interface': 'warn',
|
||||
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-inferrable-types': 'off',
|
||||
|
||||
'formatjs/enforce-id': 'off',
|
||||
'formatjs/no-id': 'error',
|
||||
'formatjs/enforce-default-message': 'error',
|
||||
'formatjs/enforce-description': 'error'
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
23
.gitignore
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
5
.idea/.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
15
.idea/git_toolbox_prj.xml
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GitToolBoxProjectSettings">
|
||||
<option name="commitMessageIssueKeyValidationOverride">
|
||||
<BoolValueOverride>
|
||||
<option name="enabled" value="true" />
|
||||
</BoolValueOverride>
|
||||
</option>
|
||||
<option name="commitMessageValidationEnabledOverride">
|
||||
<BoolValueOverride>
|
||||
<option name="enabled" value="true" />
|
||||
</BoolValueOverride>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
12
.idea/hakaton.iml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
6
.idea/inspectionProfiles/Project_Default.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
</profile>
|
||||
</component>
|
6
.idea/jsLinters/eslint.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EslintConfiguration">
|
||||
<option name="fix-on-save" value="true" />
|
||||
</component>
|
||||
</project>
|
8
.idea/modules.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/hakaton.iml" filepath="$PROJECT_DIR$/.idea/hakaton.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
7
.idea/prettier.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="PrettierConfiguration">
|
||||
<option name="myConfigurationMode" value="AUTOMATIC" />
|
||||
<option name="myRunOnSave" value="true" />
|
||||
</component>
|
||||
</project>
|
6
.idea/vcs.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
4
.idea/watcherTasks.xml
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectTasksOptions" suppressed-tasks="SCSS" />
|
||||
</project>
|
2
.prettierignore
Normal file
|
@ -0,0 +1,2 @@
|
|||
/build
|
||||
/coverage
|
12
.prettierrc.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
module.exports = {
|
||||
arrowParens: 'always',
|
||||
bracketSameLine: true,
|
||||
bracketSpacing: true,
|
||||
endOfLine: 'auto',
|
||||
printWidth: 120,
|
||||
semi: true,
|
||||
singleQuote: true,
|
||||
tabWidth: 2,
|
||||
trailingComma: 'none',
|
||||
useTabs: false
|
||||
};
|
46
README.md
Normal file
|
@ -0,0 +1,46 @@
|
|||
# Getting Started with Create React App
|
||||
|
||||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
||||
|
||||
## Available Scripts
|
||||
|
||||
In the project directory, you can run:
|
||||
|
||||
### `yarn start`
|
||||
|
||||
Runs the app in the development mode.\
|
||||
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
|
||||
|
||||
The page will reload if you make edits.\
|
||||
You will also see any lint errors in the console.
|
||||
|
||||
### `yarn test`
|
||||
|
||||
Launches the test runner in the interactive watch mode.\
|
||||
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
||||
|
||||
### `yarn build`
|
||||
|
||||
Builds the app for production to the `build` folder.\
|
||||
It correctly bundles React in production mode and optimizes the build for the best performance.
|
||||
|
||||
The build is minified and the filenames include the hashes.\
|
||||
Your app is ready to be deployed!
|
||||
|
||||
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
||||
|
||||
### `yarn eject`
|
||||
|
||||
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
|
||||
|
||||
If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
|
||||
|
||||
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
|
||||
|
||||
You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
|
||||
|
||||
## Learn More
|
||||
|
||||
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
|
||||
|
||||
To learn React, check out the [React documentation](https://reactjs.org/).
|
74
package.json
Normal file
|
@ -0,0 +1,74 @@
|
|||
{
|
||||
"name": "hakaton",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@react-pdf/renderer": "^3.1.12",
|
||||
"@seznam/compose-react-refs": "^1.0.6",
|
||||
"@tanstack/react-query": "^4.33.0",
|
||||
"@testing-library/jest-dom": "^5.14.1",
|
||||
"@testing-library/react": "^13.0.0",
|
||||
"@testing-library/user-event": "^13.2.1",
|
||||
"@types/jest": "^27.0.1",
|
||||
"@types/node": "^16.7.13",
|
||||
"@types/react": "^18.0.0",
|
||||
"@types/react-dom": "^18.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.6.0",
|
||||
"@typescript-eslint/parser": "^6.6.0",
|
||||
"axios": "^1.4.0",
|
||||
"chart.js": "^4.4.0",
|
||||
"clsx": "^2.0.0",
|
||||
"date-fns": "^2.30.0",
|
||||
"eslint": "^8.48.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-config-react-app": "^7.0.1",
|
||||
"eslint-import-resolver-typescript": "^3.6.0",
|
||||
"eslint-plugin-formatjs": "^4.10.4",
|
||||
"eslint-plugin-import": "^2.28.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.7.1",
|
||||
"eslint-plugin-react": "^7.33.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"focus-visible": "^5.2.0",
|
||||
"prettier": "^3.0.3",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-hook-form": "^7.45.4",
|
||||
"react-router-dom": "^6.15.0",
|
||||
"react-scripts": "5.0.1",
|
||||
"sanitize.css": "^13.0.0",
|
||||
"sass": "^1.66.1",
|
||||
"ts-key-enum": "^2.0.12",
|
||||
"typescript": "^4.4.2",
|
||||
"web-vitals": "^2.1.0",
|
||||
"zustand": "^4.4.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"react-app",
|
||||
"react-app/jest"
|
||||
]
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/date-fns": "^2.6.0",
|
||||
"@types/react-helmet": "^6.1.6"
|
||||
}
|
||||
}
|
29
pitch-deck/asset-manifest.json
Normal file
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"files": {
|
||||
"main.css": "/static/css/main.5f2ac698.css",
|
||||
"main.js": "/static/js/main.9948994c.js",
|
||||
"static/js/787.d98de4bb.chunk.js": "/static/js/787.d98de4bb.chunk.js",
|
||||
"static/media/background2.jpg": "/static/media/background2.ae2026eaf02a2a9549a0.jpg",
|
||||
"static/media/Raleway-Bold.woff": "/static/media/Raleway-Bold.669ff3b37217225a0735.woff",
|
||||
"static/media/Raleway-SemiBold.woff": "/static/media/Raleway-SemiBold.b4f6390736c5c84333f6.woff",
|
||||
"static/media/Raleway-Regular.woff": "/static/media/Raleway-Regular.a582669062b72fd23826.woff",
|
||||
"static/media/Raleway-Medium.woff": "/static/media/Raleway-Medium.b6832a08b63c3a92ca61.woff",
|
||||
"static/media/Raleway-Bold.woff2": "/static/media/Raleway-Bold.f45100b58922b985f604.woff2",
|
||||
"static/media/Raleway-SemiBold.woff2": "/static/media/Raleway-SemiBold.2a8d2efb19b3f056a7a5.woff2",
|
||||
"static/media/Raleway-Regular.woff2": "/static/media/Raleway-Regular.8ef2f50ea57d9d13e2f7.woff2",
|
||||
"static/media/Raleway-Medium.woff2": "/static/media/Raleway-Medium.7cc7d905f74a187d79f9.woff2",
|
||||
"static/media/IBMPlexMono-Regular.woff": "/static/media/IBMPlexMono-Regular.67e636f5e0ef0cb3f90f.woff",
|
||||
"static/media/IBMPlexMono-Regular.woff2": "/static/media/IBMPlexMono-Regular.255d8b9e69d1556eade4.woff2",
|
||||
"static/media/upload.svg": "/static/media/upload.2378fb103ff39440964e02e2516d993e.svg",
|
||||
"index.html": "/index.html",
|
||||
"static/media/loader.svg": "/static/media/loader.852ca2d21732c012738d2807dc517f14.svg",
|
||||
"static/media/right.svg": "/static/media/right.6dd63e7321721faf31750772f6ccc0c3.svg",
|
||||
"main.5f2ac698.css.map": "/static/css/main.5f2ac698.css.map",
|
||||
"main.9948994c.js.map": "/static/js/main.9948994c.js.map",
|
||||
"787.d98de4bb.chunk.js.map": "/static/js/787.d98de4bb.chunk.js.map"
|
||||
},
|
||||
"entrypoints": [
|
||||
"static/css/main.5f2ac698.css",
|
||||
"static/js/main.9948994c.js"
|
||||
]
|
||||
}
|
BIN
pitch-deck/favicon.ico
Normal file
After Width: | Height: | Size: 3.8 KiB |
1
pitch-deck/index.html
Normal file
|
@ -0,0 +1 @@
|
|||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>React App</title><script defer="defer" src="/static/js/main.9948994c.js"></script><link href="/static/css/main.5f2ac698.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
BIN
pitch-deck/logo192.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
pitch-deck/logo512.png
Normal file
After Width: | Height: | Size: 9.4 KiB |
25
pitch-deck/manifest.json
Normal file
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
3
pitch-deck/robots.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
2
pitch-deck/static/css/main.5f2ac698.css
Normal file
1
pitch-deck/static/css/main.5f2ac698.css.map
Normal file
2
pitch-deck/static/js/787.d98de4bb.chunk.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
"use strict";(self.webpackChunkhakaton=self.webpackChunkhakaton||[]).push([[787],{787:function(e,t,n){n.r(t),n.d(t,{getCLS:function(){return y},getFCP:function(){return h},getFID:function(){return F},getLCP:function(){return P},getTTFB:function(){return D}});var i,r,a,o,u=function(e,t){return{name:e,value:void 0===t?-1:t,delta:0,entries:[],id:"v2-".concat(Date.now(),"-").concat(Math.floor(8999999999999*Math.random())+1e12)}},c=function(e,t){try{if(PerformanceObserver.supportedEntryTypes.includes(e)){if("first-input"===e&&!("PerformanceEventTiming"in self))return;var n=new PerformanceObserver((function(e){return e.getEntries().map(t)}));return n.observe({type:e,buffered:!0}),n}}catch(e){}},f=function(e,t){var n=function n(i){"pagehide"!==i.type&&"hidden"!==document.visibilityState||(e(i),t&&(removeEventListener("visibilitychange",n,!0),removeEventListener("pagehide",n,!0)))};addEventListener("visibilitychange",n,!0),addEventListener("pagehide",n,!0)},s=function(e){addEventListener("pageshow",(function(t){t.persisted&&e(t)}),!0)},m=function(e,t,n){var i;return function(r){t.value>=0&&(r||n)&&(t.delta=t.value-(i||0),(t.delta||void 0===i)&&(i=t.value,e(t)))}},v=-1,p=function(){return"hidden"===document.visibilityState?0:1/0},d=function(){f((function(e){var t=e.timeStamp;v=t}),!0)},l=function(){return v<0&&(v=p(),d(),s((function(){setTimeout((function(){v=p(),d()}),0)}))),{get firstHiddenTime(){return v}}},h=function(e,t){var n,i=l(),r=u("FCP"),a=function(e){"first-contentful-paint"===e.name&&(f&&f.disconnect(),e.startTime<i.firstHiddenTime&&(r.value=e.startTime,r.entries.push(e),n(!0)))},o=window.performance&&performance.getEntriesByName&&performance.getEntriesByName("first-contentful-paint")[0],f=o?null:c("paint",a);(o||f)&&(n=m(e,r,t),o&&a(o),s((function(i){r=u("FCP"),n=m(e,r,t),requestAnimationFrame((function(){requestAnimationFrame((function(){r.value=performance.now()-i.timeStamp,n(!0)}))}))})))},g=!1,T=-1,y=function(e,t){g||(h((function(e){T=e.value})),g=!0);var n,i=function(t){T>-1&&e(t)},r=u("CLS",0),a=0,o=[],v=function(e){if(!e.hadRecentInput){var t=o[0],i=o[o.length-1];a&&e.startTime-i.startTime<1e3&&e.startTime-t.startTime<5e3?(a+=e.value,o.push(e)):(a=e.value,o=[e]),a>r.value&&(r.value=a,r.entries=o,n())}},p=c("layout-shift",v);p&&(n=m(i,r,t),f((function(){p.takeRecords().map(v),n(!0)})),s((function(){a=0,T=-1,r=u("CLS",0),n=m(i,r,t)})))},E={passive:!0,capture:!0},w=new Date,L=function(e,t){i||(i=t,r=e,a=new Date,k(removeEventListener),S())},S=function(){if(r>=0&&r<a-w){var e={entryType:"first-input",name:i.type,target:i.target,cancelable:i.cancelable,startTime:i.timeStamp,processingStart:i.timeStamp+r};o.forEach((function(t){t(e)})),o=[]}},b=function(e){if(e.cancelable){var t=(e.timeStamp>1e12?new Date:performance.now())-e.timeStamp;"pointerdown"==e.type?function(e,t){var n=function(){L(e,t),r()},i=function(){r()},r=function(){removeEventListener("pointerup",n,E),removeEventListener("pointercancel",i,E)};addEventListener("pointerup",n,E),addEventListener("pointercancel",i,E)}(t,e):L(t,e)}},k=function(e){["mousedown","keydown","touchstart","pointerdown"].forEach((function(t){return e(t,b,E)}))},F=function(e,t){var n,a=l(),v=u("FID"),p=function(e){e.startTime<a.firstHiddenTime&&(v.value=e.processingStart-e.startTime,v.entries.push(e),n(!0))},d=c("first-input",p);n=m(e,v,t),d&&f((function(){d.takeRecords().map(p),d.disconnect()}),!0),d&&s((function(){var a;v=u("FID"),n=m(e,v,t),o=[],r=-1,i=null,k(addEventListener),a=p,o.push(a),S()}))},C={},P=function(e,t){var n,i=l(),r=u("LCP"),a=function(e){var t=e.startTime;t<i.firstHiddenTime&&(r.value=t,r.entries.push(e),n())},o=c("largest-contentful-paint",a);if(o){n=m(e,r,t);var v=function(){C[r.id]||(o.takeRecords().map(a),o.disconnect(),C[r.id]=!0,n(!0))};["keydown","click"].forEach((function(e){addEventListener(e,v,{once:!0,capture:!0})})),f(v,!0),s((function(i){r=u("LCP"),n=m(e,r,t),requestAnimationFrame((function(){requestAnimationFrame((function(){r.value=performance.now()-i.timeStamp,C[r.id]=!0,n(!0)}))}))}))}},D=function(e){var t,n=u("TTFB");t=function(){try{var t=performance.getEntriesByType("navigation")[0]||function(){var e=performance.timing,t={entryType:"navigation",startTime:0};for(var n in e)"navigationStart"!==n&&"toJSON"!==n&&(t[n]=Math.max(e[n]-e.navigationStart,0));return t}();if(n.value=n.delta=t.responseStart,n.value<0||n.value>performance.now())return;n.entries=[t],e(n)}catch(e){}},"complete"===document.readyState?setTimeout(t,0):addEventListener("load",(function(){return setTimeout(t,0)}))}}}]);
|
||||
//# sourceMappingURL=787.d98de4bb.chunk.js.map
|
1
pitch-deck/static/js/787.d98de4bb.chunk.js.map
Normal file
3
pitch-deck/static/js/main.9948994c.js
Normal file
147
pitch-deck/static/js/main.9948994c.js.LICENSE.txt
Normal file
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
object-assign
|
||||
(c) Sindre Sorhus
|
||||
@license MIT
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @kurkle/color v0.3.2
|
||||
* https://github.com/kurkle/color#readme
|
||||
* (c) 2023 Jukka Kurkela
|
||||
* Released under the MIT License
|
||||
*/
|
||||
|
||||
/*!
|
||||
* Chart.js v4.4.0
|
||||
* https://www.chartjs.org
|
||||
* (c) 2023 Chart.js Contributors
|
||||
* Released under the MIT License
|
||||
*/
|
||||
|
||||
/*!
|
||||
* The buffer module from node.js, for the browser.
|
||||
*
|
||||
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/*!
|
||||
* The buffer module from node.js, for the browser.
|
||||
*
|
||||
* @author Feross Aboukhadijeh <https://feross.org>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
||||
|
||||
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
|
||||
|
||||
/*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-dom.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-jsx-runtime.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* scheduler.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* use-sync-external-store-shim.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* use-sync-external-store-shim/with-selector.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @preserve Knuth and Plass line breaking algorithm in JavaScript
|
||||
*
|
||||
* Licensed under the new BSD License.
|
||||
* Copyright 2009-2010, Bram Stein
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @remix-run/router v1.8.0
|
||||
*
|
||||
* Copyright (c) Remix Software Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE.md file in the root directory of this source tree.
|
||||
*
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/**
|
||||
* React Router v6.15.0
|
||||
*
|
||||
* Copyright (c) Remix Software Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE.md file in the root directory of this source tree.
|
||||
*
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/** @license React v0.17.0
|
||||
* scheduler.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/** @license React v0.23.0
|
||||
* react-reconciler.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
1
pitch-deck/static/js/main.9948994c.js.map
Normal file
BIN
pitch-deck/static/media/Raleway-Bold.669ff3b37217225a0735.woff
Normal file
BIN
pitch-deck/static/media/Raleway-Bold.f45100b58922b985f604.woff2
Normal file
BIN
pitch-deck/static/media/Raleway-Medium.b6832a08b63c3a92ca61.woff
Normal file
BIN
pitch-deck/static/media/background2.ae2026eaf02a2a9549a0.jpg
Normal file
After Width: | Height: | Size: 102 KiB |
|
@ -0,0 +1,3 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 3C11.4474 3 10.9994 3.448 10.9994 4.00065C10.9994 4.55329 11.4474 5.00129 12 5.00129C15.8653 5.00129 18.9987 8.13472 18.9987 12C18.9987 15.8653 15.8653 18.9987 12 18.9987C8.13472 18.9987 5.00129 15.8653 5.00129 12C5.00129 11.4474 4.55329 10.9994 4.00065 10.9994C3.448 10.9994 3 11.4474 3 12C3 16.9706 7.02944 21 12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3Z" fill="currentColor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 556 B |
|
@ -0,0 +1,5 @@
|
|||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15.834 9.99983H4.16731" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M11.6673 14.1665L15.834 9.99983" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M11.6673 5.83317L15.834 9.99983" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 494 B |
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3 14.25C3.41421 14.25 3.75 14.5858 3.75 15C3.75 16.4354 3.75159 17.4365 3.85315 18.1919C3.9518 18.9257 4.13225 19.3142 4.40901 19.591C4.68577 19.8678 5.07435 20.0482 5.80812 20.1469C6.56347 20.2484 7.56459 20.25 9 20.25H15C16.4354 20.25 17.4365 20.2484 18.1919 20.1469C18.9257 20.0482 19.3142 19.8678 19.591 19.591C19.8678 19.3142 20.0482 18.9257 20.1469 18.1919C20.2484 17.4365 20.25 16.4354 20.25 15C20.25 14.5858 20.5858 14.25 21 14.25C21.4142 14.25 21.75 14.5858 21.75 15V15.0549C21.75 16.4225 21.75 17.5248 21.6335 18.3918C21.5125 19.2919 21.2536 20.0497 20.6517 20.6516C20.0497 21.2536 19.2919 21.5125 18.3918 21.6335C17.5248 21.75 16.4225 21.75 15.0549 21.75H8.94513C7.57754 21.75 6.47522 21.75 5.60825 21.6335C4.70814 21.5125 3.95027 21.2536 3.34835 20.6517C2.74643 20.0497 2.48754 19.2919 2.36652 18.3918C2.24996 17.5248 2.24998 16.4225 2.25 15.0549C2.25 15.0366 2.25 15.0183 2.25 15C2.25 14.5858 2.58579 14.25 3 14.25Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 2.25C12.2106 2.25 12.4114 2.33852 12.5535 2.49392L16.5535 6.86892C16.833 7.17462 16.8118 7.64902 16.5061 7.92852C16.2004 8.20802 15.726 8.18678 15.4465 7.88108L12.75 4.9318V16C12.75 16.4142 12.4142 16.75 12 16.75C11.5858 16.75 11.25 16.4142 11.25 16V4.9318L8.55353 7.88108C8.27403 8.18678 7.79963 8.20802 7.49393 7.92852C7.18823 7.64902 7.16698 7.17462 7.44648 6.86892L11.4465 2.49392C11.5886 2.33852 11.7894 2.25 12 2.25Z" fill="currentColor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
BIN
public/favicon.ico
Normal file
After Width: | Height: | Size: 3.8 KiB |
43
public/index.html
Normal file
|
@ -0,0 +1,43 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>React App</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
</html>
|
BIN
public/logo192.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
public/logo512.png
Normal file
After Width: | Height: | Size: 9.4 KiB |
25
public/manifest.json
Normal file
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
3
public/robots.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
35
src/api/deck/convert.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
import {axios} from '../../lib/axios';
|
||||
import {CONVERT_API_URL} from './urlKeys';
|
||||
import {MutationConfig} from '../../lib/react-query';
|
||||
import {useMutation} from '@tanstack/react-query';
|
||||
|
||||
export type ConvertDTO = {
|
||||
pdf: File;
|
||||
};
|
||||
|
||||
export type ConvertResponse = {
|
||||
pdf: string;
|
||||
pptx: string;
|
||||
};
|
||||
|
||||
export const convert = (data: ConvertDTO): Promise<ConvertResponse> => {
|
||||
const inputData = new FormData();
|
||||
inputData.append('pdf', data.pdf);
|
||||
|
||||
return axios.post(CONVERT_API_URL, inputData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
type UseConvertOptions = {
|
||||
config?: MutationConfig<typeof convert>;
|
||||
};
|
||||
|
||||
export const useConvert = ({ config }: UseConvertOptions = {}) => {
|
||||
return useMutation({
|
||||
...config,
|
||||
mutationFn: convert
|
||||
});
|
||||
};
|
65
src/api/deck/createAnswer.ts
Normal file
|
@ -0,0 +1,65 @@
|
|||
import { useMutation } from '@tanstack/react-query';
|
||||
import { MutationConfig, queryClient } from '../../lib/react-query';
|
||||
import { axios } from '../../lib/axios';
|
||||
import { Answer, PitchDeck } from './types';
|
||||
import { DECKS_API_URL, QUESTION_API_URL, QUESTION_PARAM_DECK_ID, QUESTION_PARAM_QUESTION_ID } from './urlKeys';
|
||||
import { QUERY_KEY_ANSWER } from './queryKeys';
|
||||
|
||||
export type CreateAnswerDTO = {
|
||||
deckId: number;
|
||||
questionId: number;
|
||||
answer: any;
|
||||
isFile?: boolean;
|
||||
file?: File;
|
||||
};
|
||||
|
||||
export type CreateAnswerResponse = Answer;
|
||||
|
||||
export const createAnswer = (data: CreateAnswerDTO): Promise<CreateAnswerResponse> => {
|
||||
const path =
|
||||
QUESTION_API_URL.replace(`:${QUESTION_PARAM_DECK_ID}`, String(data.deckId)).replace(
|
||||
`:${QUESTION_PARAM_QUESTION_ID}`,
|
||||
String(data.questionId)
|
||||
) + '/';
|
||||
|
||||
let inputData: any;
|
||||
if (data.isFile) {
|
||||
inputData = new FormData();
|
||||
if (data.answer) {
|
||||
inputData.append('answer', `${data.answer}`);
|
||||
}
|
||||
for (const key in data) {
|
||||
if (key !== 'answer' && key !== 'isFile' && key !== 'deckId' && key !== 'questionId') {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
inputData.append(key, data[key]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
inputData = {
|
||||
answer: data.answer
|
||||
};
|
||||
}
|
||||
|
||||
return axios.post(path, inputData, {
|
||||
headers: data.isFile
|
||||
? {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
: {}
|
||||
});
|
||||
};
|
||||
|
||||
type UseCreateAnswerOptions = {
|
||||
config?: MutationConfig<typeof createAnswer>;
|
||||
};
|
||||
|
||||
export const useCreateAnswer = ({ config }: UseCreateAnswerOptions = {}) => {
|
||||
return useMutation({
|
||||
onMutate: async () => {
|
||||
await queryClient.cancelQueries([QUERY_KEY_ANSWER]);
|
||||
},
|
||||
...config,
|
||||
mutationFn: createAnswer
|
||||
});
|
||||
};
|
29
src/api/deck/createDeck.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
import {PitchDeck} from './types';
|
||||
import {DECKS_API_URL} from './urlKeys';
|
||||
import {MutationConfig, queryClient} from '../../lib/react-query';
|
||||
import {useMutation} from '@tanstack/react-query';
|
||||
import {QUERY_KEY_DECKS} from './queryKeys';
|
||||
import { axios } from '../../lib/axios';
|
||||
|
||||
export type CreateDeckDTO = Pick<PitchDeck, 'description'>;
|
||||
|
||||
export type CreateDeckResponse = PitchDeck;
|
||||
|
||||
export const createDeck = (data: CreateDeckDTO): Promise<CreateDeckResponse> => {
|
||||
return axios.post(DECKS_API_URL, data);
|
||||
};
|
||||
|
||||
type UseCreateDeckOptions = {
|
||||
config?: MutationConfig<typeof createDeck>;
|
||||
};
|
||||
|
||||
export const useCreateDeck = ({ config }: UseCreateDeckOptions = {}) => {
|
||||
|
||||
return useMutation({
|
||||
onMutate: async () => {
|
||||
await queryClient.cancelQueries([QUERY_KEY_DECKS]);
|
||||
},
|
||||
...config,
|
||||
mutationFn: createDeck
|
||||
});
|
||||
};
|
50
src/api/deck/getDeck.ts
Normal file
|
@ -0,0 +1,50 @@
|
|||
import {Question} from './types';
|
||||
import {axios} from '../../lib/axios';
|
||||
import {
|
||||
DECK_API_URL,
|
||||
QUESTION_API_URL,
|
||||
QUESTION_PARAM_DECK_ID,
|
||||
QUESTION_PARAM_QUESTION_ID,
|
||||
} from './urlKeys';
|
||||
import {ExtractFnReturnType, QueryConfig} from '../../lib/react-query';
|
||||
import {useQuery} from '@tanstack/react-query';
|
||||
import {QUERY_KEY_DECKS, QUERY_KEY_QUESTION} from './queryKeys';
|
||||
|
||||
export type GetDeckResponse = {
|
||||
deck: {
|
||||
name: string;
|
||||
description: string;
|
||||
},
|
||||
slides: {
|
||||
slide: number;
|
||||
data: {
|
||||
slug: string;
|
||||
answer: any;
|
||||
photos?: string[]
|
||||
}[];
|
||||
}[];
|
||||
};
|
||||
|
||||
export const getDeck = ({ deckId }: { deckId: number }): Promise<GetDeckResponse> => {
|
||||
return axios.get(
|
||||
DECK_API_URL
|
||||
.replace(`:${QUESTION_PARAM_DECK_ID}`, String(deckId))
|
||||
);
|
||||
};
|
||||
|
||||
type QueryFnType = typeof getDeck;
|
||||
|
||||
type UseDeckOptions = {
|
||||
deckId: number;
|
||||
config?: QueryConfig<QueryFnType>;
|
||||
};
|
||||
|
||||
export const useDeck = ({ deckId, config }: UseDeckOptions) => {
|
||||
return useQuery<ExtractFnReturnType<QueryFnType>>({
|
||||
...config,
|
||||
queryKey: [QUERY_KEY_DECKS, deckId],
|
||||
queryFn: async () => {
|
||||
return await getDeck({ deckId });
|
||||
},
|
||||
});
|
||||
};
|
31
src/api/deck/getFirstQuestion.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
import {Question} from './types';
|
||||
import {axios} from '../../lib/axios';
|
||||
import {FIRST_QUESTION_API_URL, FIRST_QUESTION_PARAM} from './urlKeys';
|
||||
import {ExtractFnReturnType, QueryConfig} from '../../lib/react-query';
|
||||
import {useQuery} from '@tanstack/react-query';
|
||||
import {QUERY_KEY_FIRST_QUESTION} from './queryKeys';
|
||||
|
||||
export type GetFirstQuestionResponse = Question;
|
||||
|
||||
export const getFirstQuestion = ({ deckId }: { deckId: number; }): Promise<GetFirstQuestionResponse> => {
|
||||
return axios.get(FIRST_QUESTION_API_URL.replace(`:${FIRST_QUESTION_PARAM}`, String(deckId)));
|
||||
};
|
||||
|
||||
type QueryFnType = typeof getFirstQuestion;
|
||||
|
||||
type UseFirstQuestionOptions = {
|
||||
deckId: number;
|
||||
config?: QueryConfig<QueryFnType>;
|
||||
};
|
||||
|
||||
export const useFirstQuestion = ({ deckId, config }: UseFirstQuestionOptions) => {
|
||||
return useQuery<ExtractFnReturnType<QueryFnType>>({
|
||||
...config,
|
||||
queryKey: [QUERY_KEY_FIRST_QUESTION, deckId],
|
||||
queryFn: async () => {
|
||||
const process = await getFirstQuestion({ deckId });
|
||||
|
||||
return process;
|
||||
},
|
||||
});
|
||||
};
|
38
src/api/deck/getQuestion.ts
Normal file
|
@ -0,0 +1,38 @@
|
|||
import {Question} from './types';
|
||||
import {axios} from '../../lib/axios';
|
||||
import {
|
||||
QUESTION_API_URL,
|
||||
QUESTION_PARAM_DECK_ID,
|
||||
QUESTION_PARAM_QUESTION_ID,
|
||||
} from './urlKeys';
|
||||
import {ExtractFnReturnType, QueryConfig} from '../../lib/react-query';
|
||||
import {useQuery} from '@tanstack/react-query';
|
||||
import {QUERY_KEY_QUESTION} from './queryKeys';
|
||||
|
||||
export type GetQuestionResponse = Question;
|
||||
|
||||
export const getQuestion = ({ deckId, questionId }: { deckId: number; questionId: number; }): Promise<GetQuestionResponse> => {
|
||||
return axios.get(
|
||||
QUESTION_API_URL
|
||||
.replace(`:${QUESTION_PARAM_DECK_ID}`, String(deckId))
|
||||
.replace(`:${QUESTION_PARAM_QUESTION_ID}`, String(questionId))
|
||||
);
|
||||
};
|
||||
|
||||
type QueryFnType = typeof getQuestion;
|
||||
|
||||
type UseQuestionOptions = {
|
||||
deckId: number;
|
||||
questionId: number;
|
||||
config?: QueryConfig<QueryFnType>;
|
||||
};
|
||||
|
||||
export const useQuestion = ({ deckId, questionId, config }: UseQuestionOptions) => {
|
||||
return useQuery<ExtractFnReturnType<QueryFnType>>({
|
||||
...config,
|
||||
queryKey: [QUERY_KEY_QUESTION, deckId, questionId],
|
||||
queryFn: async () => {
|
||||
return await getQuestion({ deckId, questionId });
|
||||
},
|
||||
});
|
||||
};
|
6
src/api/deck/index.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
export * from './types';
|
||||
export * from './urlKeys';
|
||||
export * from './queryKeys';
|
||||
|
||||
export * from './createDeck';
|
||||
export * from './getFirstQuestion';
|
4
src/api/deck/queryKeys.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
export const QUERY_KEY_DECKS = 'decks';
|
||||
export const QUERY_KEY_FIRST_QUESTION = 'firstQuestion';
|
||||
export const QUERY_KEY_QUESTION = 'question';
|
||||
export const QUERY_KEY_ANSWER = 'answer';
|
45
src/api/deck/types.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
export enum EntityType {
|
||||
text = 'text', // +
|
||||
number = 'number', // +
|
||||
range = 'range', // +
|
||||
multiple_range = 'multiple_range', // +
|
||||
select = 'select', // +
|
||||
link = 'link', // + добавить валидацию
|
||||
date = 'date', // +
|
||||
// photo = 'photo',
|
||||
multiple_photo = 'multiple_photo',
|
||||
photo_description = 'photo_description',
|
||||
multiple_link_description = 'multiple_link_description', //
|
||||
multiple_photo_description = 'multiple_photo_description',
|
||||
// multiple_links = 'multiple_links', // не пригодилось
|
||||
multiple_date_description = 'multiple_date_description', //
|
||||
text_array = 'text_array', // используется только в подсказке
|
||||
cards = 'cards', // используется только в подсказке
|
||||
}
|
||||
|
||||
export type PitchDeck = {
|
||||
id: number;
|
||||
name: string;
|
||||
description?: string;
|
||||
questions?: any[];
|
||||
};
|
||||
|
||||
export type Hint = {
|
||||
type: EntityType;
|
||||
value: any;
|
||||
}
|
||||
|
||||
export type Question = {
|
||||
id: number;
|
||||
text: string;
|
||||
type: EntityType;
|
||||
hint: Hint | false;
|
||||
next_id: number;
|
||||
params: { [key: string]: any } | null;
|
||||
};
|
||||
|
||||
export type Answer = {
|
||||
answer: any;
|
||||
deck: number;
|
||||
question: number;
|
||||
}
|
13
src/api/deck/urlKeys.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
export const DECKS_API_URL = '/decks/';
|
||||
|
||||
export const FIRST_QUESTION_PARAM = 'deckId';
|
||||
export const FIRST_QUESTION_API_URL = `/decks/question/:${FIRST_QUESTION_PARAM}`;
|
||||
|
||||
export const QUESTION_PARAM_DECK_ID = 'deckId';
|
||||
export const QUESTION_PARAM_QUESTION_ID = 'questionId';
|
||||
export const QUESTION_API_URL = `/decks/question/:${FIRST_QUESTION_PARAM}/:${QUESTION_PARAM_QUESTION_ID}`;
|
||||
|
||||
export const DECK_PARAM = 'deckId';
|
||||
export const DECK_API_URL = `/decks/question/:${FIRST_QUESTION_PARAM}/presentation`;
|
||||
|
||||
export const CONVERT_API_URL = '/decks/pdf-to-pptx';
|
15
src/app/App.tsx
Normal file
|
@ -0,0 +1,15 @@
|
|||
import React from 'react';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import {AppRoutes} from './routes';
|
||||
|
||||
export function App() {
|
||||
return (
|
||||
<>
|
||||
<Helmet title={"Pitch Deck"}>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
|
||||
</Helmet>
|
||||
<AppRoutes />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
13
src/app/AppProvider.tsx
Normal file
|
@ -0,0 +1,13 @@
|
|||
import {FC, PropsWithChildren} from 'react';
|
||||
import {BrowserRouter} from 'react-router-dom';
|
||||
import {ReactQueryProvider} from './providers';
|
||||
|
||||
export const AppProvider: FC<PropsWithChildren> = ({ children }) => {
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<ReactQueryProvider>
|
||||
{children}
|
||||
</ReactQueryProvider>
|
||||
</BrowserRouter>
|
||||
)
|
||||
}
|
2
src/app/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
export * from './App';
|
||||
export * from './AppProvider';
|
1
src/app/providers/index.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export * from './react-query';
|
11
src/app/providers/react-query.tsx
Normal file
|
@ -0,0 +1,11 @@
|
|||
import {ReactFCC} from '../../utils/ReactFCC';
|
||||
import {QueryClientProvider} from '@tanstack/react-query';
|
||||
import {queryClient} from '../../lib/react-query';
|
||||
|
||||
export const ReactQueryProvider: ReactFCC = ({ children }) => {
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
{children}
|
||||
</QueryClientProvider>
|
||||
)
|
||||
}
|
19
src/app/routes/AppRoutes.tsx
Normal file
|
@ -0,0 +1,19 @@
|
|||
import {Route, Routes} from 'react-router-dom';
|
||||
import {ChatPage} from '../../pages/chat';
|
||||
import {CHAT_PAGE_ROUTE, HOME_PAGE_ROUTE} from './routes';
|
||||
import {HomePage} from '../../pages/home';
|
||||
import {DefaultLayout} from '../../pages/_layouts/DefaultLayout';
|
||||
|
||||
export const AppRoutes = () => {
|
||||
|
||||
return (
|
||||
<Routes>
|
||||
<Route element={<DefaultLayout />}>
|
||||
<Route path={CHAT_PAGE_ROUTE} element={<ChatPage />} />
|
||||
<Route path={HOME_PAGE_ROUTE} element={<HomePage />} />
|
||||
</Route>
|
||||
|
||||
</Routes>
|
||||
);
|
||||
};
|
||||
|
2
src/app/routes/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
export * from './AppRoutes';
|
||||
export * from './routes';
|
2
src/app/routes/routes.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
export const CHAT_PAGE_ROUTE = `/chat`;
|
||||
export const HOME_PAGE_ROUTE = `/`;
|
160
src/app/styles/baseText.scss
Normal file
|
@ -0,0 +1,160 @@
|
|||
$font-family-default: system-ui, /* macOS 10.11-10.12 */ -apple-system, /* Windows 6+ */ 'Segoe UI',
|
||||
/* Android 4+ */ 'Roboto', /* Ubuntu 10.10+ */ 'Ubuntu', /* Gnome 3+ */ 'Cantarell', /* KDE Plasma 5+ */ 'Noto Sans',
|
||||
/* fallback */ sans-serif, /* macOS emoji */ 'Apple Color Emoji', /* Windows emoji */ 'Segoe UI Emoji',
|
||||
/* Windows emoji */ 'Segoe UI Symbol', /* Linux emoji */ 'Noto Color Emoji';
|
||||
|
||||
// Моноширинный набор шрифтов.
|
||||
$font-family-mono: 'Menlo', 'Consolas', 'Roboto Mono', 'Ubuntu Monospace', 'Noto Mono', 'Oxygen Mono', 'Liberation Mono',
|
||||
monospace, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
|
||||
$font-family-raleway: 'Raleway';
|
||||
$font-family-inter: 'Inter';
|
||||
$font-family-ibm-plex-mono: 'IBM Plex Mono';
|
||||
|
||||
$font-size-10: 10px;
|
||||
$font-size-12: 12px;
|
||||
$font-size-14: 14px;
|
||||
$font-size-16: 16px;
|
||||
$font-size-18: 18px;
|
||||
$font-size-24: 24px;
|
||||
$font-size-32: 32px;
|
||||
$font-size-56: 56px;
|
||||
|
||||
$font-weight-400: 400;
|
||||
$font-weight-500: 500;
|
||||
$font-weight-600: 600;
|
||||
$font-weight-700: 700;
|
||||
|
||||
$font-weight-regular: 400;
|
||||
$font-weight-medium: 500;
|
||||
$font-weight-semibold: 600;
|
||||
$font-weight-bold: 700;
|
||||
|
||||
$line-height-16: 16px;
|
||||
$line-height-18: 18px;
|
||||
$line-height-20: 20px;
|
||||
$line-height-24: 24px;
|
||||
$line-height-32: 32px;
|
||||
$line-height-40: 40px;
|
||||
$line-height-67: 67px;
|
||||
|
||||
@mixin text-header-h1 {
|
||||
font-family: $font-family-inter, $font-family-default;
|
||||
font-size: $font-size-56;
|
||||
font-weight: $font-weight-700;
|
||||
line-height: $line-height-67;
|
||||
}
|
||||
|
||||
@mixin text-header-h2 {
|
||||
font-family: $font-family-inter, $font-family-default;
|
||||
font-size: $font-size-32;
|
||||
font-weight: $font-weight-700;
|
||||
line-height: $line-height-40;
|
||||
}
|
||||
|
||||
@mixin text-header-h3 {
|
||||
font-family: $font-family-inter, $font-family-default;
|
||||
font-size: $font-size-24;
|
||||
font-weight: $font-weight-700;
|
||||
line-height: $line-height-32;
|
||||
}
|
||||
|
||||
@mixin text-header-h4 {
|
||||
font-family: $font-family-inter, $font-family-default;
|
||||
font-size: $font-size-18;
|
||||
font-weight: $font-weight-700;
|
||||
line-height: $line-height-24;
|
||||
}
|
||||
|
||||
@mixin text-body-l-medium {
|
||||
font-family: $font-family-inter, $font-family-default;
|
||||
font-size: $font-size-18;
|
||||
font-weight: $font-weight-600;
|
||||
line-height: $line-height-24;
|
||||
}
|
||||
|
||||
@mixin text-body-l-regular {
|
||||
font-family: $font-family-inter, $font-family-default;
|
||||
font-size: $font-size-18;
|
||||
font-weight: $font-weight-400;
|
||||
line-height: $line-height-24;
|
||||
}
|
||||
|
||||
@mixin text-body-m-medium {
|
||||
font-family: $font-family-inter, $font-family-default;
|
||||
font-size: $font-size-16;
|
||||
font-weight: $font-weight-600;
|
||||
line-height: $line-height-20;
|
||||
}
|
||||
|
||||
@mixin text-body-m-regular {
|
||||
font-family: $font-family-inter, $font-family-default;
|
||||
font-size: $font-size-16;
|
||||
font-weight: $font-weight-400;
|
||||
line-height: $line-height-20;
|
||||
}
|
||||
|
||||
@mixin text-body-s-medium {
|
||||
font-family: $font-family-inter, $font-family-default;
|
||||
font-size: $font-size-14;
|
||||
font-weight: $font-weight-600;
|
||||
line-height: $line-height-18;
|
||||
}
|
||||
|
||||
@mixin text-body-s-regular {
|
||||
font-family: $font-family-inter, $font-family-default;
|
||||
font-size: $font-size-12;
|
||||
font-weight: $font-weight-400;
|
||||
line-height: $line-height-18;
|
||||
}
|
||||
|
||||
@mixin text-caption-m-medium {
|
||||
font-family: $font-family-inter, $font-family-default;
|
||||
font-size: $font-size-14;
|
||||
font-weight: $font-weight-500;
|
||||
line-height: $line-height-20;
|
||||
}
|
||||
|
||||
@mixin text-caption-m-regular {
|
||||
font-family: $font-family-inter, $font-family-default;
|
||||
font-size: $font-size-14;
|
||||
font-weight: $font-weight-400;
|
||||
line-height: $line-height-20;
|
||||
}
|
||||
|
||||
@mixin text-caption-s-medium {
|
||||
font-family: $font-family-inter, $font-family-default;
|
||||
font-size: $font-size-10;
|
||||
font-weight: $font-weight-500;
|
||||
line-height: $line-height-16;
|
||||
}
|
||||
|
||||
@mixin text-caption-s-regular {
|
||||
font-family: $font-family-inter, $font-family-default;
|
||||
font-size: $font-size-10;
|
||||
font-weight: $font-weight-400;
|
||||
line-height: $line-height-16;
|
||||
}
|
||||
|
||||
@mixin text-caption-all-caps {
|
||||
letter-spacing: 0.04em;
|
||||
text-transform: uppercase;
|
||||
font-family: $font-family-inter, $font-family-default;
|
||||
font-size: $font-size-12;
|
||||
font-weight: $font-weight-600;
|
||||
line-height: $line-height-20;
|
||||
}
|
||||
|
||||
@mixin text-programming-code-medium {
|
||||
font-family: $font-family-ibm-plex-mono, $font-family-mono;
|
||||
font-size: $font-size-12;
|
||||
font-weight: $font-weight-400;
|
||||
line-height: $line-height-20;
|
||||
}
|
||||
|
||||
@mixin text-programming-code-regular {
|
||||
font-family: $font-family-ibm-plex-mono, $font-family-mono;
|
||||
font-size: $font-size-12;
|
||||
font-weight: $font-weight-400;
|
||||
line-height: $line-height-16;
|
||||
}
|
137
src/app/styles/breakpoints.scss
Normal file
|
@ -0,0 +1,137 @@
|
|||
$breakpoint-mobile-small: 320px;
|
||||
$breakpoint-mobile-large: 375px;
|
||||
$breakpoint-tablet-small: 768px;
|
||||
$breakpoint-tablet-large: 1024px;
|
||||
$breakpoint-desktop-small: 1280px;
|
||||
$breakpoint-desktop-medium: 1440px;
|
||||
$breakpoint-desktop-large: 1920px;
|
||||
|
||||
@mixin media-up($breakpoint) {
|
||||
@if $breakpoint == mobile-small {
|
||||
@media screen and (min-width: $breakpoint-mobile-small) {
|
||||
@content;
|
||||
}
|
||||
} @else if $breakpoint == mobile-large {
|
||||
@media screen and (min-width: $breakpoint-mobile-large) {
|
||||
@content;
|
||||
}
|
||||
} @else if $breakpoint == tablet-small {
|
||||
@media screen and (min-width: $breakpoint-tablet-small) {
|
||||
@content;
|
||||
}
|
||||
} @else if $breakpoint == tablet-large {
|
||||
@media screen and (min-width: $breakpoint-tablet-large) {
|
||||
@content;
|
||||
}
|
||||
} @else if $breakpoint == desktop-small {
|
||||
@media screen and (min-width: $breakpoint-desktop-small) {
|
||||
@content;
|
||||
}
|
||||
} @else if $breakpoint == desktop-medium {
|
||||
@media screen and (min-width: $breakpoint-desktop-medium) {
|
||||
@content;
|
||||
}
|
||||
} @else if $breakpoint == desktop-large {
|
||||
@media screen and (min-width: $breakpoint-desktop-large) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin media-down($breakpoint) {
|
||||
@if $breakpoint == mobile-small {
|
||||
@media screen and (max-width: $breakpoint-mobile-small - 1) {
|
||||
@content;
|
||||
}
|
||||
} @else if $breakpoint == mobile-large {
|
||||
@media screen and (max-width: $breakpoint-mobile-large - 1) {
|
||||
@content;
|
||||
}
|
||||
} @else if $breakpoint == tablet-small {
|
||||
@media screen and (max-width: $breakpoint-tablet-small - 1) {
|
||||
@content;
|
||||
}
|
||||
} @else if $breakpoint == tablet-large {
|
||||
@media screen and (max-width: $breakpoint-tablet-large - 1) {
|
||||
@content;
|
||||
}
|
||||
} @else if $breakpoint == desktop-small {
|
||||
@media screen and (max-width: $breakpoint-desktop-small - 1) {
|
||||
@content;
|
||||
}
|
||||
} @else if $breakpoint == desktop-medium {
|
||||
@media screen and (max-width: $breakpoint-desktop-medium - 1) {
|
||||
@content;
|
||||
}
|
||||
} @else if $breakpoint == desktop-large {
|
||||
@media screen and (max-width: $breakpoint-desktop-large - 1) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin grid-for($breakpoint) {
|
||||
display: grid;
|
||||
|
||||
@if $breakpoint == mobile-small {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
padding-right: 16px;
|
||||
padding-left: 16px;
|
||||
column-gap: 16px;
|
||||
} @else if $breakpoint == mobile-large {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
padding-right: 16px;
|
||||
padding-left: 16px;
|
||||
column-gap: 16px;
|
||||
} @else if $breakpoint == tablet-small {
|
||||
grid-template-columns: repeat(8, 1fr);
|
||||
padding-right: 72px;
|
||||
padding-left: 72px;
|
||||
column-gap: 16px;
|
||||
} @else if $breakpoint == tablet-large {
|
||||
grid-template-columns: repeat(12, 1fr);
|
||||
padding-right: 40px;
|
||||
padding-left: 40px;
|
||||
column-gap: 16px;
|
||||
} @else if $breakpoint == desktop-small {
|
||||
grid-template-columns: repeat(12, 1fr);
|
||||
padding-right: 76px;
|
||||
padding-left: 76px;
|
||||
column-gap: 24px;
|
||||
} @else if $breakpoint == desktop-medium {
|
||||
grid-template-columns: repeat(12, 1fr);
|
||||
padding-right: 112px;
|
||||
padding-left: 112px;
|
||||
column-gap: 32px;
|
||||
} @else if $breakpoint == desktop-large {
|
||||
grid-template-columns: repeat(16, 1fr);
|
||||
padding-right: 144px;
|
||||
padding-left: 144px;
|
||||
column-gap: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin mobile-down {
|
||||
@include media-down(tablet-small) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin mobile-up {
|
||||
@include media-up(tablet-small) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin tablet-down {
|
||||
@include media-down(desktop-small) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin tablet-up {
|
||||
@include media-up(desktop-small) {
|
||||
@content;
|
||||
}
|
||||
}
|
131
src/app/styles/colors.scss
Normal file
|
@ -0,0 +1,131 @@
|
|||
@use 'sass:color' as color;
|
||||
|
||||
// бело-коричневый
|
||||
//$color-text: #1b1918;
|
||||
//$color-background: #fafafa;
|
||||
//$color-primary: #7e716d;
|
||||
//$color-secondary: #e7e5e4;
|
||||
//$color-accent: #887b77;
|
||||
|
||||
// синий
|
||||
$color-text: #010819;
|
||||
$color-background: #e6edfe;
|
||||
$color-primary: #0647e0;
|
||||
$color-secondary: #cddcfe;
|
||||
$color-accent: #064ff9;
|
||||
|
||||
// сине-пастельный
|
||||
//$color-text: #130e07;
|
||||
//$color-background: #fbf8f4;
|
||||
//$color-primary: #223a5e;
|
||||
//$color-secondary: #ebdcc7;
|
||||
//$color-accent: #3d68a9;
|
||||
|
||||
// синий монохром
|
||||
//$color-text: #01062d;
|
||||
//$color-background: #ebedfe;
|
||||
//$color-primary: #3e51f9;
|
||||
//$color-secondary: #b5bcfd;
|
||||
//$color-accent: #071cdf;
|
||||
|
||||
$color-background-primary: $color-background;
|
||||
$color-background-secondary: $color-secondary;
|
||||
$color-background-dark-100: darken($color-background, 1%);
|
||||
$color-background-dark-200: darken($color-background, 2%);
|
||||
$color-background-dark-300: darken($color-background, 3%);
|
||||
$color-background-dark-400: darken($color-background, 4%);
|
||||
$color-background-accent: $color-accent;
|
||||
|
||||
$color-text-primary: $color-text;
|
||||
$color-text-secondary: color.adjust($color-background, $blackness: 100%);
|
||||
$color-text-tertiary: color.adjust($color-background, $blackness: 70%);
|
||||
$color-text-quaternary: $color-background;
|
||||
$color-text-brand: $color-primary;
|
||||
$color-text-disabled: color.adjust($color-text, $lightness: 40%);
|
||||
|
||||
$color-brand-primary: $color-primary;
|
||||
$color-brand-hover: color.adjust($color-primary, $blackness: 2%);
|
||||
$color-brand-disabled: color.adjust($color-primary, $lightness: 2%);
|
||||
|
||||
$color-border: color.invert($color-background);
|
||||
|
||||
//@debug $color-border;
|
||||
|
||||
//
|
||||
/* --- surface --- */
|
||||
$color-surface-primary: #141414;
|
||||
|
||||
/* --- on-surface --- */
|
||||
$color-on-surface-dark-100: #1d1d1d;
|
||||
$color-on-surface-dark-200: #252525;
|
||||
$color-on-surface-dark-300: #2d2d2d;
|
||||
$color-on-surface-dark-400: #3e3e3e;
|
||||
$color-on-surface-light-400: #5e6166;
|
||||
$color-on-surface-light-300: #868a92;
|
||||
$color-on-surface-light-200: #c5c6ca;
|
||||
$color-on-surface-light-100: #fafafa;
|
||||
$color-on-surface-quaternary: #2b2b2b;
|
||||
|
||||
/* --- text --- */
|
||||
//$color-text-primary: #fafafa;
|
||||
//$color-text-secondary: #c5c6ca;
|
||||
//$color-text-tertiary: #868a92;
|
||||
//$color-text-quaternary: #5e6166;
|
||||
//$color-text-dark: #2b2b2b;
|
||||
//$color-text-brand: #8e85e5;
|
||||
|
||||
/* --- brand --- */
|
||||
//$color-brand-primary: #695fcf;
|
||||
//$color-brand-hover: #9288f8;
|
||||
//$color-brand-disabled: #49428e;
|
||||
|
||||
/* --- system --- */
|
||||
$color-system-link: #7f9ef3;
|
||||
$color-system-success: #10b981;
|
||||
$color-system-warning: #f59e0b;
|
||||
$color-system-error: #f43f5e;
|
||||
$color-system-link-weak: #142144;
|
||||
$color-system-success-weak: #042c1f;
|
||||
$color-system-warning-weak: #3d2907;
|
||||
$color-system-error-weak: #2d1015;
|
||||
$color-system-link-hover: #a8c1f8;
|
||||
|
||||
/* --- accent --- */
|
||||
$color-accent-blue-100: #7f9ef3;
|
||||
$color-accent-blue-200: #2b4acb;
|
||||
$color-accent-blue-300: #203175;
|
||||
$color-accent-blue-400: #191e40;
|
||||
$color-accent-pink-100: #f37fb7;
|
||||
$color-accent-pink-200: #cb2b83;
|
||||
$color-accent-pink-300: #75204f;
|
||||
$color-accent-pink-400: #40162f;
|
||||
$color-accent-purple-100: #ab7ae0;
|
||||
$color-accent-purple-200: #642ab5;
|
||||
$color-accent-purple-300: #3e2069;
|
||||
$color-accent-purple-400: #21183b;
|
||||
$color-accent-green-100: #8fd460;
|
||||
$color-accent-green-200: #49aa19;
|
||||
$color-accent-green-300: #306317;
|
||||
$color-accent-green-400: #1d3712;
|
||||
$color-accent-cyan-100: #58d1c9;
|
||||
$color-accent-cyan-200: #13a8a8;
|
||||
$color-accent-cyan-300: #146262;
|
||||
$color-accent-cyan-400: #163b2e;
|
||||
$color-accent-orange-100: #f3b765;
|
||||
$color-accent-orange-200: #d87a16;
|
||||
$color-accent-orange-300: #7c4a15;
|
||||
$color-accent-orange-400: #442a11;
|
||||
$color-accent-yellow-100: #f3ea62;
|
||||
$color-accent-yellow-200: #d8bd14;
|
||||
$color-accent-yellow-300: #7c6e14;
|
||||
$color-accent-yellow-400: #443611;
|
||||
$color-accent-red-100: #f37370;
|
||||
$color-accent-red-200: #d32029;
|
||||
$color-accent-red-300: #791a1f;
|
||||
$color-accent-red-400: #421716;
|
||||
//
|
||||
//$text: #131513;
|
||||
//$background: #f4f5f4;
|
||||
//$primary: #5d555e;
|
||||
//$secondary: #d8d4d6;
|
||||
//$accent: #706b76;
|
81
src/app/styles/fonts.scss
Normal file
|
@ -0,0 +1,81 @@
|
|||
@import './baseText';
|
||||
|
||||
$fonts-path: '../../assets/fonts' !default;
|
||||
|
||||
@font-face {
|
||||
font-family: $font-family-raleway;
|
||||
src: url('#{$fonts-path}/Raleway/Raleway-Regular.woff2') format('woff2'),
|
||||
url('#{$fonts-path}/Raleway/Raleway-Regular.woff') format('woff');
|
||||
font-weight: $font-weight-400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: $font-family-raleway;
|
||||
src: url('#{$fonts-path}/Raleway/Raleway-Medium.woff2') format('woff2'),
|
||||
url('#{$fonts-path}/Raleway/Raleway-Medium.woff') format('woff');
|
||||
font-weight: $font-weight-500;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: $font-family-raleway;
|
||||
src: url('#{$fonts-path}/Raleway/Raleway-SemiBold.woff2') format('woff2'),
|
||||
url('#{$fonts-path}/Raleway/Raleway-SemiBold.woff') format('woff');
|
||||
font-weight: $font-weight-600;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: $font-family-raleway;
|
||||
src: url('#{$fonts-path}/Raleway/Raleway-Bold.woff2') format('woff2'),
|
||||
url('#{$fonts-path}/Raleway/Raleway-Bold.woff') format('woff');
|
||||
font-weight: $font-weight-700;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
|
||||
@font-face {
|
||||
font-family: $font-family-inter;
|
||||
src: url('#{$fonts-path}/Inter/Inter-Regular.ttf') format('truetype');
|
||||
font-weight: $font-weight-regular;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: $font-family-inter;
|
||||
src: url('#{$fonts-path}/Inter/Inter-Medium.ttf') format('truetype');
|
||||
font-weight: $font-weight-medium;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: $font-family-inter;
|
||||
src: url('#{$fonts-path}/Inter/Inter-SemiBold.ttf') format('truetype');
|
||||
font-weight: $font-weight-semibold;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: $font-family-inter;
|
||||
src: url('#{$fonts-path}/Inter/Inter-Bold.ttf') format('truetype');
|
||||
font-weight: $font-weight-bold;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: $font-family-ibm-plex-mono;
|
||||
src: url('#{$fonts-path}/IBM_Plex_Mono/IBMPlexMono-Regular.woff2') format('woff2'),
|
||||
url('#{$fonts-path}/IBM_Plex_Mono/IBMPlexMono-Regular.woff') format('woff');
|
||||
font-weight: $font-weight-400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
35
src/app/styles/index.scss
Normal file
|
@ -0,0 +1,35 @@
|
|||
@import './vars';
|
||||
@import './fonts';
|
||||
|
||||
html {
|
||||
background-color: $color-background-primary;
|
||||
color: $color-text-primary;
|
||||
font-family: $font-family-inter, $font-family-default;
|
||||
font-size: $font-size-16;
|
||||
line-height: $line-height-20;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
font-feature-settings: 'pnum' on, 'lnum' on;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
220
src/app/styles/mixins.scss
Normal file
|
@ -0,0 +1,220 @@
|
|||
@use 'sass:list';
|
||||
|
||||
/* positions */
|
||||
|
||||
@mixin position-absolute-full-screen {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/* size */
|
||||
|
||||
@mixin size($size) {
|
||||
min-width: $size;
|
||||
max-width: $size;
|
||||
min-height: $size;
|
||||
max-height: $size;
|
||||
}
|
||||
|
||||
/* placeholder */
|
||||
|
||||
@mixin placeholder {
|
||||
&::placeholder {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
/* buttons */
|
||||
|
||||
@mixin reset-button {
|
||||
align-items: flex-start;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
text-indent: 0;
|
||||
letter-spacing: inherit;
|
||||
word-spacing: inherit;
|
||||
text-transform: none;
|
||||
color: inherit;
|
||||
border: none;
|
||||
outline: none;
|
||||
background: none;
|
||||
text-shadow: none;
|
||||
font: inherit;
|
||||
line-height: inherit;
|
||||
cursor: default;
|
||||
box-sizing: border-box;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin reset-default-input {
|
||||
padding: unset;
|
||||
border: none;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
outline-offset: initial;
|
||||
}
|
||||
}
|
||||
|
||||
/* Хак для того, чтобы убрать браузерные autofill стили */
|
||||
@mixin remove-autofill-style {
|
||||
&:-webkit-autofill {
|
||||
/* stylelint-disable-next-line */
|
||||
-webkit-background-clip: text;
|
||||
}
|
||||
}
|
||||
|
||||
/* links */
|
||||
|
||||
@mixin link-reset {
|
||||
all: unset;
|
||||
}
|
||||
|
||||
@mixin focus-visible {
|
||||
/* stylelint-disable-next-line */
|
||||
&:global(.focus-visible) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin line-clamp($n) {
|
||||
display: -webkit-box;
|
||||
overflow: hidden;
|
||||
-webkit-line-clamp: $n;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
@mixin hide-default-input {
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/* stylelint-disable order/order */
|
||||
|
||||
@mixin transition($properties...) {
|
||||
$declarations: ();
|
||||
|
||||
@each $declaration in $properties {
|
||||
$duration: 0.2s;
|
||||
$delay: false;
|
||||
$timing-function: ease;
|
||||
$property: all;
|
||||
|
||||
@if type-of($declaration) == 'map' {
|
||||
$duration: if(map_get($declaration, 'duration'), #{map_get($declaration, 'duration')}, $duration);
|
||||
$delay: if(map_get($declaration, 'delay'), #{map_get($declaration, 'delay')}, $delay);
|
||||
$timing-function: if(
|
||||
map_get($declaration, 'timing-function'),
|
||||
#{map_get($declaration, 'timing-function')},
|
||||
$timing-function
|
||||
);
|
||||
$property: if(map_get($declaration, 'property'), #{map_get($declaration, 'property')}, $property);
|
||||
} @else {
|
||||
$property: $declaration;
|
||||
}
|
||||
|
||||
$delay-value: if($delay, ' ' + $delay, '');
|
||||
$declarations: list.append(
|
||||
$declarations,
|
||||
#{$property + ' ' + $duration + $delay-value + ' ' + $timing-function},
|
||||
comma
|
||||
);
|
||||
}
|
||||
|
||||
transition: $declarations;
|
||||
}
|
||||
|
||||
/* stylelint-enable order/order */
|
||||
|
||||
@mixin flex {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: baseline;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
@mixin flex-center {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@mixin flex-between {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
@mixin flex-middle {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@mixin flex-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
@mixin flex-col-middle {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@mixin text-overflow {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
/* scrollbar */
|
||||
|
||||
$scrollbar-width: 12px;
|
||||
|
||||
@mixin scrollbar {
|
||||
&::-webkit-scrollbar {
|
||||
width: $scrollbar-width;
|
||||
height: $scrollbar-width;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
border: 4px solid transparent;
|
||||
border-radius: 6px;
|
||||
background-color: $color-on-surface-light-400;
|
||||
background-clip: content-box;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb:hover {
|
||||
background-color: $color-on-surface-light-300;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin hide-scrollbar {
|
||||
overflow-y: auto;
|
||||
-ms-overflow-style: none;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none; /* for Chrome, Safari, and Opera */
|
||||
}
|
||||
}
|
7
src/app/styles/radius.scss
Normal file
|
@ -0,0 +1,7 @@
|
|||
$radius-none: 0;
|
||||
$radius-small: 4px;
|
||||
$radius-medium-x: 6px;
|
||||
$radius-medium: 8px;
|
||||
$radius-large: 12px;
|
||||
$radius-large-x: 16px;
|
||||
$radius-large-xx: 24px;
|
7
src/app/styles/shadow.scss
Normal file
|
@ -0,0 +1,7 @@
|
|||
$shadow-dropdown: 0 1px 24px 0 rgb(0 0 0 / 40%);
|
||||
$shadow-hover: 0 4px 24px 0 rgb(0 0 0 / 24%);
|
||||
$shadow-bottom-item: 0 -2px 12px 0 rgb(0 0 0 / 25%);
|
||||
$shadow-top: 0 -4px 1px rgb(20 20 20 / 8%), 0 -12px 6px rgb(20 20 20 / 16%), 0 -8px 20px rgb(20 20 20 / 24%);
|
||||
$shadow-left: -4px 0 1px rgb(20 20 20 / 8%), -12px 0 6px rgb(20 20 20 / 16%), -8px 0 20px rgb(20 20 20 / 24%);
|
||||
$shadow-right: 4px 0 1px rgb(20 20 20 / 8%), 12px 0 6px rgb(20 20 20 / 16%), 8px 0 20px rgb(20 20 20 / 24%);
|
||||
$shadow-short: 0 6px 16px -12px rgb(23 40 77 / 6%);
|
12
src/app/styles/spacing.scss
Normal file
|
@ -0,0 +1,12 @@
|
|||
$spacing-small-4x: 4px;
|
||||
$spacing-small-3x: 8px;
|
||||
$spacing-small-2x: 12px;
|
||||
$spacing-small-x: 16px;
|
||||
$spacing-small: 24px;
|
||||
$spacing-medium: 32px;
|
||||
$spacing-medium-x: 40px;
|
||||
$spacing-large: 48px;
|
||||
$spacing-large-x: 64px;
|
||||
$spacing-large-2x: 72px;
|
||||
$spacing-large-3x: 96px;
|
||||
$spacing-large-4x: 124px;
|
10
src/app/styles/vars.scss
Normal file
|
@ -0,0 +1,10 @@
|
|||
@import 'colors';
|
||||
@import 'baseText';
|
||||
@import 'breakpoints';
|
||||
@import 'mixins';
|
||||
@import 'radius';
|
||||
@import 'spacing';
|
||||
@import 'z-index';
|
||||
@import 'shadow';
|
||||
|
||||
$header-height: 64px;
|
11
src/app/styles/z-index.scss
Normal file
|
@ -0,0 +1,11 @@
|
|||
$z-index-behind: -1;
|
||||
$z-index-default: 0;
|
||||
$z-index-primary: 1;
|
||||
$z-index-secondary: 2;
|
||||
$z-index-dropdown-menu: 10;
|
||||
$z-index-sidebar: 100;
|
||||
$z-index-editor: 100;
|
||||
$z-index-overlay: 101;
|
||||
$z-index-modal: 1000;
|
||||
$z-index-notification: 1001;
|
||||
$z-index-max: 99999;
|
BIN
src/assets/fonts/IBM_Plex_Mono/IBMPlexMono-Regular.woff
Normal file
BIN
src/assets/fonts/IBM_Plex_Mono/IBMPlexMono-Regular.woff2
Normal file
BIN
src/assets/fonts/Inter/Inter-Black.ttf
Executable file
BIN
src/assets/fonts/Inter/Inter-Bold.ttf
Executable file
BIN
src/assets/fonts/Inter/Inter-ExtraBold.ttf
Executable file
BIN
src/assets/fonts/Inter/Inter-ExtraLight.ttf
Executable file
BIN
src/assets/fonts/Inter/Inter-Light.ttf
Executable file
BIN
src/assets/fonts/Inter/Inter-Medium.ttf
Executable file
BIN
src/assets/fonts/Inter/Inter-Regular.ttf
Executable file
BIN
src/assets/fonts/Inter/Inter-SemiBold.ttf
Executable file
BIN
src/assets/fonts/Inter/Inter-Thin.ttf
Executable file
BIN
src/assets/fonts/Raleway/Raleway-Bold.woff
Normal file
BIN
src/assets/fonts/Raleway/Raleway-Bold.woff2
Normal file
BIN
src/assets/fonts/Raleway/Raleway-Medium.woff
Normal file
BIN
src/assets/fonts/Raleway/Raleway-Medium.woff2
Normal file
BIN
src/assets/fonts/Raleway/Raleway-Regular.woff
Normal file
BIN
src/assets/fonts/Raleway/Raleway-Regular.woff2
Normal file
BIN
src/assets/fonts/Raleway/Raleway-SemiBold.woff
Normal file
BIN
src/assets/fonts/Raleway/Raleway-SemiBold.woff2
Normal file
3
src/assets/icons/loader.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 3C11.4474 3 10.9994 3.448 10.9994 4.00065C10.9994 4.55329 11.4474 5.00129 12 5.00129C15.8653 5.00129 18.9987 8.13472 18.9987 12C18.9987 15.8653 15.8653 18.9987 12 18.9987C8.13472 18.9987 5.00129 15.8653 5.00129 12C5.00129 11.4474 4.55329 10.9994 4.00065 10.9994C3.448 10.9994 3 11.4474 3 12C3 16.9706 7.02944 21 12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3Z" fill="currentColor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 556 B |
5
src/assets/icons/right.svg
Normal file
|
@ -0,0 +1,5 @@
|
|||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15.834 9.99983H4.16731" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M11.6673 14.1665L15.834 9.99983" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M11.6673 5.83317L15.834 9.99983" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 494 B |
5
src/assets/icons/upload.svg
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3 14.25C3.41421 14.25 3.75 14.5858 3.75 15C3.75 16.4354 3.75159 17.4365 3.85315 18.1919C3.9518 18.9257 4.13225 19.3142 4.40901 19.591C4.68577 19.8678 5.07435 20.0482 5.80812 20.1469C6.56347 20.2484 7.56459 20.25 9 20.25H15C16.4354 20.25 17.4365 20.2484 18.1919 20.1469C18.9257 20.0482 19.3142 19.8678 19.591 19.591C19.8678 19.3142 20.0482 18.9257 20.1469 18.1919C20.2484 17.4365 20.25 16.4354 20.25 15C20.25 14.5858 20.5858 14.25 21 14.25C21.4142 14.25 21.75 14.5858 21.75 15V15.0549C21.75 16.4225 21.75 17.5248 21.6335 18.3918C21.5125 19.2919 21.2536 20.0497 20.6517 20.6516C20.0497 21.2536 19.2919 21.5125 18.3918 21.6335C17.5248 21.75 16.4225 21.75 15.0549 21.75H8.94513C7.57754 21.75 6.47522 21.75 5.60825 21.6335C4.70814 21.5125 3.95027 21.2536 3.34835 20.6517C2.74643 20.0497 2.48754 19.2919 2.36652 18.3918C2.24996 17.5248 2.24998 16.4225 2.25 15.0549C2.25 15.0366 2.25 15.0183 2.25 15C2.25 14.5858 2.58579 14.25 3 14.25Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 2.25C12.2106 2.25 12.4114 2.33852 12.5535 2.49392L16.5535 6.86892C16.833 7.17462 16.8118 7.64902 16.5061 7.92852C16.2004 8.20802 15.726 8.18678 15.4465 7.88108L12.75 4.9318V16C12.75 16.4142 12.4142 16.75 12 16.75C11.5858 16.75 11.25 16.4142 11.25 16V4.9318L8.55353 7.88108C8.27403 8.18678 7.79963 8.20802 7.49393 7.92852C7.18823 7.64902 7.16698 7.17462 7.44648 6.86892L11.4465 2.49392C11.5886 2.33852 11.7894 2.25 12 2.25Z" fill="currentColor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.7 KiB |