├── frontend ├── src │ ├── vite-env.d.ts │ ├── main.tsx │ ├── components │ │ ├── Info.tsx │ │ ├── Maps │ │ │ ├── Marker.tsx │ │ │ └── Map.tsx │ │ ├── StatsCard.tsx │ │ ├── StatusIndicator.tsx │ │ ├── Footer.tsx │ │ ├── FAQ.tsx │ │ ├── Landing.tsx │ │ ├── Dashboard.tsx │ │ └── CallsTable.tsx │ ├── firebaseConfig.ts │ ├── index.css │ ├── App.tsx │ └── types │ │ └── calls.ts ├── .env ├── public │ ├── favicon.png │ ├── call_center.jpg │ ├── vite.svg │ └── undraw_active_support.svg ├── .prettierrc ├── .eslintignore ├── vite.config.ts ├── tsconfig.node.json ├── tsconfig.eslint.json ├── index.html ├── tsconfig.json ├── .eslintrc.cjs └── package.json ├── assets ├── OperatorAI.png └── OperatorAI-Header.png ├── backend ├── .env.example ├── .prettierrc ├── package.json ├── src │ ├── firebase.js │ └── utils.js ├── index.js └── package-lock.json ├── .gitignore ├── LICENSE └── README.md /frontend/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /frontend/.env: -------------------------------------------------------------------------------- 1 | VITE_GOOGLE_API_KEY=AIzaSyBWCLdCVQ1siM_M5zExHqsMLItO_nUvT4U -------------------------------------------------------------------------------- /assets/OperatorAI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtemir/OperatorAI/HEAD/assets/OperatorAI.png -------------------------------------------------------------------------------- /frontend/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtemir/OperatorAI/HEAD/frontend/public/favicon.png -------------------------------------------------------------------------------- /assets/OperatorAI-Header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtemir/OperatorAI/HEAD/assets/OperatorAI-Header.png -------------------------------------------------------------------------------- /backend/.env.example: -------------------------------------------------------------------------------- 1 | ASSEMBLYAI_API_KEY= 2 | MAPS_API_KEY= 3 | HUGGINGFACE_API_KEY= 4 | HUGGINGFACE_API_KEY2= 5 | -------------------------------------------------------------------------------- /backend/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "printWidth": 120, 4 | "endOfLine": "auto" 5 | } 6 | -------------------------------------------------------------------------------- /frontend/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "printWidth": 120, 4 | "endOfLine": "auto" 5 | } 6 | -------------------------------------------------------------------------------- /frontend/public/call_center.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtemir/OperatorAI/HEAD/frontend/public/call_center.jpg -------------------------------------------------------------------------------- /frontend/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .prettierrc.js 4 | .eslintrc.cjs 5 | tsconfig.json 6 | vite.config.ts 7 | env.d.ts -------------------------------------------------------------------------------- /frontend/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import react from '@vitejs/plugin-react'; 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | }); 8 | -------------------------------------------------------------------------------- /frontend/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /frontend/tsconfig.eslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": [ 4 | // 👇️ add all the directories and files 5 | // that you want to lint here 6 | "src", 7 | "tests", 8 | 9 | // add all files in which you see 10 | // the "parserOptions.project" error 11 | ".eslintrc.cjs" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /frontend/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import { ChakraProvider } from '@chakra-ui/react'; 4 | import App from './App'; 5 | 6 | ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( 7 | 8 | 9 | 10 | 11 | 12 | ); 13 | -------------------------------------------------------------------------------- /frontend/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | OperatorAI 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /frontend/src/components/Info.tsx: -------------------------------------------------------------------------------- 1 | import { Flex, Heading } from '@chakra-ui/react'; 2 | import { HiInformationCircle } from 'react-icons/hi'; 3 | export const Info = ({ text }: { text: string }) => { 4 | return ( 5 | 6 | 7 | 8 | {text} 9 | 10 | 11 | ); 12 | }; 13 | -------------------------------------------------------------------------------- /backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backend", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "scripts": { 6 | "start": "node index.js", 7 | "pretty": "prettier --write \"./**/*.{js,json}\"" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "description": "", 12 | "dependencies": { 13 | "axios": "^1.2.1", 14 | "body-parser": "^1.20.1", 15 | "dotenv": "^16.0.3", 16 | "express": "^4.18.2", 17 | "firebase": "^9.15.0", 18 | "prettier": "^2.8.1", 19 | "wavefile": "^11.0.0", 20 | "ws": "^8.11.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /frontend/src/firebaseConfig.ts: -------------------------------------------------------------------------------- 1 | import { initializeApp } from 'firebase/app'; 2 | import { getDatabase } from 'firebase/database'; 3 | 4 | export const app = initializeApp({ 5 | apiKey: 'AIzaSyCvco7fC8XnCjXGir_bY_QKXVrn7qdZglU', 6 | authDomain: 'assemblyai-hackathon.firebaseapp.com', 7 | databaseURL: 'https://assemblyai-hackathon-default-rtdb.firebaseio.com', 8 | projectId: 'assemblyai-hackathon', 9 | storageBucket: 'assemblyai-hackathon.appspot.com', 10 | messagingSenderId: '675472088767', 11 | appId: '1:675472088767:web:07f34df7eb2a635ebb300a', 12 | }); 13 | 14 | export const db = getDatabase(app); 15 | -------------------------------------------------------------------------------- /frontend/src/components/Maps/Marker.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react'; 2 | 3 | export const Marker: React.FC = (options) => { 4 | const [marker, setMarker] = useState(); 5 | 6 | useEffect(() => { 7 | if (!marker) { 8 | setMarker(new google.maps.Marker()); 9 | } 10 | 11 | // remove marker from map on unmount 12 | return () => { 13 | if (marker) { 14 | marker.setMap(null); 15 | } 16 | }; 17 | }, [marker]); 18 | 19 | useEffect(() => { 20 | if (marker) { 21 | marker.setOptions(options); 22 | } 23 | }, [marker, options]); 24 | 25 | return null; 26 | }; 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | dist 5 | tmp 6 | /out-tsc 7 | 8 | # dependencies 9 | node_modules 10 | 11 | # IDEs and editors 12 | .idea 13 | .project 14 | .classpath 15 | .c9/ 16 | *.launch 17 | .settings/ 18 | *.sublime-workspace 19 | 20 | # IDE - VSCode 21 | .vscode/* 22 | !.vscode/settings.json 23 | !.vscode/tasks.json 24 | !.vscode/launch.json 25 | !.vscode/extensions.json 26 | 27 | # misc 28 | /.sass-cache 29 | /connect.lock 30 | /coverage 31 | /libpeerconnection.log 32 | npm-debug.log 33 | yarn-error.log 34 | testem.log 35 | /typings 36 | .env 37 | 38 | # System Files 39 | .DS_Store 40 | Thumbs.db -------------------------------------------------------------------------------- /frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "noUnusedLocals": false, 18 | "noUnusedParameters": false, 19 | "jsx": "react-jsx" 20 | }, 21 | "include": ["src"], 22 | "references": [{ "path": "./tsconfig.node.json" }] 23 | } 24 | -------------------------------------------------------------------------------- /frontend/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | es2021: true, 5 | node: true, 6 | }, 7 | extends: [ 8 | 'eslint:recommended', 9 | 'plugin:react/recommended', 10 | 'plugin:react/jsx-runtime', 11 | 'plugin:react-hooks/recommended', 12 | 'plugin:@typescript-eslint/recommended', 13 | ], 14 | parser: '@typescript-eslint/parser', 15 | parserOptions: { 16 | ecmaFeatures: { 17 | jsx: true, 18 | }, 19 | ecmaVersion: 2021, 20 | sourceType: 'module', 21 | project: 'tsconfig.eslint.json', 22 | tsconfigRootDir: __dirname, 23 | }, 24 | plugins: ['react', '@typescript-eslint'], 25 | rules: { 26 | 'react/jsx-uses-react': 'off', 27 | 'react/react-in-jsx-scope': 'off', 28 | semi: 'off', 29 | '@typescript-eslint/semi': 'error', 30 | }, 31 | settings: { 32 | react: { 33 | version: 'detect', 34 | }, 35 | }, 36 | }; 37 | -------------------------------------------------------------------------------- /frontend/src/index.css: -------------------------------------------------------------------------------- 1 | .blinking-cursor { 2 | font-weight: 400; 3 | font-size: 18px; 4 | color: #2e3d48; 5 | -webkit-animation: 0.8s blink step-end infinite; 6 | -moz-animation: 0.8s blink step-end infinite; 7 | -ms-animation: 0.8s blink step-end infinite; 8 | -o-animation: 0.8s blink step-end infinite; 9 | animation: 0.8s blink step-end infinite; 10 | } 11 | 12 | @keyframes blink { 13 | from, 14 | to { 15 | color: transparent; 16 | } 17 | 50% { 18 | color: black; 19 | } 20 | } 21 | 22 | @-moz-keyframes blink { 23 | from, 24 | to { 25 | color: transparent; 26 | } 27 | 50% { 28 | color: black; 29 | } 30 | } 31 | 32 | @-webkit-keyframes blink { 33 | from, 34 | to { 35 | color: transparent; 36 | } 37 | 50% { 38 | color: black; 39 | } 40 | } 41 | 42 | @-ms-keyframes blink { 43 | from, 44 | to { 45 | color: transparent; 46 | } 47 | 50% { 48 | color: black; 49 | } 50 | } 51 | 52 | @-o-keyframes blink { 53 | from, 54 | to { 55 | color: transparent; 56 | } 57 | 50% { 58 | color: black; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /frontend/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { Container } from '@chakra-ui/react'; 2 | import { ref } from 'firebase/database'; 3 | import { useListVals } from 'react-firebase-hooks/database'; 4 | 5 | import { db } from './firebaseConfig'; 6 | 7 | import { CallData } from './types/calls'; 8 | 9 | import { Dashboard } from './components/Dashboard'; 10 | import { Landing } from './components/Landing'; 11 | import { Footer } from './components/Footer'; 12 | 13 | import './index.css'; 14 | 15 | export interface MapCoordinates { 16 | name: string; 17 | location: Location; 18 | } 19 | 20 | function App() { 21 | const [values, loading, error] = useListVals(ref(db, 'calls')); 22 | 23 | const calls: CallData[] | undefined = values 24 | ?.map((call) => ({ ...call, key: call.callSid })) 25 | .filter(({ key }) => !!key); 26 | 27 | return ( 28 | 29 | 30 | 31 |