diff --git a/package-lock.json b/package-lock.json index 3f6ccbb..8d575ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "strowger-dialer", + "name": "tinyphone-ui", "version": "0.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "strowger-dialer", + "name": "tinyphone-ui", "version": "0.1.0", "dependencies": { "@fortawesome/fontawesome-svg-core": "^1.2.28", @@ -18326,7 +18326,7 @@ "node_modules/react-toastify": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-5.5.0.tgz", - "integrity": "sha1-9V3kT2tePOOxO2nlu0Qn8slASCI=", + "integrity": "sha512-jsVme7jALIFGRyQsri/g4YTsRuaaGI70T6/ikjwZMB4mwTZaCWqj5NqxhGrRStKlJc5npXKKvKeqTiRGQl78LQ==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.4.2", @@ -34162,7 +34162,7 @@ "react-toastify": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-5.5.0.tgz", - "integrity": "sha1-9V3kT2tePOOxO2nlu0Qn8slASCI=", + "integrity": "sha512-jsVme7jALIFGRyQsri/g4YTsRuaaGI70T6/ikjwZMB4mwTZaCWqj5NqxhGrRStKlJc5npXKKvKeqTiRGQl78LQ==", "requires": { "@babel/runtime": "^7.4.2", "classnames": "^2.2.6", diff --git a/package.json b/package.json index 308729a..dc9bdc4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "tinyphone-ui", "version": "0.1.0", - "homepage" : "http://voiceip.github.io/tinyphone-ui", + "homepage": "http://voiceip.github.io/tinyphone-ui", "private": true, "dependencies": { "@fortawesome/fontawesome-svg-core": "^1.2.28", diff --git a/src/App.css b/src/App.css index 40abd2d..ca4ae97 100644 --- a/src/App.css +++ b/src/App.css @@ -1,45 +1,88 @@ @import url(https://fonts.googleapis.com/css?family=Roboto:400,100); + +/* Color Scheme */ +:root { + --primary: #2196F3; + --primary-variant: #1976D2; + --secondary: #26A69A; + --background: #F0F2F5; + --surface: #FFFFFF; + --text-primary: #212121; + --text-secondary: #757575; +} + +/* Global Styles */ body{ font-family: 'Roboto'; + background-color: var(--background); + font-size: 16px; + line-height: 1.5; + color: var(--text-primary); } -nav.navbar{ +nav.navbar { display: flex; align-items: center; min-height: 65px; + background-color: var(--primary); + color: var(--surface); + box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1); +} + +.alert-danger{ + background-color: #F2DEDE; /* very pale pink */ + color: #8A4A4A; /* muted red */ + padding: 15px; + border-radius: 5px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + border: none; } + .login-container{ margin-top: 100px; display: flex; justify-content: center; } + .info-container{ margin:50px; margin-top: 100px; } .login{ - width: 400px; - padding: 40px; - background-color: #F7F7F7; - margin: 0 auto 10px; - border-radius: 2px; - box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); - overflow: hidden; + width: 400px; + padding: 40px; + background-color: var(--surface); + margin: 0 auto 10px; + border-radius: 8px; + box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1); + overflow: hidden; } .name{ - color: #fff; + color: var(--surface); margin: 0 15px; font-weight: bold; } + .message{ margin-top: 10px; } + .loading{ margin-right: 10px; } +/*Form*/ + +input[type="text"], input[type="password"] { + border: 1px solid var(--text-secondary); + border-radius: 4px; + padding: 8px; + margin-bottom: 10px; + width: 100%; +} + /* Progress Bar */ /* Thanks to https://codepen.io/holdencreative/pen/vEVbwv */ .progress-loader { @@ -50,11 +93,11 @@ nav.navbar{ background-color: #acece6; background-clip: padding-box; overflow: hidden; } - .progress-loader .determinate { - position: absolute; - background-color: inherit; - top: 0; - bottom: 0; + .progress-loader .determinate { + position: absolute; + background-color: inherit; + top: 0; + bottom: 0; background-color: #26a69a; transition: width .3s linear; } .progress-loader .indeterminate { @@ -127,87 +170,108 @@ nav.navbar{ .dialer { margin: 20px auto 0; width: 280px; - text-align: center; - box-shadow: 20px 20px 10px grey; + text-align: center; + background-color: var(--surface); + border-radius: 10px; + box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1); } .StatusArea { padding-top: 7px; - height: 120px; - width: 280px; + padding: 15px; + width: 100%; text-align: center; font-size: 16px; - background-color: #0470bf; - color: white; + background-color: var(--primary); + color: var(--surface); font-weight: bold; - border-style: outset; - border-color: #599ef2; + border-top-left-radius: 10px; + border-top-right-radius: 10px; } .functionArea { display: grid; grid-template-columns: repeat(2, 1fr); - grid-auto-rows: minmax(2px, auto); + grid-auto-rows: minmax(60px, auto); text-align: center; - background-color: #eaeaea; } .keypad { display: grid; grid-template-columns: repeat(3, 1fr); - grid-auto-rows: minmax(80px, auto); + grid-auto-rows: minmax(70px, auto); text-align: center; - background-color: #eaeaea; + gap: 5px; /* Keep horizontal gap at 5px */ + row-gap: 3px; /* Reduce vertical gap to 3px */ } .button { - margin: 18px auto 0; - border-radius: 4px; + margin: 10px auto; + border-radius: 8px; width: 85%; height: 70%; - padding: 8px; - background: #027cd5; - color: white; - border-color: #599ef2; - border-style: outset; + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + background-color: #E3F2FD; /* Lighter blue */ + box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2); /* Subtle shadow */ + color: var(--text-primary); + border: none; + font-weight: bold; font-size: 18px; + + + cursor: pointer; font-family: 'Roboto', serif; } .button:hover { - background: #166095; + background: var(--primary); + } input[type="display"] { - height: 60px; - width: 280px; - text-align: center; - font-size: 22px; - background-color: #0470bf; - color: white; - font-weight: bold; - outline: none !important; - border-style: none; + height: 60px; /* Keep the fixed height */ + width: 100%; /* Fill available width */ + font-size: 22px; /* Keep the font size */ + background-color: #E3F2FD; /* Keep the background color */ + color: var(--text-primary); /* Keep the text color */ + font-weight: bold; /* Keep the font weight */ + white-space: nowrap; /* Prevent text from wrapping */ + overflow-x: auto; /* Enable horizontal scrolling */ + text-align: center; /* Align to center */ + border: none; + outline: none; } .functionButton { margin: 10px auto; - width: 60px; - height: 60px; - background-color: #eaeaea; - border-style: none; - outline: none !important; -} - -.functionButton:hover { - opacity: 0.50; -} + width: 85%; + background-color: var(--surface); /* Match number button background */ + border: none; /* Remove border */ + border-radius: 8px; /* Match number button border-radius */ + outline: none !important; + display: flex; + align-items: center; + justify-content: center; + position: relative; + } + + .functionButton:hover { + background-color: var(--primary); + } + .sub-dig { font-size: 12px; font-weight: 500; - position: relative; - top: -3px; + pointer-events: none; + margin-top: -3px; +} + +.overflowing { + text-align: right; } \ No newline at end of file diff --git a/src/App.js b/src/App.js index b0f1c23..0fb48ac 100644 --- a/src/App.js +++ b/src/App.js @@ -1,4 +1,4 @@ -import React, {Fragment, useEffect, useState, useCallback} from 'react'; +import React, {Fragment, useEffect, useState, useCallback, useRef} from 'react'; import {shallowEqual, useDispatch, useSelector} from 'react-redux'; import Form from 'react-bootstrap/Form'; import Button from 'react-bootstrap/Button'; @@ -7,7 +7,7 @@ import Spinner from 'react-bootstrap/Spinner'; import {SlideDown} from 'react-slidedown' import 'react-slidedown/lib/slidedown.css' import {callStatus, dial, dtmf, getAccounts, getSoftphoneStatus, hangUp, hold, loginSync, logout, unHold, updateCallStatus} from './actions'; -import {ToastContainer} from 'react-toastify'; +import {ToastContainer, Bounce} from 'react-toastify'; import logo from './logo.png'; import {CALL_TERMINATE, CONFIRMED, DISCONNECTED, LOADER, EARLY, LOCAL_HOLD} from './constant'; import './App.css'; @@ -136,6 +136,8 @@ function WSEventStream() { function Dialer() { const dispatch = useDispatch(); const loading = useSelector(state => state.loading, shallowEqual); + const inputRef = useRef(null); + const [phoneNumber, setPhoneNumber] = useState(""); const isCallDialed = useSelector(state => state.callDialed, shallowEqual); const accountName = useSelector(state => state.accountName, shallowEqual); @@ -156,7 +158,9 @@ function Dialer() { } function clear() { - setPhoneNumber(""); + if (phoneNumber.length > 0) { + setPhoneNumber(phoneNumber.slice(0, -1)); + } } const dialNumber = () => { @@ -236,6 +240,22 @@ function Dialer() { return () => clearInterval(interval); }, [isCallDialed]); + useEffect(() => { + if (inputRef.current) { + const input = inputRef.current; + + if (input.scrollWidth > input.clientWidth) { + input.classList.add('overflowing'); + input.scrollLeft = input.scrollWidth; + } else { + input.classList.remove('overflowing'); + } + } + }, [phoneNumber]); + + + + return (