diff --git a/.env.local b/.env.local index 8ca3788..3f17611 100644 --- a/.env.local +++ b/.env.local @@ -1,3 +1,4 @@ CI=false # Needed to skip warnings from jest@beta in package.json SKIP_PREFLIGHT_CHECK=true +REACT_APP_GOOGLE_KEY=AIzaSyAKXAOSMhEWTb1PAUTbDUGof50hNyY-BBw diff --git a/.gitignore b/.gitignore index ea39237..668a207 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ build src/config.js .env +.local #Firebase cache .firebase/** diff --git a/package-lock.json b/package-lock.json index 30aee5f..ed50579 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "myProject", + "name": "GiveMe.lk", "version": "0.0.1", "lockfileVersion": 1, "requires": true, @@ -2270,6 +2270,11 @@ "@types/yargs": "^13.0.0" } }, + "@mapbox/point-geometry": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz", + "integrity": "sha1-ioP5M1x4YO/6Lu7KJUMyqgru2PI=" + }, "@material-ui/core": { "version": "4.9.9", "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.9.9.tgz", @@ -2952,6 +2957,14 @@ "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", "dev": true }, + "@types/use-deep-compare-effect": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/use-deep-compare-effect/-/use-deep-compare-effect-1.2.0.tgz", + "integrity": "sha512-2uNqaSobMvUTGR7G72tUHDX+Kx341q25OuM0m2B6VID7eljIvYuDaFTKfmDnbvej67yEhCc35zA6dmIYriwOXA==", + "requires": { + "@types/react": "*" + } + }, "@types/yargs": { "version": "13.0.8", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.8.tgz", @@ -6601,6 +6614,11 @@ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", "dev": true }, + "dequal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-1.0.0.tgz", + "integrity": "sha512-/Nd1EQbQbI9UbSHrMiKZjFLrXSnU328iQdZKPQf78XQI6C+gutkFUeoHpG5J08Ioa6HeRbRNFpSIclh1xyG0mw==" + }, "des.js": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", @@ -10027,6 +10045,24 @@ } } }, + "google-map-react": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/google-map-react/-/google-map-react-1.1.7.tgz", + "integrity": "sha512-OWwfvVlJG3aQbDZOezWPzT7b8uqk5iMya5yEfBcfGYBFONna5UYCWZl49/cS0j1DPigtwtN0YCzPKjXMQHOUeA==", + "requires": { + "@mapbox/point-geometry": "^0.1.0", + "eventemitter3": "^1.1.0", + "prop-types": "^15.5.6", + "scriptjs": "^2.5.7" + }, + "dependencies": { + "eventemitter3": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", + "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=" + } + } + }, "google-p12-pem": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-2.0.4.tgz", @@ -10836,6 +10872,14 @@ } } }, + "html-parse-stringify2": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify2/-/html-parse-stringify2-2.0.1.tgz", + "integrity": "sha1-3FZwtyksoVi3vJFsmmc1rIhyg0o=", + "requires": { + "void-elements": "^2.0.1" + } + }, "html-webpack-plugin": { "version": "4.0.0-beta.11", "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-4.0.0-beta.11.tgz", @@ -11245,6 +11289,22 @@ "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz", "integrity": "sha512-EcuixamT82oplpoJ2XU4pDtKGWQ7b00CD9f1ug9IaQ3p1bkHMiKCZ9ut9QDI6qsa6cpUuB+A/I+zLtdNK4n2DQ==" }, + "i18next": { + "version": "19.4.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-19.4.1.tgz", + "integrity": "sha512-dC3ue15jkLebN2je4xEjfjVYd/fSAo+UVK9f+JxvceCJRowkI+S0lGohgKejqU+FYLfvw9IAPylIIEWwR8Djrg==", + "requires": { + "@babel/runtime": "^7.3.1" + } + }, + "i18next-browser-languagedetector": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-4.0.2.tgz", + "integrity": "sha512-AK4IZ3XST4HIKShgpB2gOFeDPrMOnZx56GLA6dGo/8rvkiczIlq05lV8w77c3ShEZxtTZeUVRI4Q/cBFFVXS/w==", + "requires": { + "@babel/runtime": "^7.5.5" + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -14387,6 +14447,11 @@ "safe-buffer": "^5.0.1" } }, + "kdbush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-3.0.0.tgz", + "integrity": "sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew==" + }, "killable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", @@ -18694,6 +18759,15 @@ "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-5.3.1.tgz", "integrity": "sha512-n73nVyBaTBL4r2//6ZWi5x41ZYsKRtrqbNf40KILv4XrNO/DQbzFRdr/s53Ua+M0y76TKS3xmOEnk6hWhVTR/w==" }, + "react-i18next": { + "version": "11.3.4", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.3.4.tgz", + "integrity": "sha512-IRZMD7PAM3C+fJNzRbyLNi1ZD0kc3Z3obBspJjEl+9H+ME41PhVor3BpdIqv/Rm7lUoGhMjmpu42J45ooJ61KA==", + "requires": { + "@babel/runtime": "^7.3.1", + "html-parse-stringify2": "2.0.1" + } + }, "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -18704,6 +18778,11 @@ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, + "react-moment": { + "version": "0.9.7", + "resolved": "https://registry.npmjs.org/react-moment/-/react-moment-0.9.7.tgz", + "integrity": "sha512-ifzUrUGF6KRsUN2pRG5k56kO0mJBr8kRkWb0wNvtFIsBIxOuPxhUpL1YlXwpbQCbHq23hUu6A0VEk64HsFxk9g==" + }, "react-redux": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.0.tgz", @@ -19896,6 +19975,11 @@ "ajv-keywords": "^3.4.1" } }, + "scriptjs": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/scriptjs/-/scriptjs-2.5.9.tgz", + "integrity": "sha512-qGVDoreyYiP1pkQnbnFAUIS5AjenNwwQBdl7zeos9etl+hYKWahjRTfzAZZYBv5xNHx7vNKCmaLDQZ6Fr2AEXg==" + }, "select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -20918,6 +21002,14 @@ } } }, + "supercluster": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-7.0.0.tgz", + "integrity": "sha512-8VuHI8ynylYQj7Qf6PBMWy1PdgsnBiIxujOgc9Z83QvJ8ualIYWNx2iMKyKeC4DZI5ntD9tz/CIwwZvIelixsA==", + "requires": { + "kdbush": "^3.0.0" + } + }, "superstatic": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/superstatic/-/superstatic-6.0.4.tgz", @@ -21065,6 +21157,21 @@ "util.promisify": "~1.0.0" } }, + "swr": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/swr/-/swr-0.2.0.tgz", + "integrity": "sha512-8IZCdM0deUPhDiqOmyaj0BsnNjav1fu83nD0d07PEAzOHOn+lxcJOxwXeDBShwF6qCeZ8u8ab+a2yXkjD8yT3A==", + "requires": { + "fast-deep-equal": "2.0.1" + }, + "dependencies": { + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + } + } + }, "symbol-observable": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", @@ -22249,11 +22356,30 @@ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, + "use-deep-compare-effect": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/use-deep-compare-effect/-/use-deep-compare-effect-1.3.1.tgz", + "integrity": "sha512-ejL+Al+aeDyC9Sywx56ti4PtSwkf6BH27tEptMWF2cfO41/auG0nRRsArh6Vv5bUyBe3z7IyxmgQCK5nas70hg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@types/use-deep-compare-effect": "^1.2.0", + "dequal": "^1.0.0" + } + }, "use-position": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/use-position/-/use-position-0.0.6.tgz", "integrity": "sha512-iAibEtuA3o7ebx03eExIIysqNz2U/PZO2NA+KZfvAOPOrnwc2mWytV4HfpUN+onmhN6bdpiCSZY9U9IzUgNSag==" }, + "use-supercluster": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/use-supercluster/-/use-supercluster-0.2.6.tgz", + "integrity": "sha512-rmTDacYkUa0wbyKYP33VnPQwyf4gYuUw1pYn14rHue6bFk+WQHq/QtVSVMjWkvmLvsAZY98vvy7A2ldAr8I/QQ==", + "requires": { + "dequal": "^1.0.0", + "use-deep-compare-effect": "^1.3.0" + } + }, "util": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", @@ -22363,6 +22489,11 @@ "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", "dev": true }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=" + }, "w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", diff --git a/public/img/Dairy.svg b/public/img/Dairy.svg new file mode 100644 index 0000000..0cbf835 --- /dev/null +++ b/public/img/Dairy.svg @@ -0,0 +1,2 @@ + + diff --git a/public/img/Grocery.svg b/public/img/Grocery.svg new file mode 100644 index 0000000..9b00d84 --- /dev/null +++ b/public/img/Grocery.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/img/Meat,Seafood & Poultry.svg b/public/img/Meat,Seafood & Poultry.svg new file mode 100644 index 0000000..36ccdc3 --- /dev/null +++ b/public/img/Meat,Seafood & Poultry.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/img/grains.svg b/public/img/grains.svg new file mode 100644 index 0000000..3456bb3 --- /dev/null +++ b/public/img/grains.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/containers/Navbar/AccountMenu.js b/src/containers/Navbar/AccountMenu.js index 7258838..ffdde04 100644 --- a/src/containers/Navbar/AccountMenu.js +++ b/src/containers/Navbar/AccountMenu.js @@ -15,10 +15,10 @@ const useStyles = makeStyles((theme) => ({ button: { textTransform: 'none', marginLeft: '10px', - [theme.breakpoints.down(600)]: { + [theme.breakpoints.down(715)]: { display: 'none' }, - [theme.breakpoints.up(600)]: { + [theme.breakpoints.up(715)]: { display: 'inline-flex' } }, @@ -26,10 +26,10 @@ const useStyles = makeStyles((theme) => ({ marginLeft: '5px' }, buttonCollapse: { - [theme.breakpoints.down(600)]: { + [theme.breakpoints.down(715)]: { display: 'inline-flex' }, - [theme.breakpoints.up(600)]: { + [theme.breakpoints.up(715)]: { display: 'none' } } diff --git a/src/containers/Navbar/Navbar.styles.js b/src/containers/Navbar/Navbar.styles.js index 5869456..7a49003 100644 --- a/src/containers/Navbar/Navbar.styles.js +++ b/src/containers/Navbar/Navbar.styles.js @@ -1,4 +1,4 @@ -export default () => ({ +export default (theme) => ({ flex: { flexGrow: 1 }, @@ -16,5 +16,25 @@ export default () => ({ brandLogo: { marginRight: '1em', width: '140px' + }, + langMenu: { + flexGrow: 1, + flexDirection: 'row' + }, + langExpand: { + [theme.breakpoints.down(600)]: { + display: 'none' + }, + [theme.breakpoints.up(600)]: { + display: 'inline-flex' + } + }, + langCollapse: { + [theme.breakpoints.down(600)]: { + display: 'inline-flex' + }, + [theme.breakpoints.up(600)]: { + display: 'none' + } } }) diff --git a/src/containers/Navbar/NavbarWithoutAuth.js b/src/containers/Navbar/NavbarWithoutAuth.js index d00684f..dc737c3 100644 --- a/src/containers/Navbar/NavbarWithoutAuth.js +++ b/src/containers/Navbar/NavbarWithoutAuth.js @@ -9,6 +9,8 @@ import { Avatar } from '@material-ui/core' import logo from './logo.png' import ButtonGroup from '@material-ui/core/ButtonGroup' import Button from '@material-ui/core/Button' +import Menu from '@material-ui/core/Menu' +import MenuItem from '@material-ui/core/MenuItem' const useStyles = makeStyles(styles) @@ -26,6 +28,15 @@ const changeLanguge = (lan) => { function NavbarWithoutAuth({ children, brandPath }) { const classes = useStyles() + // Language Bar Toggle + const [anchorElLang, setAnchorElLang] = React.useState(null) + const handleClick = (event) => { + setAnchorElLang(event.currentTarget) + } + const handleClose = () => { + setAnchorElLang(null) + } + return ( @@ -36,12 +47,37 @@ function NavbarWithoutAuth({ children, brandPath }) { component={Link} to={brandPath || '/'} /> -
- +
+ + + {/* Collpse Menu */} +
+ + + English + සිංහල + தமிழ் + +
{children} diff --git a/src/lang/translations.json b/src/lang/translations.json index a70bb25..cfb9c99 100644 --- a/src/lang/translations.json +++ b/src/lang/translations.json @@ -21,20 +21,20 @@ "translation": { "Worried about basic rations during the curfew?
GIVEME.lk is here to voice your needs.": "ඇඳිරි නීතිය අතරතුර මූලික සලාක ගැන කරදර වෙනවාද?
ඔබගේ අවශ්යතා සපුරාලීම සඳහා GIVEME.lk මෙහි ඇත.", "Welcome to GIVE<1>ME.lk!": "GIVE<1>ME.lk වෙත සාදරයෙන් පිළිගනිමු!", - "Log-in and start adding your requirements to GiveME. This is how you do that...": "පුරනය වී ඔබගේ අවශ්යතා GiveME වෙත එක් කිරීම ආරම්භ කරන්න. ඔබ එය කරන්නේ එලෙසයි ...", + "Log-in and start adding your requirements to GiveME. This is how you do that...": "ලොගි​න් වී ඔබගේ අවශ්යතා GiveME වෙත එක් කිරීම ආරම්භ කරන්න. ඔබ එය කරන්නේ එලෙසයි ...", "Step": "පියවර", "You log in to GIVE<1>ME.": "ඔබ GIVE<1>ME වෙත පිවිසෙන්න", - "You request items that you need": "ඔබට අවශ්ය අයිතම ඉල්ලා සිටී", - "Authorized vendors see your requirements": "බලයලත් වෙළෙන්දෝ ඔබේ අවශ්යතා දකිති", + "You request items that you need": "ඔබට අවශ්ය භාණ්​ඩ ඉල්ලා සිටින්​න", + "Authorized vendors see your requirements": "ඔබේ අවශ්‍ය​තා බලයලත් වෙළෙන්දෝ හට පෙනෙනු ඇ​ත", "Vendors will come and fulfill your needs.": "විකුණුම්කරුවන් පැමිණ ඔබේ අවශ්යතා සපුරාලනු ඇත.", "Developed By": "සංවර්ධනය කළේ", "About": "අපි ගැන", "My Requests": "මගේ ඉල්ලීම්", "My Account": "මගේ ගිණුම", "Account Settings": "ගිණුම් සැකසුම්", - "Sign Out": "වරන්න", - "Sign In": "පුරන්න", - "Request new item": "නව අයිතමයක් ඉල්ලන්න", + "Sign Out": "ඉවත් වෙන්න", + "Sign In": "ලොගින් වෙන්​න", + "Request new item": "නව භාණ්ඩය​ක් ඉල්ලන්න", "Your Needs List": "ඔබේ අවශ්යතා ලැයිස්තුව", "What do you want?": "ඔබට අවශය මොනවාද ?", "Category": "වර්ගය", @@ -44,7 +44,19 @@ "Grains": "ධාන්ය වර්ග", "Grocery Items": "සිල්ලර බඩු", "Pharmacy Items": "ඖෂධ වර්ග", - "Products": "නිෂ්පාදන" + "Products": "නිෂ්පාදන", + "Linked Accounts": "සම්බන්ධිත ගිණුම්", + "Display Name": "ඔබේ නම", + "Contact Number": "ඇමතුම් අංකය", + "NIC Number": "ජාතික හැඳුනුම්පත් අංකය", + "Delivery Address": "බෙදා හැරීමේ ලිපිනය", + "Your Email": "ඔබේ ඊමේ​ල් ලිපිනය", + "Save": "සුරකින්න", + "About GiveME.lk": "GiveME.lk ගැන", + "What is GiveME.lk?": "GiveME.lk යනු කුමක්ද?", + "GiveME.lk is a platform aimed at connecting people with wholesale and retail businesses during the SARS-CoV-2 breakout's social distancing period. Our goal is to tell the sellers where the requirement exists for their produce to make the home delivery more efficient for them and more effective for people who are expecting goods and services.": "GiveME.lk යනු SARS-CoV-2 කඩාවැටීමේ සමාජ දුරස්ථ කාල පරිච්ඡේදය තුළ තොග හා සිල්ලර ව්‍යාපාර සමඟ පුද්ගලයින් සම්බන්ධ කිරීම අරමුණු කරගත් වේදිකාවකි. අපගේ ඉලක්කය වන්නේ විකුණුම්කරුවන්ට ඔවුන්ගේ නිෂ්පාදන සඳහා අවශ්‍යතාවය පවතින්නේ කොතැනද යන්න ඔවුන්ට නිවාස සැපයුම වඩාත් කාර්යක්ෂම කිරීමට සහ භාණ්ඩ හා සේවා අපේක්ෂා කරන පුද්ගලයින් සඳහා වඩාත් ඵලදායී කිරීමටය.", + "This is an idea by the co-founders of Siyomek, Harshadewa Ariyasinghe and Keshan Sodimana. The project is run as an open-sourced project by CodeLanka. Codelanka is an initiative by GDG Sri Lanka to code things that make sense to the public, irrespective of the existence of a financial gain.": "මෙය සියොමෙක්, හර්ෂදේව ආරියසිංහ සහ කේෂන් සොදිමාන යන සම-නිර්මාතෘවරුන්ගේ අදහසකි. මෙම ව්‍යාපෘතිය CodeLanka විසින් විවෘතකේත ව්‍යාපෘතියක් ලෙස ක්‍රියාත්මක වේ. CodeLanka යනු මූල්‍යමය වාසියක් නොතකා මහජනයාට අර්ථවත් වන දේ කේත කිරීමට GDG SriLanka මුලපිරීමකි.", + "Who is involved?": "සම්බන්ධ වන්නේ කවුද?" } } } diff --git a/src/routes/Needs/components/AssignNeedDialog/AssignNeedDialog.js b/src/routes/Needs/components/AssignNeedDialog/AssignNeedDialog.js new file mode 100644 index 0000000..0c7e861 --- /dev/null +++ b/src/routes/Needs/components/AssignNeedDialog/AssignNeedDialog.js @@ -0,0 +1,64 @@ +import React from 'react' +import PropTypes from 'prop-types' +import { useForm } from 'react-hook-form' +import TextField from '@material-ui/core/TextField' +import { makeStyles } from '@material-ui/core/styles' +import Button from '@material-ui/core/Button' +import Dialog from '@material-ui/core/Dialog' +import DialogTitle from '@material-ui/core/DialogTitle' +import DialogActions from '@material-ui/core/DialogActions' +import DialogContent from '@material-ui/core/DialogContent' +import styles from './AssignNeedDialog.styles' +import { Trans } from 'react-i18next' + +const useStyles = makeStyles(styles) + +function AssignNeedDialog({ onSubmit, open, onRequestClose }) { + const classes = useStyles() + const { + register, + handleSubmit, + formState: { isSubmitting, isValid } + } = useForm({ mode: 'onChange' }) + + return ( + + + Assign for Delivery + +
+ + + + + + + +
+
+ ) +} + +AssignNeedDialog.propTypes = { + onSubmit: PropTypes.func.isRequired, + open: PropTypes.bool.isRequired, + onRequestClose: PropTypes.func.isRequired +} + +export default AssignNeedDialog diff --git a/src/routes/Needs/components/AssignNeedDialog/AssignNeedDialog.styles.js b/src/routes/Needs/components/AssignNeedDialog/AssignNeedDialog.styles.js new file mode 100644 index 0000000..d0cef2f --- /dev/null +++ b/src/routes/Needs/components/AssignNeedDialog/AssignNeedDialog.styles.js @@ -0,0 +1,19 @@ +export default (theme) => ({ + root: { + padding: theme.spacing(2), + width: '500px', + maxWidth: '100%' + }, + inputs: { + ...theme.flexColumnCenter + }, + selection: { + width: '100%' + }, + buttons: { + ...theme.flexColumnCenter + }, + emojis: { + fontSize: '35px' + } +}) diff --git a/src/routes/Needs/components/AssignNeedDialog/index.js b/src/routes/Needs/components/AssignNeedDialog/index.js new file mode 100644 index 0000000..b7912d2 --- /dev/null +++ b/src/routes/Needs/components/AssignNeedDialog/index.js @@ -0,0 +1,3 @@ +import AssignNeedDialog from './AssignNeedDialog' + +export default AssignNeedDialog diff --git a/src/routes/Needs/components/NeedsList/NeedsList.js b/src/routes/Needs/components/NeedsList/NeedsList.js index 7c3b9d6..24e87aa 100644 --- a/src/routes/Needs/components/NeedsList/NeedsList.js +++ b/src/routes/Needs/components/NeedsList/NeedsList.js @@ -1,7 +1,7 @@ -import React from 'react' +import React, { useState } from 'react' import { makeStyles } from '@material-ui/core/styles' import { - // useFirestore, + useFirestore, useFirestoreConnect, isLoaded } from 'react-redux-firebase' @@ -12,6 +12,7 @@ import LoadingSpinner from 'components/LoadingSpinner' import TabPanel from '../TabPanel' import NewNeedTable from '../NewNeedTable' import MapView from '../MapView' +import SideMenu from '../SideMenu' import styles from './NeedsList.styles' import { usePosition } from 'use-position' import AppBar from '@material-ui/core/AppBar' @@ -20,13 +21,37 @@ import Tab from '@material-ui/core/Tab' import TableChartIcon from '@material-ui/icons/TableChart' import MapIcon from '@material-ui/icons/Map' import fetcher from 'utils/fetcher' +import Grid from '@material-ui/core/Grid' +import AssignNeedDialog from '../AssignNeedDialog' +import { useNotifications } from 'modules/notification' const useStyles = makeStyles(styles) function useNeedsList() { - // const { showSuccess, showError } = useNotifications() - // const firestore = useFirestore() - const url = 'https://api-aw4mzcvpla-uc.a.run.app/api/v1/needs' + const { showSuccess, showError } = useNotifications() + const firestore = useFirestore() + const [selectedProducts, setSelectedProducts] = React.useState(new Set()) + + // New dialog + const [assignNeedsDialogOpen, changeAssignNeedsDialogState] = useState(false) + const toggleassignNeedsDialog = () => + changeAssignNeedsDialogState(!assignNeedsDialogOpen) + + const handleSelectedProductsChange = (product, state) => { + let nextSelectedProducts = null + if (state) { + nextSelectedProducts = selectedProducts.add(product) + setSelectedProducts(new Set()) + } else { + selectedProducts.delete(product) + nextSelectedProducts = selectedProducts + } + setSelectedProducts(new Set(nextSelectedProducts)) + } + + const url = `https://api-aw4mzcvpla-uc.a.run.app/api/v2/needs?products=${[ + ...selectedProducts.keys() + ].join()}` const { data, error } = useSwr(url, { fetcher }) const needs = data && !error ? data : [] @@ -52,12 +77,36 @@ function useNeedsList() { } ]) - // Get needs from redux state - // const needs = useSelector(({ firestore: { ordered } }) => ordered.needs) - - // console.log(needs,crimes) + function addDelivery(newInstance) { + if (!auth.uid) { + return showError('You must be logged in to assign a delivery') + } + return firestore + .add('delivery', { + ...newInstance, + createdBy: auth.uid, + createdAt: firestore.FieldValue.serverTimestamp() + }) + .then(() => { + toggleassignNeedsDialog() + showSuccess('Delivery added successfully') + }) + .catch((err) => { + console.error('Error:', err) // eslint-disable-line no-console + showError(err.message || 'Could not add delivery') + return Promise.reject(err) + }) + } - return { needs, location } + return { + needs, + location, + selectedProducts, + handleSelectedProductsChange, + assignNeedsDialogOpen, + toggleassignNeedsDialog, + addDelivery + } } function createData(id, name, amount, time, user, location) { @@ -79,7 +128,15 @@ function createAllData(needs) { function NeedsList() { const classes = useStyles() - const { needs, location } = useNeedsList() + const { + needs, + location, + selectedProducts, + handleSelectedProductsChange, + assignNeedsDialogOpen, + toggleassignNeedsDialog, + addDelivery + } = useNeedsList() const rows = needs ? createAllData(needs) : [] const [tab, setTab] = React.useState(0) @@ -93,26 +150,43 @@ function NeedsList() { } return ( -
- - - } label="Table" /> - } label="Map" /> - - - - - - - - -
+ + + + + + + + + } label="Table" /> + } label="Map" /> + + + + + + + + + + ) } diff --git a/src/routes/Needs/components/NeedsList/NeedsList.styles.js b/src/routes/Needs/components/NeedsList/NeedsList.styles.js index ae81da0..26d84c3 100644 --- a/src/routes/Needs/components/NeedsList/NeedsList.styles.js +++ b/src/routes/Needs/components/NeedsList/NeedsList.styles.js @@ -1,15 +1,16 @@ export default (theme) => ({ root: { - ...theme.flexColumnCenter, - paddingTop: theme.spacing(4), - flexGrow: '2', - boxSizing: 'border-box', - overflowY: 'scroll' + // ...theme.flexColumnCenter, + // paddingTop: theme.spacing(4), + // flexGrow: '2', + // boxSizing: 'border-box', + // overflowY: 'scroll' }, - tiles: { - display: 'flex', - justifyContent: 'center', - flexWrap: 'wrap', - '-webkit-flex-flow': 'row wrap' + sideMenu: { + background: '#fbfbfb', + textAlign: 'center' + }, + main: { + padding: '0 !important' } }) diff --git a/src/routes/Needs/components/NewNeedTable/NewNeedTable.js b/src/routes/Needs/components/NewNeedTable/NewNeedTable.js index 4e08669..b021060 100644 --- a/src/routes/Needs/components/NewNeedTable/NewNeedTable.js +++ b/src/routes/Needs/components/NewNeedTable/NewNeedTable.js @@ -14,14 +14,15 @@ import Toolbar from '@material-ui/core/Toolbar' import Typography from '@material-ui/core/Typography' import Paper from '@material-ui/core/Paper' import Checkbox from '@material-ui/core/Checkbox' +import Button from '@material-ui/core/Button' import IconButton from '@material-ui/core/IconButton' import Tooltip from '@material-ui/core/Tooltip' import FormControlLabel from '@material-ui/core/FormControlLabel' import Switch from '@material-ui/core/Switch' -import DeleteIcon from '@material-ui/icons/Delete' -import FilterListIcon from '@material-ui/icons/FilterList' +import PrintIcon from '@material-ui/icons/Print' import Moment from 'react-moment' import RoomIcon from '@material-ui/icons/Room' +import LocalShippingIcon from '@material-ui/icons/LocalShipping' function goToMapLocation(lat, lon) { return () => @@ -151,7 +152,7 @@ const useToolbarStyles = makeStyles((theme) => ({ const EnhancedTableToolbar = (props) => { const classes = useToolbarStyles() - const { numSelected } = props + const { numSelected, toggleassignNeedsDialog } = props return ( { )} {numSelected > 0 ? ( - - - + + + ) : ( - - - + + + )} @@ -194,7 +202,8 @@ const EnhancedTableToolbar = (props) => { } EnhancedTableToolbar.propTypes = { - numSelected: PropTypes.number.isRequired + numSelected: PropTypes.number.isRequired, + toggleassignNeedsDialog: PropTypes.func.isRequired } const useStyles = makeStyles((theme) => ({ @@ -223,7 +232,7 @@ const useStyles = makeStyles((theme) => ({ export default function EnhancedTable(props) { // eslint-disable-next-line - const { needs } = props; + const { needs, toggleassignNeedsDialog } = props; const classes = useStyles() const [order, setOrder] = React.useState('asc') const [orderBy, setOrderBy] = React.useState('name') @@ -240,7 +249,7 @@ export default function EnhancedTable(props) { const handleSelectAllClick = (event) => { if (event.target.checked) { - const newSelecteds = needs.map((n) => n.name) + const newSelecteds = needs.map((n) => n.id) setSelected(newSelecteds) return } @@ -288,7 +297,10 @@ export default function EnhancedTable(props) { return (
- + { - const isItemSelected = isSelected(row.name) + const isItemSelected = isSelected(row.id) const labelId = `enhanced-table-checkbox-${index}` return ( handleClick(event, row.name)} + onClick={(event) => handleClick(event, row.id)} role="checkbox" aria-checked={isItemSelected} tabIndex={-1} - key={row.name} + key={row.id} selected={isItemSelected}> { + return () => onChange(id, state) + } + if (!products) return null + return ( + <> + + + + + + {open ? : } + + + + {products && + products.map((product) => ( + + + + + + + ))} + + + + ) +} + +Category.propTypes = { + onClick: PropTypes.func, + open: PropTypes.bool, + classes: PropTypes.any, + onChange: PropTypes.func, + category: PropTypes.string, + products: PropTypes.array, + selectedProducts: PropTypes.object +} + +export default function SideMenu(props) { + const { selectedProducts, onSelectedProductsChange } = props + const classes = useStyles() + const [openCategories, setOpenCategories] = React.useState(new Map()) + const categories = { + meat: 'Meat,Seafood & Poultry', + dairy: 'Dairy', + grocery: 'Grocery', + grains: 'Grains', + foo: 'Fooo' + } + + useFirestoreConnect({ + collection: 'products', + where: ['category', 'in', Object.keys(categories)] + }) + + const products = useSelector(({ firestore: { ordered } }) => ordered.products) + const productGroups = groupBy(products, 'category') + + const handleClick = (category, state) => { + return () => setOpenCategories(new Map(openCategories.set(category, state))) + } + + return ( + + Filters + + } + className={classes.root}> + + + + + + + {Object.keys(categories).map((category) => ( + + ))} + + ) +} + +SideMenu.propTypes = { + onSelectedProductsChange: PropTypes.func, + selectedProducts: PropTypes.object +} diff --git a/src/routes/Needs/components/SideMenu/SideMenu.styles.js b/src/routes/Needs/components/SideMenu/SideMenu.styles.js new file mode 100644 index 0000000..04bc359 --- /dev/null +++ b/src/routes/Needs/components/SideMenu/SideMenu.styles.js @@ -0,0 +1,13 @@ +export default (theme) => ({ + root: { + width: '100%', + maxWidth: '100%', + backgroundColor: '#fbfbfb' + }, + nested: { + paddingLeft: theme.spacing(4) + }, + formInput: { + width: '100%' + } +}) diff --git a/src/routes/Needs/components/SideMenu/index.js b/src/routes/Needs/components/SideMenu/index.js new file mode 100644 index 0000000..93fcbf4 --- /dev/null +++ b/src/routes/Needs/components/SideMenu/index.js @@ -0,0 +1,3 @@ +import SideMenu from './SideMenu' + +export default SideMenu