From 371114f3576dafd856b64a57f021d01013c78cdd Mon Sep 17 00:00:00 2001 From: "Yash Pandey (YP)" Date: Sun, 9 May 2021 13:17:33 +0530 Subject: [PATCH 1/6] =?UTF-8?q?Implemented=20Provider=20Operations=20?= =?UTF-8?q?=F0=9F=8F=A5=20=20(#23)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added resource resolver * Added deleteResource * Added contacts and Auth * Added mutations and endpoints to frontend * Added graphql queries * fixed errors * Added more queries --- client/public/index.html | 4 +- .../Pages/CreateProvider/CreateProvider.js | 4 +- .../Pages/CreateProvider/CreateResource.js | 62 +++++++ .../Pages/LandingPage/LandingPage.js | 12 +- .../Components/Pages/LoginPage/Login.js | 24 +-- .../OrganisationPage/OrganisationPage.js | 8 +- .../RegistrationPage/RegistrationPage.js | 20 +-- .../ResourcesCardSection/CardView.js | 2 +- .../mutations/Contact/CreateContact.js | 18 ++ .../mutations/Contact/DeleteContact.js | 7 + .../mutations/Provider/CreateProvider.js | 18 ++ .../mutations/Provider/UpdateProvider.js | 17 ++ .../mutations/Resource/CreateResource.js | 19 ++ .../mutations/Resource/DeleteResource.js | 7 + .../mutations/Resource/UpdateResource.js | 17 ++ .../graphql/mutations/User/AddUser.js | 12 ++ .../graphql/mutations/User/Login.js | 16 ++ .../graphql/mutations/User/Logout.js | 7 + .../graphql/queries/Provider/FindProvider.js | 17 ++ .../queries/Provider/GetAllProviders.js | 17 ++ .../graphql/queries/Provider/GetContacts.js | 11 ++ .../graphql/queries/Provider/GetResources.js | 12 ++ .../graphql/queries/Provider/MyProvider.js | 18 ++ .../graphql/queries/User/GetUser.js | 11 ++ .../graphql/queries/User/MyProvider.js | 18 ++ server/{.env.dev => .env} | 0 server/src/entities/Contact.ts | 7 +- server/src/entities/Resource.ts | 8 +- server/src/entities/User.ts | 2 +- server/src/index.ts | 4 +- server/src/middleware/Auth.ts | 0 server/src/middleware/isAuth.ts | 10 ++ server/src/middleware/isRegistered.ts | 10 ++ server/src/resolvers/Contact.ts | 168 ++++++++++++++++++ server/src/resolvers/Provider.ts | 57 +++--- server/src/resolvers/Resource.ts | 168 ++++++++++++++++++ server/src/resolvers/User.ts | 63 +++++-- 37 files changed, 769 insertions(+), 106 deletions(-) create mode 100644 client/src/CoviSource/Components/Pages/CreateProvider/CreateResource.js create mode 100644 client/src/CoviSource/graphql/mutations/Contact/CreateContact.js create mode 100644 client/src/CoviSource/graphql/mutations/Contact/DeleteContact.js create mode 100644 client/src/CoviSource/graphql/mutations/Provider/CreateProvider.js create mode 100644 client/src/CoviSource/graphql/mutations/Provider/UpdateProvider.js create mode 100644 client/src/CoviSource/graphql/mutations/Resource/CreateResource.js create mode 100644 client/src/CoviSource/graphql/mutations/Resource/DeleteResource.js create mode 100644 client/src/CoviSource/graphql/mutations/Resource/UpdateResource.js create mode 100644 client/src/CoviSource/graphql/mutations/User/AddUser.js create mode 100644 client/src/CoviSource/graphql/mutations/User/Login.js create mode 100644 client/src/CoviSource/graphql/mutations/User/Logout.js create mode 100644 client/src/CoviSource/graphql/queries/Provider/FindProvider.js create mode 100644 client/src/CoviSource/graphql/queries/Provider/GetAllProviders.js create mode 100644 client/src/CoviSource/graphql/queries/Provider/GetContacts.js create mode 100644 client/src/CoviSource/graphql/queries/Provider/GetResources.js create mode 100644 client/src/CoviSource/graphql/queries/Provider/MyProvider.js create mode 100644 client/src/CoviSource/graphql/queries/User/GetUser.js create mode 100644 client/src/CoviSource/graphql/queries/User/MyProvider.js rename server/{.env.dev => .env} (100%) delete mode 100644 server/src/middleware/Auth.ts create mode 100644 server/src/middleware/isAuth.ts create mode 100644 server/src/middleware/isRegistered.ts create mode 100644 server/src/resolvers/Contact.ts create mode 100644 server/src/resolvers/Resource.ts diff --git a/client/public/index.html b/client/public/index.html index 0dceb5f..0c51ff3 100644 --- a/client/public/index.html +++ b/client/public/index.html @@ -14,14 +14,14 @@ - + - + diff --git a/client/src/CoviSource/Components/Pages/CreateProvider/CreateProvider.js b/client/src/CoviSource/Components/Pages/CreateProvider/CreateProvider.js index 7b866d7..496121d 100644 --- a/client/src/CoviSource/Components/Pages/CreateProvider/CreateProvider.js +++ b/client/src/CoviSource/Components/Pages/CreateProvider/CreateProvider.js @@ -36,7 +36,7 @@ const formReducer = (state, event) => { export default function CreateProvider(props) { const [formData, setFormData] = useReducer(formReducer, {}); - const [resourceData, setresourceData] = useReducer(formReducer, {}); + const [resourceData, setresourceData] = useState([]); const [cardAnimaton, setCardAnimation] = useState("cardHidden"); const [numberContact, setNumberContact] = useState(0); @@ -171,8 +171,6 @@ export default function CreateProvider(props) { > + Add Contacts - {/* { - } */} { + setresourceData({ + name: event.target.name, + value: event.target.value, + }); + }; + return ( +
+ + + + ), + autoComplete: "off", + name: "name", + onChange: handleChange, + }} + /> + + + + ), + autoComplete: "off", + name: "quantity", + onChange: handleChange, + }} + /> +
+ ); +} + +CreateContact.propTypes = { + classes: propTypes.object, + formData: propTypes.object, + setresourceData: propTypes.func, +}; diff --git a/client/src/CoviSource/Components/Pages/LandingPage/LandingPage.js b/client/src/CoviSource/Components/Pages/LandingPage/LandingPage.js index 29b9857..e70ad6a 100644 --- a/client/src/CoviSource/Components/Pages/LandingPage/LandingPage.js +++ b/client/src/CoviSource/Components/Pages/LandingPage/LandingPage.js @@ -54,7 +54,7 @@ export default function LandingPage(props) { ], address: "Provider Address", contactPersonName: "Contact Person's Name", - contactNumber: "9821095754", + phoneNumber: "9821095754", serviceName: "Service Provided", }, { @@ -80,7 +80,7 @@ export default function LandingPage(props) { ], address: "Free oxygen seva, near gurudwara, delhi", contactPersonName: "Jaspal Singh", - contactNumber: "9821095754", + phoneNumber: "9821095754", serviceName: "Oxygen refilling", }, { @@ -106,7 +106,7 @@ export default function LandingPage(props) { ], address: "Apex Hospital, Kalyan West, Mumbai", contactPersonName: "Dr. D P Goel", - contactNumber: "9789965234", + phoneNumber: "9789965234", serviceName: "Hospital", }, ]); @@ -139,7 +139,7 @@ export default function LandingPage(props) { ], address: "Provider Address", contactPersonName: "Contact Person's Name", - contactNumber: "9821095754", + phoneNumber: "9821095754", serviceName: "Service Provided", }, { @@ -165,7 +165,7 @@ export default function LandingPage(props) { ], address: "Free oxygen seva, near gurudwara, delhi", contactPersonName: "Jaspal Singh", - contactNumber: "9821095754", + phoneNumber: "9821095754", serviceName: "Oxygen refilling", }, { @@ -191,7 +191,7 @@ export default function LandingPage(props) { ], address: "Apex Hospital, Kalyan West, Mumbai", contactPersonName: "Dr. D P Goel", - contactNumber: "9789965234", + phoneNumber: "9789965234", serviceName: "Hospital", }, ]); diff --git a/client/src/CoviSource/Components/Pages/LoginPage/Login.js b/client/src/CoviSource/Components/Pages/LoginPage/Login.js index d8f4df6..a9ff14c 100644 --- a/client/src/CoviSource/Components/Pages/LoginPage/Login.js +++ b/client/src/CoviSource/Components/Pages/LoginPage/Login.js @@ -22,29 +22,11 @@ import "./Login.scss"; import image from "assets/img/bg7.jpg"; -import { gql, useMutation } from "@apollo/client"; +import { useMutation } from "@apollo/client"; +import { LOGIN } from "CoviSource/graphql/mutations/User/Login"; const useStyles = makeStyles(styles); -const LOGIN = gql` - mutation Login($input: UsernamePasswordInput!) { - login(input: $input) { - errors { - field - message - } - user { - _id - createdAt - updatedAt - email - name - contactNumber - } - } - } -`; - const formReducer = (state, event) => { return { ...state, @@ -85,7 +67,7 @@ export default function Login(props) { alert(`Your details: \n ID: ${data.login.user._id}\n Name: ${data.login.user.name}\n - Contact Number: ${data.login.user.contactNumber}\n + Contact Number: ${data.login.user.phoneNumber}\n `); console.log(data.login.user); } diff --git a/client/src/CoviSource/Components/Pages/OrganisationPage/OrganisationPage.js b/client/src/CoviSource/Components/Pages/OrganisationPage/OrganisationPage.js index 61aa939..3b4a9bb 100644 --- a/client/src/CoviSource/Components/Pages/OrganisationPage/OrganisationPage.js +++ b/client/src/CoviSource/Components/Pages/OrganisationPage/OrganisationPage.js @@ -46,15 +46,15 @@ export default function OrganisationPage() { contacts: [ { contactPersonName: "Dr. Gaurav Bhatt", - contactNumber: "9821095754", + phoneNumber: "9821095754", }, { contactPersonName: "Dr. Ashok Bhoir", - contactNumber: "9821095754", + phoneNumber: "9821095754", }, { contactPersonName: "Dr. Rupender Singh Sodhi", - contactNumber: "9821095754", + phoneNumber: "9821095754", }, ], serviceName: "Service Provided", @@ -148,7 +148,7 @@ export default function OrganisationPage() {
- {item.contactNumber} + {item.phoneNumber}
diff --git a/client/src/CoviSource/Components/Pages/RegistrationPage/RegistrationPage.js b/client/src/CoviSource/Components/Pages/RegistrationPage/RegistrationPage.js index 88187eb..44f8459 100644 --- a/client/src/CoviSource/Components/Pages/RegistrationPage/RegistrationPage.js +++ b/client/src/CoviSource/Components/Pages/RegistrationPage/RegistrationPage.js @@ -25,21 +25,11 @@ import "./RegistrationPage.scss"; import image from "assets/img/bg2.jpg"; import Phone from "@material-ui/icons/Phone"; -import { gql, useMutation } from "@apollo/client"; +import { useMutation } from "@apollo/client"; +import { ADD_USER } from "CoviSource/graphql/mutations/User/AddUser"; const useStyles = makeStyles(styles); -const ADD_USER = gql` - mutation AddUser($input: UserRegisterInput!) { - register(input: $input) { - errors { - field - message - } - } - } -`; - const formReducer = (state, event) => { return { ...state, @@ -77,7 +67,7 @@ export default function RegistrationPage(props) { input: { name: formData.name, email: formData.email, - contactNumber: formData.contactNumber, + phoneNumber: formData.phoneNumber, password: formData.password, }, }, @@ -178,7 +168,7 @@ export default function RegistrationPage(props) { /> ), autoComplete: "off", - name: "contactNumber", + name: "phoneNumber", onChange: handleChange, }} /> diff --git a/client/src/CoviSource/Components/UtilityComponents/ResourcesCardSection/CardView.js b/client/src/CoviSource/Components/UtilityComponents/ResourcesCardSection/CardView.js index 88ecf7f..b6a26df 100644 --- a/client/src/CoviSource/Components/UtilityComponents/ResourcesCardSection/CardView.js +++ b/client/src/CoviSource/Components/UtilityComponents/ResourcesCardSection/CardView.js @@ -188,7 +188,7 @@ export default function CardView(props) {

- {details.contactNumber} + {details.phoneNumber}

diff --git a/client/src/CoviSource/graphql/mutations/Contact/CreateContact.js b/client/src/CoviSource/graphql/mutations/Contact/CreateContact.js new file mode 100644 index 0000000..8fdbf7f --- /dev/null +++ b/client/src/CoviSource/graphql/mutations/Contact/CreateContact.js @@ -0,0 +1,18 @@ +import { gql } from "@apollo/client"; + +export const CREATE_CONTACT = gql` + mutation CreateContact($input: ContactInput!) { + createContact(input: $input) { + errors { + field + message + } + contact { + id + providerID + name + phoneNumber + } + } + } +`; diff --git a/client/src/CoviSource/graphql/mutations/Contact/DeleteContact.js b/client/src/CoviSource/graphql/mutations/Contact/DeleteContact.js new file mode 100644 index 0000000..677345a --- /dev/null +++ b/client/src/CoviSource/graphql/mutations/Contact/DeleteContact.js @@ -0,0 +1,7 @@ +import { gql } from "@apollo/client"; + +export const DELETE_CONTACT = gql` + mutation DeleteContact($id: Float!) { + deleteContact(id: $id) + } +`; diff --git a/client/src/CoviSource/graphql/mutations/Provider/CreateProvider.js b/client/src/CoviSource/graphql/mutations/Provider/CreateProvider.js new file mode 100644 index 0000000..c2830bb --- /dev/null +++ b/client/src/CoviSource/graphql/mutations/Provider/CreateProvider.js @@ -0,0 +1,18 @@ +import { gql } from "@apollo/client"; + +export const CREATE_PROVIDER = gql` + mutation CreateProvider($input: NewProviderInput!) { + createProvider(input: $input) { + providerName + updatedAt + _id + ownerID + slug + location { + latitude + longitude + } + address + } + } +`; diff --git a/client/src/CoviSource/graphql/mutations/Provider/UpdateProvider.js b/client/src/CoviSource/graphql/mutations/Provider/UpdateProvider.js new file mode 100644 index 0000000..89a2736 --- /dev/null +++ b/client/src/CoviSource/graphql/mutations/Provider/UpdateProvider.js @@ -0,0 +1,17 @@ +import { gql } from "@apollo/client"; + +export const UPDATE_PROVIDER = gql` + mutation UpdateProvider($input: NewProviderInput!) { + updateProvider(input: $input) { + _id + providerName + updatedAt + slug + location { + latitude + longitude + } + address + } + } +`; diff --git a/client/src/CoviSource/graphql/mutations/Resource/CreateResource.js b/client/src/CoviSource/graphql/mutations/Resource/CreateResource.js new file mode 100644 index 0000000..ab47c8e --- /dev/null +++ b/client/src/CoviSource/graphql/mutations/Resource/CreateResource.js @@ -0,0 +1,19 @@ +import { gql } from "@apollo/client"; + +export const CREATE_RESOURCE = gql` + mutation CreateResource($input: ResourceInput!) { + createResource(input: $input) { + errors { + field + message + } + resource { + providerID + name + quantity + createdAt + updatedAt + } + } + } +`; diff --git a/client/src/CoviSource/graphql/mutations/Resource/DeleteResource.js b/client/src/CoviSource/graphql/mutations/Resource/DeleteResource.js new file mode 100644 index 0000000..cbcc23a --- /dev/null +++ b/client/src/CoviSource/graphql/mutations/Resource/DeleteResource.js @@ -0,0 +1,7 @@ +import { gql } from "@apollo/client"; + +export const DELETE_RESOURCE = gql` + mutation DeleteResource($id: Float!) { + deleteResource(id: $id) + } +`; diff --git a/client/src/CoviSource/graphql/mutations/Resource/UpdateResource.js b/client/src/CoviSource/graphql/mutations/Resource/UpdateResource.js new file mode 100644 index 0000000..1b2a940 --- /dev/null +++ b/client/src/CoviSource/graphql/mutations/Resource/UpdateResource.js @@ -0,0 +1,17 @@ +import { gql } from "@apollo/client"; + +export const UPDATE_RESOURCE = gql` + mutation UpdateResource($input: ResourceUpdateInput!) { + updateResource(input: $input) { + errors { + field + message + } + resource { + id + name + quantity + } + } + } +`; diff --git a/client/src/CoviSource/graphql/mutations/User/AddUser.js b/client/src/CoviSource/graphql/mutations/User/AddUser.js new file mode 100644 index 0000000..be753e8 --- /dev/null +++ b/client/src/CoviSource/graphql/mutations/User/AddUser.js @@ -0,0 +1,12 @@ +import { gql } from "@apollo/client"; + +export const ADD_USER = gql` + mutation AddUser($input: UserRegisterInput!) { + register(input: $input) { + errors { + field + message + } + } + } +`; diff --git a/client/src/CoviSource/graphql/mutations/User/Login.js b/client/src/CoviSource/graphql/mutations/User/Login.js new file mode 100644 index 0000000..83f050b --- /dev/null +++ b/client/src/CoviSource/graphql/mutations/User/Login.js @@ -0,0 +1,16 @@ +import { gql } from "@apollo/client"; + +export const LOGIN = gql` + mutation Login($input: UsernamePasswordInput!) { + login(input: $input) { + errors { + field + message + } + user { + _id + name + } + } + } +`; diff --git a/client/src/CoviSource/graphql/mutations/User/Logout.js b/client/src/CoviSource/graphql/mutations/User/Logout.js new file mode 100644 index 0000000..0bb0978 --- /dev/null +++ b/client/src/CoviSource/graphql/mutations/User/Logout.js @@ -0,0 +1,7 @@ +import { gql } from "@apollo/client"; + +export const LOGOUT = gql` + mutation Logout { + logout + } +`; diff --git a/client/src/CoviSource/graphql/queries/Provider/FindProvider.js b/client/src/CoviSource/graphql/queries/Provider/FindProvider.js new file mode 100644 index 0000000..28b3303 --- /dev/null +++ b/client/src/CoviSource/graphql/queries/Provider/FindProvider.js @@ -0,0 +1,17 @@ +import { gql } from "@apollo/client"; + +export const FIND_PROVIDER = gql` + query FindProvider($slug: String!) { + findProviderbySlug(slug: $slug) { + id + providerName + address + location { + latitude + longitude + } + createdAt + updatedAt + } + } +`; diff --git a/client/src/CoviSource/graphql/queries/Provider/GetAllProviders.js b/client/src/CoviSource/graphql/queries/Provider/GetAllProviders.js new file mode 100644 index 0000000..a76db49 --- /dev/null +++ b/client/src/CoviSource/graphql/queries/Provider/GetAllProviders.js @@ -0,0 +1,17 @@ +import { gql } from "@apollo/client"; + +export const GET_ALL_PROVIDERS = gql` + query GetAllProviders { + allProviders { + id + providerName + address + location { + latitude + longitude + } + slug + updatedAt + } + } +`; diff --git a/client/src/CoviSource/graphql/queries/Provider/GetContacts.js b/client/src/CoviSource/graphql/queries/Provider/GetContacts.js new file mode 100644 index 0000000..20ce160 --- /dev/null +++ b/client/src/CoviSource/graphql/queries/Provider/GetContacts.js @@ -0,0 +1,11 @@ +import { gql } from "@apollo/client"; + +export const GET_CONTACTS = gql` + query GetContacts($id: Float!) { + getContact(providerID: $id) { + id + name + phoneNumber + } + } +`; diff --git a/client/src/CoviSource/graphql/queries/Provider/GetResources.js b/client/src/CoviSource/graphql/queries/Provider/GetResources.js new file mode 100644 index 0000000..e7cecfc --- /dev/null +++ b/client/src/CoviSource/graphql/queries/Provider/GetResources.js @@ -0,0 +1,12 @@ +import { gql } from "@apollo/client"; + +export const GET_RESOURCES = gql` + query GetResources($id: Float!) { + getResource(providerID: $id) { + id + name + quantity + updatedAt + } + } +`; diff --git a/client/src/CoviSource/graphql/queries/Provider/MyProvider.js b/client/src/CoviSource/graphql/queries/Provider/MyProvider.js new file mode 100644 index 0000000..bce178a --- /dev/null +++ b/client/src/CoviSource/graphql/queries/Provider/MyProvider.js @@ -0,0 +1,18 @@ +import { gql } from "@apollo/client"; + +export const MY_PROVIDER = gql` + query MyProvider { + myProvider { + _id + providerName + address + location { + latitude + longitude + } + slug + updatedAt + createdAt + } + } +`; diff --git a/client/src/CoviSource/graphql/queries/User/GetUser.js b/client/src/CoviSource/graphql/queries/User/GetUser.js new file mode 100644 index 0000000..4eed52c --- /dev/null +++ b/client/src/CoviSource/graphql/queries/User/GetUser.js @@ -0,0 +1,11 @@ +import { gql } from "@apollo/client"; + +export const GET_USER = gql` + query GetUser { + me { + name + _id + email + } + } +`; diff --git a/client/src/CoviSource/graphql/queries/User/MyProvider.js b/client/src/CoviSource/graphql/queries/User/MyProvider.js new file mode 100644 index 0000000..5e036d4 --- /dev/null +++ b/client/src/CoviSource/graphql/queries/User/MyProvider.js @@ -0,0 +1,18 @@ +import { gql } from "@apollo/client"; + +export const MY_PROVIDER = gql` + query MyProvider { + myProvider { + providerName + address + location { + latitude + longitude + } + slug + _id + updatedAt + createdAt + } + } +`; diff --git a/server/.env.dev b/server/.env similarity index 100% rename from server/.env.dev rename to server/.env diff --git a/server/src/entities/Contact.ts b/server/src/entities/Contact.ts index d61541b..9a7ac70 100644 --- a/server/src/entities/Contact.ts +++ b/server/src/entities/Contact.ts @@ -1,10 +1,13 @@ import { Field, Int, ObjectType } from "type-graphql"; -import { Column, Entity, JoinColumn, ManyToOne, PrimaryColumn } from "typeorm"; +import { BaseEntity, Column, Entity, JoinColumn, ManyToOne, PrimaryColumn, PrimaryGeneratedColumn } from "typeorm"; import { Provider } from "./Provider"; @ObjectType() @Entity() -export class Contact { +export class Contact extends BaseEntity { + @Field(() => Int) + @PrimaryGeneratedColumn() + id: number; @Field(() => Int) @PrimaryColumn() diff --git a/server/src/entities/Resource.ts b/server/src/entities/Resource.ts index cad34b9..b960229 100644 --- a/server/src/entities/Resource.ts +++ b/server/src/entities/Resource.ts @@ -1,10 +1,10 @@ import { Field, Int, ObjectType } from "type-graphql"; -import { Column, CreateDateColumn, Entity, JoinColumn, ManyToOne, PrimaryColumn, UpdateDateColumn } from "typeorm"; +import { BaseEntity, Column, CreateDateColumn, Entity, JoinColumn, ManyToOne, PrimaryColumn, PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm"; import { Provider } from "./Provider"; @ObjectType() @Entity() -export class Resource { +export class Resource extends BaseEntity { @Field(() => String) @Column() name: string; @@ -21,6 +21,10 @@ export class Resource { @JoinColumn() provider: Provider; + @Field(() => Int) + @PrimaryGeneratedColumn() + id: number; + @Field(() => String) @CreateDateColumn() createdAt: Date; diff --git a/server/src/entities/User.ts b/server/src/entities/User.ts index e1b36e3..c474e5b 100644 --- a/server/src/entities/User.ts +++ b/server/src/entities/User.ts @@ -15,7 +15,7 @@ export class User extends BaseEntity { @Field(() => String) @Column({ nullable: true, unique: true }) - contactNumber!: string; + phoneNumber!: string; @Field(() => String) @Column({}) diff --git a/server/src/index.ts b/server/src/index.ts index 8d16592..b2a7093 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -13,6 +13,8 @@ import { MyContext } from './types'; import { createConnection } from 'typeorm'; import config from './typeorm.config'; import cors from 'cors'; +import { ResourceResolver } from './resolvers/Resource'; +import { ContactResolver } from './resolvers/Contact'; const main = async () => { await createConnection(config); @@ -53,7 +55,7 @@ const main = async () => { const apolloServer = new ApolloServer({ schema: await buildSchema({ - resolvers: [ProviderResolver, UserResolver], + resolvers: [ProviderResolver, UserResolver, ResourceResolver, ContactResolver], validate: false }), context: ({ req, res }) : MyContext => ({ req, res, redis }) diff --git a/server/src/middleware/Auth.ts b/server/src/middleware/Auth.ts deleted file mode 100644 index e69de29..0000000 diff --git a/server/src/middleware/isAuth.ts b/server/src/middleware/isAuth.ts new file mode 100644 index 0000000..1541360 --- /dev/null +++ b/server/src/middleware/isAuth.ts @@ -0,0 +1,10 @@ +import { MyContext } from "src/types"; +import { MiddlewareFn } from "type-graphql"; + + +export const isAuth: MiddlewareFn = ({ context }, next) => { + if (!context.req.session.userID) { + throw new Error("Not authenticated"); + } + return next(); +} \ No newline at end of file diff --git a/server/src/middleware/isRegistered.ts b/server/src/middleware/isRegistered.ts new file mode 100644 index 0000000..2f9aaf2 --- /dev/null +++ b/server/src/middleware/isRegistered.ts @@ -0,0 +1,10 @@ +import { MyContext } from "src/types"; +import { MiddlewareFn } from "type-graphql"; + + +export const isRegistered: MiddlewareFn = ({ context }, next) => { + if (!context.req.session.userID) { + throw new Error("Not registered as a provider"); + } + return next(); +} \ No newline at end of file diff --git a/server/src/resolvers/Contact.ts b/server/src/resolvers/Contact.ts new file mode 100644 index 0000000..910db4a --- /dev/null +++ b/server/src/resolvers/Contact.ts @@ -0,0 +1,168 @@ +import { Contact } from '../entities/Contact'; +import { MyContext } from '../types'; +import { Arg, Ctx, Field, InputType, Mutation, ObjectType, Query, Resolver, UseMiddleware } from 'type-graphql'; +import { isAuth } from '../middleware/isAuth'; +import { isRegistered } from '../middleware/isRegistered'; + +@InputType() +class ContactInput { + @Field() + name: string; + + @Field() + phoneNumber: string; +} + +@InputType() +class ContactUpdateInput { + @Field() + id: number; + + @Field() + name: string; + + @Field() + phoneNumber: string; +} + +@ObjectType() +class ContactErrorFormat { + @Field() + field: string; + + @Field() + message: string; +} + + +@ObjectType() +class ContactResponse { + @Field(() => [ContactErrorFormat], { nullable: true }) + errors?: ContactErrorFormat[]; + + @Field(() => Contact, { nullable: true }) + contact?: Contact; +} + +@Resolver() +export class ContactResolver { + + @Query(() => [Contact]) + allContacts(): Promise { + return Contact.find(); + } + + @Query(() => [Contact]) + async getContact( + @Arg('providerID') providerID: number, + ): Promise{ + const contacts = await Contact.find({ where: { providerID } }); + return contacts; + } + + @Mutation(() => ContactResponse) + @UseMiddleware(isAuth, isRegistered) + async createContact( + @Arg('input') input: ContactInput, + @Ctx() { req }: MyContext + ): Promise { + if (input.name.length <= 3) { + return { + errors: [{ + field: "name", + message: "Invalid Name" + }] + } + } + if (input.phoneNumber.length < 10) { + return { + errors: [{ + field: "phoneNumber", + message: "phoneNumber should be at least 10 digits long" + }] + } + } + const result = await Contact.findOne({ + where: { + providerID: req.session.providerID, + name: input.name, + } + }); + if (result) { + return { + errors: [{ + field: "contact", + message: "This contact already exists" + }] + } + } + const contact = await Contact.create({ + ...input, + providerID: req.session.providerID, + }).save(); + + return { contact }; + } + + @Mutation(() => ContactResponse) + @UseMiddleware(isAuth, isRegistered) + async updateContact( + @Arg('input') input: ContactUpdateInput, + ): Promise { + if (input.name.length <= 3) { + return { + errors: [{ + field: "name", + message: "Invalid Name" + }] + } + } + if (input.phoneNumber.length < 10) { + return { + errors: [{ + field: "phoneNumber", + message: "phoneNumber should be at least 10 digits long" + }] + } + } + var contact = await Contact.findOne(input.id); + if (!contact) { + return { + errors: [{ + field: "name", + message: "Contact not found for this provider" + }] + } + } else { + await Contact.update(input.id, { + name: input.name, + phoneNumber: input.phoneNumber + }); + contact = await Contact.findOne(input.id); + return { contact }; + } + } + + @Mutation(() => Boolean) + @UseMiddleware(isAuth, isRegistered) + async deleteContact( + @Arg('id') id: number, + @Ctx() { req }: MyContext + ): Promise { + return new Promise(async (resolve) => { + const contact = await Contact.findOne({ id: id, providerID: req.session.providerID }); + if (!contact) { + console.log("Contact not found!"); + resolve(false); + } else { + try { + await Contact.delete({ id: id, providerID: req.session.providerID }); + } catch (err) { + console.log(err); + resolve(false); + } + resolve(true); + } + }) + } +} diff --git a/server/src/resolvers/Provider.ts b/server/src/resolvers/Provider.ts index 39c5e3d..b780ffb 100644 --- a/server/src/resolvers/Provider.ts +++ b/server/src/resolvers/Provider.ts @@ -1,7 +1,9 @@ import { Provider } from '../entities/Provider'; -import { Arg, Ctx, Field, InputType, Int, Mutation, Query, Resolver } from 'type-graphql'; +import { Arg, Ctx, Field, InputType, Int, Mutation, Query, Resolver, UseMiddleware } from 'type-graphql'; import slugify from 'slugify'; import { MyContext } from 'src/types'; +import { isAuth } from '../middleware/isAuth'; +import { isRegistered } from '../middleware/isRegistered'; @InputType() class LocationTemplate { @@ -12,15 +14,6 @@ class LocationTemplate { longitude: number; } -@InputType() -class ContactTemplate { - @Field() - name: string; - - @Field() - number: string; -} - @InputType() class NewProviderInput { @Field() @@ -31,9 +24,6 @@ class NewProviderInput { @Field(() => LocationTemplate) location: LocationTemplate; - - @Field(() => [ContactTemplate]) - contacts: [ContactTemplate]; } @Resolver() @@ -44,34 +34,34 @@ export class ProviderResolver { } @Query(() => Provider, { nullable: true }) - findProvider( - @Arg('id', () => Int) id: number, + @UseMiddleware(isAuth, isRegistered) + myProvider( + @Ctx() { req }: MyContext ): Promise { - return Provider.findOne(id); + return Provider.findOne(req.session.providerID); } @Query(() => Provider, { nullable: true }) findProviderbySlug( @Arg('slug', () => String) slug: string, ): Promise { - return Provider.findOne({slug: slug}); + return Provider.findOne({ where: { slug: slug } }); } @Mutation(() => Provider) + @UseMiddleware(isAuth) async createProvider( @Arg('input') input: NewProviderInput, @Ctx() { req }: MyContext - // @UseMiddleware(onAuth) ): Promise { - if (typeof req.session.providerID !== 'undefined') { + if (req.session.providerID) { throw Error("Provider already created!"); } var provider; try { provider = await Provider.create({ ...input, - location: input.location, - slug: slugify(input.providerName), + slug: slugify(input.providerName, { lower: true }), ownerID: req.session.userID, resources: [], }).save(); @@ -82,22 +72,31 @@ export class ProviderResolver { return provider; } - @Mutation(() => Provider, {nullable: true}) + @Mutation(() => Provider, { nullable: true }) + @UseMiddleware(isAuth, isRegistered) async updateProvider( - @Arg('id', () => Int) id: number, - @Arg('providerName', () => String) providerName: string, + @Arg('input') input: NewProviderInput, + @Ctx() { req }: MyContext ): Promise { - const provider = await Provider.findOne(id); + const provider = await Provider.findOne(req.session.providerID); if (!provider) { return null; } - if (typeof providerName !== 'undefined') { - await Provider.update(id, { providerName: providerName, slug: slugify(providerName, { lower: true }) }); + if (provider) { + await Provider.update(req.session.providerID as number, { + ...input, + slug: slugify(input.providerName, { lower: true }), + }); } - return provider; + const updatedProvider = await Provider.findOne(req.session.providerID); + if (updatedProvider) { + return updatedProvider; + } + return null; } - @Mutation(() => Boolean, {nullable: true}) + @Mutation(() => Boolean, { nullable: true }) + @UseMiddleware(isAuth, isRegistered) async deleteProvider( @Arg('id', () => Int) id: number, ): Promise { diff --git a/server/src/resolvers/Resource.ts b/server/src/resolvers/Resource.ts new file mode 100644 index 0000000..2aff551 --- /dev/null +++ b/server/src/resolvers/Resource.ts @@ -0,0 +1,168 @@ +import { Resource } from '../entities/Resource'; +import { MyContext } from '../types'; +import { Arg, Ctx, Field, InputType, Mutation, ObjectType, Query, Resolver, UseMiddleware } from 'type-graphql'; +import { isAuth } from '../middleware/isAuth'; +import { isRegistered } from '../middleware/isRegistered'; + +@InputType() +class ResourceInput { + @Field() + name: string; + + @Field() + quantity: number; +} + +@InputType() +class ResourceUpdateInput { + @Field() + id: number; + + @Field() + name: string; + + @Field() + quantity: number; +} + +@ObjectType() +class ErrorFormat { + @Field() + field: string; + + @Field() + message: string; +} + + +@ObjectType() +class ResourceResponse { + @Field(() => [ErrorFormat], { nullable: true }) + errors?: ErrorFormat[]; + + @Field(() => Resource, { nullable: true }) + resource?: Resource; +} + +@Resolver() +export class ResourceResolver { + + @Query(() => [Resource]) + allResources(): Promise { + return Resource.find(); + } + + @Query(() => [Resource]) + async getResource( + @Arg('providerID') providerID: number, + ): Promise { + const resources = await Resource.find({ where: { providerID } }); + return resources; + } + + @Mutation(() => ResourceResponse) + @UseMiddleware(isAuth) + async createResource( + @Arg('input') input: ResourceInput, + @Ctx() { req }: MyContext + ): Promise { + if (input.name.length <= 3) { + return { + errors: [{ + field: "name", + message: "Invalid Name" + }] + } + } + if (input.quantity < 0) { + return { + errors: [{ + field: "quantity", + message: "quantity should be greater than 0" + }] + } + } + const result = await Resource.findOne({ + where: { + providerID: req.session.providerID, + name: input.name, + } + }); + if (result) { + return { + errors: [{ + field: "resource", + message: "This resource already exists" + }] + } + } + const resource = await Resource.create({ + ...input, + providerID: req.session.providerID, + }).save(); + + return { resource }; + } + + @Mutation(() => ResourceResponse) + @UseMiddleware(isAuth, isRegistered) + async updateResource( + @Arg('input') input: ResourceUpdateInput, + ): Promise { + if (input.name.length <= 3) { + return { + errors: [{ + field: "name", + message: "Invalid Name" + }] + } + } + if (input.quantity < 0) { + return { + errors: [{ + field: "quantity", + message: "quantity should be greater than 0" + }] + } + } + const resource = await Resource.findOne(input.id); + if (!resource) { + return { + errors: [{ + field: "name", + message: "Resource not found for this provider" + }] + } + } else { + await Resource.update(input.id, { + name: input.name, + quantity: input.quantity + }); + + return { resource }; + } + } + + @Mutation(() => Boolean) + @UseMiddleware(isAuth, isRegistered) + async deleteResource( + @Arg('id') id: number, + @Ctx() { req }: MyContext + ): Promise { + return new Promise(async (resolve) => { + const resource = await Resource.findOne({ id: id, providerID: req.session.providerID }); + if (!resource) { + console.log("Resource not found!"); + resolve(false); + } else { + try { + await Resource.delete({ id: id, providerID: req.session.providerID }); + } catch (err) { + console.log(err); + resolve(false); + } + resolve(true); + } + }) + } +} diff --git a/server/src/resolvers/User.ts b/server/src/resolvers/User.ts index f1ae855..dad8d63 100644 --- a/server/src/resolvers/User.ts +++ b/server/src/resolvers/User.ts @@ -1,9 +1,11 @@ import { User } from '../entities/User'; import { MyContext } from '../types'; -import { Arg, Ctx, Field, InputType, Mutation, ObjectType, Query, Resolver } from 'type-graphql'; +import { Arg, Ctx, Field, InputType, Mutation, ObjectType, Query, Resolver, UseMiddleware } from 'type-graphql'; import argon2 from 'argon2'; import { COOKIE_NAME } from '../constants'; import { getConnection } from 'typeorm'; +import { isAuth } from '../middleware/isAuth'; +import { Provider } from '../entities/Provider'; @InputType() class UsernamePasswordInput { @@ -23,7 +25,7 @@ class UserRegisterInput { password: string @Field() - contactNumber: string + phoneNumber: string @Field() name: string @@ -52,6 +54,7 @@ class UserResponse { export class UserResolver { @Query(() => User, { nullable: true }) + @UseMiddleware(isAuth) async me(@Ctx() { req } : MyContext): Promise { // Not logged in if (!req.session.userID) { @@ -70,6 +73,14 @@ export class UserResolver { @Arg('input') input: UserRegisterInput, @Ctx() { req }: MyContext ): Promise { + if (req.session.userID) { + return { + errors: [{ + field: "user", + message: "Already logged in" + }] + } + } if (input.email.length <= 4 || !input.email.includes('@')) { return { errors: [{ @@ -86,10 +97,10 @@ export class UserResolver { }] } } - if (input.contactNumber.length < 10) { + if (input.phoneNumber.length < 10 || input.phoneNumber.length > 13) { return { errors: [{ - field: "contactNumber", + field: "phoneNumber", message: "Contact number is invalid. Enter 10 Digit number" }] } @@ -106,18 +117,19 @@ export class UserResolver { let user; try { const result = await getConnection() - .createQueryBuilder() - .insert() - .into(User) - .values([{ - email: input.email, - password: hasedPassword, - name: input.name, - contactNumber: input.contactNumber, - providerID: req.session.providerID || undefined, - }]) - .execute(); - user = result.raw; + .createQueryBuilder() + .insert() + .into(User) + .values([{ + email: input.email, + password: hasedPassword, + name: input.name, + phoneNumber: input.phoneNumber, + providerID: req.session.providerID || undefined, + }]) + .returning('*') + .execute(); + user = result.raw[0]; } catch (err) { return { errors: [{ @@ -147,8 +159,16 @@ export class UserResolver { @Mutation(() => UserResponse) async login( @Arg('input') input: UsernamePasswordInput, - @Ctx() {req} : MyContext - ) : Promise { + @Ctx() { req } : MyContext + ): Promise { + if (req.session.userID !== undefined) { + return { + errors: [{ + field: "email", + message: "You're already logged in!", + }] + } + } const user = await User.findOne({where: { email: input.email }}); if (!user) { return { @@ -167,11 +187,16 @@ export class UserResolver { }] } } + const provider = await Provider.findOne({ where: { ownerID: user._id } }); req.session.userID = user._id; + if (provider) { + req.session.providerID = provider._id; + } return { user }; } @Mutation(() => Boolean) + @UseMiddleware(isAuth) logout( @Ctx() {req, res}: MyContext ) { @@ -182,7 +207,7 @@ export class UserResolver { resolve(false); return; } - res.clearCookie(COOKIE_NAME as string); + res.clearCookie(COOKIE_NAME); resolve(true); }) ) From 0b3bd6c7136f66dea1ad5db4d53a139064ead5a5 Mon Sep 17 00:00:00 2001 From: Rishav Mazumdar Date: Sun, 9 May 2021 19:29:18 +0530 Subject: [PATCH 2/6] =?UTF-8?q?Implemented=20User=20Login=20and=20Register?= =?UTF-8?q?=20=F0=9F=94=92=20=20(#26)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * added navbar responsiveness * Added alpine-node Co-authored-by: Yash Pandey (YP) --- .github/CONTRIBUTING.md | 9 ++-- client/Dockerfile | 3 +- .../Components/Pages/LoginPage/Login.js | 3 ++ .../UtilityComponents/Header/Header.js | 44 +++++++++++++++++++ .../UtilityComponents/Header/Header.scss | 10 +++++ client/src/index.js | 1 + server/Dockerfile | 3 +- server/package.json | 1 + server/src/index.ts | 4 +- server/src/resolvers/User.ts | 26 ++++------- server/tsconfig.json | 1 + server/yarn.lock | 2 +- 12 files changed, 80 insertions(+), 27 deletions(-) create mode 100644 client/src/CoviSource/Components/UtilityComponents/Header/Header.scss diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 7067d10..f44059c 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -105,18 +105,21 @@ git checkout example-feature createdb covisourcetestdb ``` -6. Issue the following commands in the root directory of the project: +6. Copy the contents of `/server/.env.dev` to `/server/.env` +(Make a new .env file. Do NOT delete `.env.dev`) + +7. Issue the following commands in the root directory of the project: ```bash yarn install yarn watch ``` -7. Let `yarn watch` run in background. Open a new terminal and issue: +8. Let `yarn watch` run in background. Open a new terminal and issue: ```bash yarn dev ``` -8. Make changes and push it to your fork, and create a PR on `dev` branch of this repo. +9. Make changes and push it to your fork, and create a PR on `dev` branch of this repo.
diff --git a/client/Dockerfile b/client/Dockerfile index f8cdac9..bf0e1d7 100644 --- a/client/Dockerfile +++ b/client/Dockerfile @@ -1,4 +1,4 @@ -FROM node:16 +FROM mhart/alpine-node:16 WORKDIR /client @@ -13,4 +13,3 @@ ENV NODE_ENV development EXPOSE 3000 CMD [ "yarn", "start" ] -USER node diff --git a/client/src/CoviSource/Components/Pages/LoginPage/Login.js b/client/src/CoviSource/Components/Pages/LoginPage/Login.js index a9ff14c..27afda6 100644 --- a/client/src/CoviSource/Components/Pages/LoginPage/Login.js +++ b/client/src/CoviSource/Components/Pages/LoginPage/Login.js @@ -21,6 +21,7 @@ import styles from "assets/jss/material-kit-react/views/loginPage.js"; import "./Login.scss"; import image from "assets/img/bg7.jpg"; +import { useHistory } from "react-router-dom"; import { useMutation } from "@apollo/client"; import { LOGIN } from "CoviSource/graphql/mutations/User/Login"; @@ -53,6 +54,7 @@ export default function Login(props) { }; const handleSubmit = async (event) => { + const history = useHistory(); event.preventDefault(); await login({ variables: { @@ -70,6 +72,7 @@ export default function Login(props) { Contact Number: ${data.login.user.phoneNumber}\n `); console.log(data.login.user); + history.push("/"); } }; diff --git a/client/src/CoviSource/Components/UtilityComponents/Header/Header.js b/client/src/CoviSource/Components/UtilityComponents/Header/Header.js index 8e31529..2efa532 100644 --- a/client/src/CoviSource/Components/UtilityComponents/Header/Header.js +++ b/client/src/CoviSource/Components/UtilityComponents/Header/Header.js @@ -1,8 +1,21 @@ import React from "react"; +import { NavLink } from "react-router-dom"; import propTypes from "prop-types"; import UI_HEADER from "components/Header/Header.js"; import { logoURL } from "CoviSource/UtilityFunctions"; +import "./Header.scss"; +import { gql, useQuery } from "@apollo/client"; + +const ME = gql` + query Me { + me { + _id + email + name + } + } +`; Header.propTypes = { theme: propTypes.string, @@ -10,6 +23,36 @@ Header.propTypes = { export default function Header(props) { const { ...rest } = props; + const { data, loading } = useQuery(ME); + let body = null; + if (loading) { + body = null; + } else if (data.me === null) { + body = ( + <> + + Login + + + Register + + + ); + } else { + body = ( + <> + + My Provider + + + Register Provider + + + Logout + + + ); + } return ( ); diff --git a/client/src/CoviSource/Components/UtilityComponents/Header/Header.scss b/client/src/CoviSource/Components/UtilityComponents/Header/Header.scss new file mode 100644 index 0000000..12bf8b2 --- /dev/null +++ b/client/src/CoviSource/Components/UtilityComponents/Header/Header.scss @@ -0,0 +1,10 @@ +.nav-link { + color: white; + :hover, :focus { + color: orange; + } + margin: 0 2em 0 2em; + @media (max-width: 960px) { + width: 100%; + } +} \ No newline at end of file diff --git a/client/src/index.js b/client/src/index.js index fcae7a4..883741a 100755 --- a/client/src/index.js +++ b/client/src/index.js @@ -17,6 +17,7 @@ import { ApolloClient, InMemoryCache } from "@apollo/client"; const client = new ApolloClient({ uri: process.env.REACT_APP_SERVER_URL, cache: new InMemoryCache(), + credentials: "include", }); var hist = createBrowserHistory(); diff --git a/server/Dockerfile b/server/Dockerfile index 7b7750c..d0488ab 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -1,4 +1,4 @@ -FROM node:16 +FROM mhart/alpine-node:16 # Create app directory WORKDIR /server @@ -16,4 +16,3 @@ ENV NODE_ENV development EXPOSE 4000 CMD [ "yarn", "dev" ] -USER node diff --git a/server/package.json b/server/package.json index c96c393..6ea8b67 100644 --- a/server/package.json +++ b/server/package.json @@ -33,6 +33,7 @@ "homepage": "https://github.com/EmperorYP7/CoviSource#readme", "devDependencies": { "@types/connect-redis": "^0.0.16", + "@types/cors": "^2.8.10", "@types/express": "^4.17.11", "@types/express-session": "^1.17.3", "@types/node": "^15.0.0", diff --git a/server/src/index.ts b/server/src/index.ts index b2a7093..5890454 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -32,7 +32,7 @@ const main = async () => { origin: process.env.CORS_ORIGIN, credentials: true, }) - ) + ); app.use( session({ @@ -61,7 +61,7 @@ const main = async () => { context: ({ req, res }) : MyContext => ({ req, res, redis }) }); - apolloServer.applyMiddleware({ app }); + apolloServer.applyMiddleware({ app, cors: false }); app.listen(parseInt(process.env.PORT), () => { console.log("connected to DB!"); diff --git a/server/src/resolvers/User.ts b/server/src/resolvers/User.ts index dad8d63..49d244a 100644 --- a/server/src/resolvers/User.ts +++ b/server/src/resolvers/User.ts @@ -131,23 +131,15 @@ export class UserResolver { .execute(); user = result.raw[0]; } catch (err) { - return { - errors: [{ - field: "THAT error :/", - message: err, - } - ] - } - } - - if (typeof user === 'undefined') { - return { - errors: [ - { - field: "password", - message: "Not a valid password" - } - ] + if (err.detail.includes("already exists")) { + return { + errors: [ + { + field: "username", + message: "This user already exists!" + } + ] + }; } } // Store userID session diff --git a/server/tsconfig.json b/server/tsconfig.json index 4abe505..4541234 100644 --- a/server/tsconfig.json +++ b/server/tsconfig.json @@ -11,6 +11,7 @@ "sourceMap": true, "outDir": "./dist", "moduleResolution": "node", + "skipLibCheck": true, "removeComments": true, "noImplicitAny": true, "strictNullChecks": true, diff --git a/server/yarn.lock b/server/yarn.lock index b521c38..27a23ce 100644 --- a/server/yarn.lock +++ b/server/yarn.lock @@ -296,7 +296,7 @@ "@types/keygrip" "*" "@types/node" "*" -"@types/cors@2.8.10": +"@types/cors@2.8.10", "@types/cors@^2.8.10": version "2.8.10" resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.10.tgz#61cc8469849e5bcdd0c7044122265c39cec10cf4" integrity sha512-C7srjHiVG3Ey1nR6d511dtDkCEjxuN9W1HWAEjGq8kpcwmNM6JJkpC0xvabM7BXTG2wDq8Eu33iH9aQKa7IvLQ== From 79c8f65dfa1adc8912b7b0f77671423c5292cc58 Mon Sep 17 00:00:00 2001 From: "Yash Pandey (YP)" Date: Mon, 10 May 2021 17:45:49 +0530 Subject: [PATCH 3/6] =?UTF-8?q?Fixed=20Login,=20Providers=20and=20Org=20pa?= =?UTF-8?q?ge=20=F0=9F=94=A8=20=20(#27)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fixed login and logout * Fixed login * Organisation page linked * Improved header --- .../Pages/CreateProvider/CreateProvider.js | 53 +++++-- .../Pages/CreateProvider/CreateResource.js | 6 +- .../Components/Pages/LoginPage/Login.js | 24 ++- .../Pages/OrganisationPage/Contacts.js | 54 +++++++ .../OrganisationPage/OrganisationPage.js | 144 ++++-------------- .../Pages/OrganisationPage/Resources.js | 57 +++++++ .../UtilityComponents/Header/Header.js | 92 ++++++----- .../graphql/queries/Provider/FindProvider.js | 2 +- .../graphql/queries/Provider/MyProvider.js | 8 - server/src/middleware/isRegistered.ts | 2 +- server/src/resolvers/User.ts | 3 +- 11 files changed, 252 insertions(+), 193 deletions(-) create mode 100644 client/src/CoviSource/Components/Pages/OrganisationPage/Contacts.js create mode 100644 client/src/CoviSource/Components/Pages/OrganisationPage/Resources.js diff --git a/client/src/CoviSource/Components/Pages/CreateProvider/CreateProvider.js b/client/src/CoviSource/Components/Pages/CreateProvider/CreateProvider.js index 496121d..ad9b2bb 100644 --- a/client/src/CoviSource/Components/Pages/CreateProvider/CreateProvider.js +++ b/client/src/CoviSource/Components/Pages/CreateProvider/CreateProvider.js @@ -23,6 +23,9 @@ import "./CreateProvider.scss"; import image from "assets/img/bg7.jpg"; import CreateContact from "./CreateContact"; +import { useMutation } from "@apollo/client"; +import { CREATE_PROVIDER } from "CoviSource/graphql/mutations/Provider/CreateProvider"; +import CreateResource from "./CreateResource"; // import Map from "CoviSource/Components/UtilityComponents/Map/Map"; const useStyles = makeStyles(styles); @@ -36,9 +39,12 @@ const formReducer = (state, event) => { export default function CreateProvider(props) { const [formData, setFormData] = useReducer(formReducer, {}); - const [resourceData, setresourceData] = useState([]); + const [resourceData, setresourceData] = useState({}); const [cardAnimaton, setCardAnimation] = useState("cardHidden"); const [numberContact, setNumberContact] = useState(0); + const [createProvider, { loading, data, error }] = useMutation( + CREATE_PROVIDER + ); setTimeout(function () { setCardAnimation(""); @@ -58,11 +64,35 @@ export default function CreateProvider(props) { }); console.log(formData); }; - const handleSubmit = (event) => { - console.log(formData); event.preventDefault(); - // console.log(resourceData); + createProvider({ + variables: { + input: { + providerName: formData.providerName, + address: formData.address, + location: { + latitude: formData.latitude * 1.0, + longitude: formData.longitude * 1.0, + }, + }, + }, + }); + if (!loading) { + if (data) { + if (data.createProvider.provider) { + alert( + "Created Provider: ", + data.createProvider.provider.providerName + ); + window.location.assign("/" + data.createProvider.provider.slug); + } else if (data.createProvider.errors) { + alert(data.createProvider.errors[0].message); + } + } else if (error) { + alert(error); + } + } }; return ( @@ -85,7 +115,7 @@ export default function CreateProvider(props) { -
+

Register your Institute/Provider

@@ -176,14 +206,13 @@ export default function CreateProvider(props) { resourceData={resourceData} setresourceData={setresourceData} /> + - diff --git a/client/src/CoviSource/Components/Pages/CreateProvider/CreateResource.js b/client/src/CoviSource/Components/Pages/CreateProvider/CreateResource.js index a3e01ba..a53f18a 100644 --- a/client/src/CoviSource/Components/Pages/CreateProvider/CreateResource.js +++ b/client/src/CoviSource/Components/Pages/CreateProvider/CreateResource.js @@ -5,7 +5,7 @@ import CustomInput from "components/CustomInput/CustomInput"; import propTypes from "prop-types"; import React from "react"; -export default function CreateContact({ classes, setresourceData }) { +export default function CreateResource({ classes, setresourceData }) { const handleChange = (event) => { setresourceData({ name: event.target.name, @@ -13,7 +13,7 @@ export default function CreateContact({ classes, setresourceData }) { }); }; return ( -
+
{ - const history = useHistory(); + const handleSubmit = (event) => { event.preventDefault(); - await login({ + login({ variables: { input: { email: formData.email, @@ -64,15 +62,15 @@ export default function Login(props) { }, }, }); - if (!loading && data !== undefined) { - alert("Login Sucessfull!"); - alert(`Your details: \n - ID: ${data.login.user._id}\n - Name: ${data.login.user.name}\n - Contact Number: ${data.login.user.phoneNumber}\n - `); - console.log(data.login.user); - history.push("/"); + if (!loading) { + if (data) { + if (data.login.errors) { + alert(data.login.errors[0].message); + } else { + alert("Logged In!"); + window.location.assign("/"); + } + } } }; diff --git a/client/src/CoviSource/Components/Pages/OrganisationPage/Contacts.js b/client/src/CoviSource/Components/Pages/OrganisationPage/Contacts.js new file mode 100644 index 0000000..381256a --- /dev/null +++ b/client/src/CoviSource/Components/Pages/OrganisationPage/Contacts.js @@ -0,0 +1,54 @@ +import React from "react"; +import { useQuery } from "@apollo/client"; +import { GET_CONTACTS } from "CoviSource/graphql/queries/Provider/GetContacts"; +import propTypes from "prop-types"; + +Contacts.propTypes = { + providerID: propTypes.number, +}; + +export default function Contacts({ providerID }) { + const { loading, data, error } = useQuery(GET_CONTACTS, { + variables: { + id: providerID, + }, + }); + if (loading) return <>Loading; + if (error) { + console.log(error); + return <>Error; + } + return ( +
+
    +
  • +
    +
    +
    contacts
    +
    +
    +
    +
  • + {data.getContact.map((item, id) => { + return ( +
  • +
    +
    +
    + {item.name}
    +
    +
    +
    +
    + {item.phoneNumber} +
    +
    +
    +
    +
  • + ); + })} +
+
+ ); +} diff --git a/client/src/CoviSource/Components/Pages/OrganisationPage/OrganisationPage.js b/client/src/CoviSource/Components/Pages/OrganisationPage/OrganisationPage.js index 3b4a9bb..3435998 100644 --- a/client/src/CoviSource/Components/Pages/OrganisationPage/OrganisationPage.js +++ b/client/src/CoviSource/Components/Pages/OrganisationPage/OrganisationPage.js @@ -1,13 +1,13 @@ import React from "react"; +import { useQuery } from "@apollo/client"; +import { FIND_PROVIDER } from "CoviSource/graphql/queries/Provider/FindProvider"; import { useParams } from "react-router-dom"; +import Contacts from "./Contacts"; import { makeStyles } from "@material-ui/core"; - import styles from "assets/jss/material-kit-react/views/components.js"; - import "./OrganisationPage.scss"; - +import Resources from "./Resources"; import Header from "CoviSource/Components/UtilityComponents/Header/Header"; -// import { logoURL } from "CoviSource/UtilityFunctions"; import { isMobile } from "CoviSource/UtilityFunctions"; import Map from "CoviSource/Components/UtilityComponents/Map/Map"; const useStyles = makeStyles(styles); @@ -20,51 +20,20 @@ const status = { export default function OrganisationPage() { const classes = useStyles(); - const data = { - username: "someUsername", - resourceProviderName: "Fortis Hospital, Kalyan", - availability: "AVAILABLE", - resources: [ - { - resource: "Oxygen refilling", - quantity: 32, - updated: "06:00 PM, 27 APRIL", - }, - { - resource: "Hospital Beds", - quantity: 23, - updated: "06:00 PM, 27 APRIL", - }, - { - resource: "Remdesivir Vials", - quantity: 65, - updated: "06:00 PM, 27 APRIL", - }, - ], - address: - "Fortis Hospital,\n Near Kalyan Market,\n Kalyan West,\n Maharashtra, India - 421306", - contacts: [ - { - contactPersonName: "Dr. Gaurav Bhatt", - phoneNumber: "9821095754", - }, - { - contactPersonName: "Dr. Ashok Bhoir", - phoneNumber: "9821095754", - }, - { - contactPersonName: "Dr. Rupender Singh Sodhi", - phoneNumber: "9821095754", - }, - ], - serviceName: "Service Provided", - location: { - lat: 19.21832, - lng: 73.1273, - }, - }; const params = useParams(); - console.log(params.orgName); + const { loading, data, error } = useQuery(FIND_PROVIDER, { + variables: { + slug: `${params.orgName}`, + }, + }); + if (loading) return <>Loading; + if (error) { + console.log(error); + return <>Error; + } + if (data) { + console.log(data); + } const getBannerClass = function () { return "banner banner" + status[data.availability]; @@ -75,6 +44,9 @@ export default function OrganisationPage() { color: "white", }; + if (data.findProviderbySlug === null) { + return <>Provider Not found!; + } return ( <>
-
{data.serviceName}
-

{data.resourceProviderName}

+
{data.findProviderbySlug.providerName}
+

{data.findProviderbySlug.providerName}

- {/* Resources */} -
    -
  • -
    -
    -
    resources
    -
    -
    -
    updated
    -
    -
    -
  • - {data.resources.map((item, id) => { - return ( -
  • -
    -
    -
    - {item.resource}
    - {item.quantity} Available -
    -
    -
    -
    - {item.updated}, 2021
    -
    -
    -
    -
  • - ); - })} -
- - {/* Contacts */} -
    -
  • -
    -
    -
    contacts
    -
    -
    -
    -
  • - {data.contacts.map((item, id) => { - return ( -
  • -
    -
    -
    - {item.contactPersonName}
    -
    -
    -
    -
    - {item.phoneNumber} -
    -
    -
    -
    -
  • - ); - })} -
+ + {/* Address */}
    @@ -172,7 +83,7 @@ export default function OrganisationPage() {
    - {data.address} + {data.findProviderbySlug.address}
    @@ -206,7 +117,10 @@ export default function OrganisationPage() { diff --git a/client/src/CoviSource/Components/Pages/OrganisationPage/Resources.js b/client/src/CoviSource/Components/Pages/OrganisationPage/Resources.js new file mode 100644 index 0000000..f0c55cb --- /dev/null +++ b/client/src/CoviSource/Components/Pages/OrganisationPage/Resources.js @@ -0,0 +1,57 @@ +import React from "react"; +import { useQuery } from "@apollo/client"; +import { GET_RESOURCES } from "CoviSource/graphql/queries/Provider/GetResources"; +import propTypes from "prop-types"; + +Resources.propTypes = { + providerID: propTypes.number, +}; + +export default function Resources({ providerID }) { + const { loading, data, error } = useQuery(GET_RESOURCES, { + variables: { + id: providerID, + }, + }); + if (loading) return <>Loading; + if (error) { + console.log(error); + return <>Error; + } + return ( +
    + {/* Resources */} +
      +
    • +
      +
      +
      resources
      +
      +
      +
      updated
      +
      +
      +
    • + {data.getResource.map((item, id) => { + return ( +
    • +
      +
      +
      + {item.name}
      + {item.quantity} Available +
      +
      +
      +
      + {item.updatedAt.toString()}, 2021
      +
      +
      +
      +
    • + ); + })} +
    +
    + ); +} diff --git a/client/src/CoviSource/Components/UtilityComponents/Header/Header.js b/client/src/CoviSource/Components/UtilityComponents/Header/Header.js index 2efa532..fab3731 100644 --- a/client/src/CoviSource/Components/UtilityComponents/Header/Header.js +++ b/client/src/CoviSource/Components/UtilityComponents/Header/Header.js @@ -5,17 +5,10 @@ import propTypes from "prop-types"; import UI_HEADER from "components/Header/Header.js"; import { logoURL } from "CoviSource/UtilityFunctions"; import "./Header.scss"; -import { gql, useQuery } from "@apollo/client"; - -const ME = gql` - query Me { - me { - _id - email - name - } - } -`; +import { useMutation, useQuery } from "@apollo/client"; +import { GET_USER } from "CoviSource/graphql/queries/User/GetUser"; +import { LOGOUT } from "CoviSource/graphql/mutations/User/Logout"; +import { MY_PROVIDER } from "CoviSource/graphql/queries/Provider/MyProvider"; Header.propTypes = { theme: propTypes.string, @@ -23,35 +16,41 @@ Header.propTypes = { export default function Header(props) { const { ...rest } = props; - const { data, loading } = useQuery(ME); - let body = null; + const { data, loading, error } = useQuery(GET_USER); + const [logout] = useMutation(LOGOUT); + const handleLogout = () => { + logout(); + window.location.assign("/"); + }; + let body; if (loading) { body = null; - } else if (data.me === null) { - body = ( - <> - - Login - - - Register - - - ); - } else { - body = ( - <> - - My Provider - - - Register Provider - - - Logout - - - ); + } + if (error) { + body = <>Error!; + } + if (data) { + if (data.me === null) { + body = ( + <> + + Login + + + Register + + + ); + } else { + body = ( + <> + + + Logout + + + ); + } } return ( ); } +const MyProviderButton = () => { + const { loading, data, error } = useQuery(MY_PROVIDER); + if (loading) return <>; + if (error) + return ( + + Register Provider + + ); + if (data) { + return ( + + My Provider + + ); + } +}; diff --git a/client/src/CoviSource/graphql/queries/Provider/FindProvider.js b/client/src/CoviSource/graphql/queries/Provider/FindProvider.js index 28b3303..308a7f1 100644 --- a/client/src/CoviSource/graphql/queries/Provider/FindProvider.js +++ b/client/src/CoviSource/graphql/queries/Provider/FindProvider.js @@ -3,7 +3,7 @@ import { gql } from "@apollo/client"; export const FIND_PROVIDER = gql` query FindProvider($slug: String!) { findProviderbySlug(slug: $slug) { - id + _id providerName address location { diff --git a/client/src/CoviSource/graphql/queries/Provider/MyProvider.js b/client/src/CoviSource/graphql/queries/Provider/MyProvider.js index bce178a..875bb31 100644 --- a/client/src/CoviSource/graphql/queries/Provider/MyProvider.js +++ b/client/src/CoviSource/graphql/queries/Provider/MyProvider.js @@ -4,15 +4,7 @@ export const MY_PROVIDER = gql` query MyProvider { myProvider { _id - providerName - address - location { - latitude - longitude - } slug - updatedAt - createdAt } } `; diff --git a/server/src/middleware/isRegistered.ts b/server/src/middleware/isRegistered.ts index 2f9aaf2..ffea952 100644 --- a/server/src/middleware/isRegistered.ts +++ b/server/src/middleware/isRegistered.ts @@ -3,7 +3,7 @@ import { MiddlewareFn } from "type-graphql"; export const isRegistered: MiddlewareFn = ({ context }, next) => { - if (!context.req.session.userID) { + if (!context.req.session.providerID) { throw new Error("Not registered as a provider"); } return next(); diff --git a/server/src/resolvers/User.ts b/server/src/resolvers/User.ts index 49d244a..af7fe21 100644 --- a/server/src/resolvers/User.ts +++ b/server/src/resolvers/User.ts @@ -54,7 +54,6 @@ class UserResponse { export class UserResolver { @Query(() => User, { nullable: true }) - @UseMiddleware(isAuth) async me(@Ctx() { req } : MyContext): Promise { // Not logged in if (!req.session.userID) { @@ -125,7 +124,7 @@ export class UserResolver { password: hasedPassword, name: input.name, phoneNumber: input.phoneNumber, - providerID: req.session.providerID || undefined, + providerID: undefined, }]) .returning('*') .execute(); From 16863e74dd52c633fbd964149ac78570f25d45a6 Mon Sep 17 00:00:00 2001 From: "Yash Pandey (YP)" Date: Thu, 13 May 2021 01:50:07 +0530 Subject: [PATCH 4/6] =?UTF-8?q?Connecting=20HomePage=20to=20backend=20?= =?UTF-8?q?=F0=9F=94=8C=20=F0=9F=9A=80=20=20(#30)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fixed login and logout * Fixed login * Organisation page linked * Improved header * Final fix * Connected homepage with backend * Fixed redis and homepage --- client/Dockerfile | 2 +- .../Pages/LandingPage/LandingPage.js | 393 +++++++++--------- .../Pages/OrganisationPage/Resources.js | 4 +- .../RegistrationPage/RegistrationPage.js | 16 +- .../ResourcesCardSection/CardView.js | 138 +++--- .../queries/Provider/GetAllProviders.js | 2 +- docker-compose.yml | 7 +- server/.env | 3 +- server/.env.example | 3 +- server/src/entities/Provider.ts | 6 +- server/src/env.d.ts | 3 +- server/src/index.ts | 23 +- server/src/resolvers/Provider.ts | 5 +- server/src/resolvers/Resource.ts | 6 +- 14 files changed, 330 insertions(+), 281 deletions(-) diff --git a/client/Dockerfile b/client/Dockerfile index bf0e1d7..0c2a096 100644 --- a/client/Dockerfile +++ b/client/Dockerfile @@ -1,4 +1,4 @@ -FROM mhart/alpine-node:16 +FROM node:16-alpine WORKDIR /client diff --git a/client/src/CoviSource/Components/Pages/LandingPage/LandingPage.js b/client/src/CoviSource/Components/Pages/LandingPage/LandingPage.js index e70ad6a..517606c 100644 --- a/client/src/CoviSource/Components/Pages/LandingPage/LandingPage.js +++ b/client/src/CoviSource/Components/Pages/LandingPage/LandingPage.js @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React from "react"; import { makeStyles } from "@material-ui/core"; // nodejs library that concatenates classes @@ -23,181 +23,186 @@ import styles from "assets/jss/material-kit-react/views/components.js"; import { isMobile } from "CoviSource/UtilityFunctions"; import coviLogo from "assets/img/logo.svg"; import bgImage from "assets/img/bg.jpg"; +import { useQuery } from "@apollo/client"; +import { GET_ALL_PROVIDERS } from "CoviSource/graphql/queries/Provider/GetAllProviders"; const useStyles = makeStyles(styles); export default function LandingPage(props) { const classes = useStyles(); const { ...rest } = props; + const { loading, data, error } = useQuery(GET_ALL_PROVIDERS); + if (loading) return <>Loading...; + if (error) return <>Error; + if (data) console.log(data); - const [data, setData] = useState([ - { - username: "someUsername", - resourceProviderName: "Resource Provider Name", - availability: "UNUPDATED", - resources: [ - { - resource: "Oxygen refilling", - quantity: 32, - updated: "06:00 PM, 27 APRIL", - }, - { - resource: "Hospital Beds", - quantity: 23, - updated: "06:00 PM, 27 APRIL", - }, - { - resource: "Remdesivir Vials", - quantity: 65, - updated: "06:00 PM, 27 APRIL", - }, - ], - address: "Provider Address", - contactPersonName: "Contact Person's Name", - phoneNumber: "9821095754", - serviceName: "Service Provided", - }, - { - username: "anotherUsername", - resourceProviderName: "Free oxygen seva vijaya nagar", - availability: "AVAILABLE", - resources: [ - { - resource: "Oxygen refilling", - quantity: 32, - updated: "06:00 PM, 27 APRIL", - }, - { - resource: "Hospital Beds", - quantity: 23, - updated: "06:00 PM, 27 APRIL", - }, - { - resource: "Remdesivir Vials", - quantity: 65, - updated: "06:00 PM, 27 APRIL", - }, - ], - address: "Free oxygen seva, near gurudwara, delhi", - contactPersonName: "Jaspal Singh", - phoneNumber: "9821095754", - serviceName: "Oxygen refilling", - }, - { - username: "anotherUsername2", - resourceProviderName: "Apex Hospital", - availability: "UNAVAILABLE", - resources: [ - { - resource: "Oxygen Cylinders", - quantity: 0, - updated: "06:00 PM, 27 APRIL", - }, - { - resource: "Hospital Beds", - quantity: 0, - updated: "06:00 PM, 27 APRIL", - }, - { - resource: "Remdesivir Vials", - quantity: 0, - updated: "06:00 PM, 27 APRIL", - }, - ], - address: "Apex Hospital, Kalyan West, Mumbai", - contactPersonName: "Dr. D P Goel", - phoneNumber: "9789965234", - serviceName: "Hospital", - }, - ]); + // const [data, setData] = useState([ + // { + // username: "someUsername", + // resourceProviderName: "Resource Provider Name", + // availability: "UNUPDATED", + // resources: [ + // { + // resource: "Oxygen refilling", + // quantity: 32, + // updated: "06:00 PM, 27 APRIL", + // }, + // { + // resource: "Hospital Beds", + // quantity: 23, + // updated: "06:00 PM, 27 APRIL", + // }, + // { + // resource: "Remdesivir Vials", + // quantity: 65, + // updated: "06:00 PM, 27 APRIL", + // }, + // ], + // address: "Provider Address", + // contactPersonName: "Contact Person's Name", + // phoneNumber: "9821095754", + // serviceName: "Service Provided", + // }, + // { + // username: "anotherUsername", + // resourceProviderName: "Free oxygen seva vijaya nagar", + // availability: "AVAILABLE", + // resources: [ + // { + // resource: "Oxygen refilling", + // quantity: 32, + // updated: "06:00 PM, 27 APRIL", + // }, + // { + // resource: "Hospital Beds", + // quantity: 23, + // updated: "06:00 PM, 27 APRIL", + // }, + // { + // resource: "Remdesivir Vials", + // quantity: 65, + // updated: "06:00 PM, 27 APRIL", + // }, + // ], + // address: "Free oxygen seva, near gurudwara, delhi", + // contactPersonName: "Jaspal Singh", + // phoneNumber: "9821095754", + // serviceName: "Oxygen refilling", + // }, + // { + // username: "anotherUsername2", + // resourceProviderName: "Apex Hospital", + // availability: "UNAVAILABLE", + // resources: [ + // { + // resource: "Oxygen Cylinders", + // quantity: 0, + // updated: "06:00 PM, 27 APRIL", + // }, + // { + // resource: "Hospital Beds", + // quantity: 0, + // updated: "06:00 PM, 27 APRIL", + // }, + // { + // resource: "Remdesivir Vials", + // quantity: 0, + // updated: "06:00 PM, 27 APRIL", + // }, + // ], + // address: "Apex Hospital, Kalyan West, Mumbai", + // contactPersonName: "Dr. D P Goel", + // phoneNumber: "9789965234", + // serviceName: "Hospital", + // }, + // ]); const onSearchButtonClick = function () { console.log("Search Button Clicked"); // a fetch operation will be made here which will then update the state -> data; - setData([ - { - username: "someUsername", - resourceProviderName: "Resource Provider Name", - availability: "UNUPDATED", - resources: [ - { - resource: "Oxygen refilling", - quantity: 32, - updated: "06:00 PM, 27 APRIL", - }, - { - resource: "Hospital Beds", - quantity: 23, - updated: "06:00 PM, 27 APRIL", - }, - { - resource: "Remdesivir Vials", - quantity: 65, - updated: "06:00 PM, 27 APRIL", - }, - ], - address: "Provider Address", - contactPersonName: "Contact Person's Name", - phoneNumber: "9821095754", - serviceName: "Service Provided", - }, - { - username: "anotherUsername", - resourceProviderName: "Free oxygen seva vijaya nagar", - availability: "AVAILABLE", - resources: [ - { - resource: "Oxygen refilling", - quantity: 32, - updated: "06:00 PM, 27 APRIL", - }, - { - resource: "Hospital Beds", - quantity: 23, - updated: "06:00 PM, 27 APRIL", - }, - { - resource: "Remdesivir Vials", - quantity: 65, - updated: "06:00 PM, 27 APRIL", - }, - ], - address: "Free oxygen seva, near gurudwara, delhi", - contactPersonName: "Jaspal Singh", - phoneNumber: "9821095754", - serviceName: "Oxygen refilling", - }, - { - username: "anotherUsername2", - resourceProviderName: "Apex Hospital", - availability: "UNAVAILABLE", - resources: [ - { - resource: "Oxygen Cylinders", - quantity: 0, - updated: "06:00 PM, 27 APRIL", - }, - { - resource: "Hospital Beds", - quantity: 0, - updated: "06:00 PM, 27 APRIL", - }, - { - resource: "Remdesivir Vials", - quantity: 0, - updated: "06:00 PM, 27 APRIL", - }, - ], - address: "Apex Hospital, Kalyan West, Mumbai", - contactPersonName: "Dr. D P Goel", - phoneNumber: "9789965234", - serviceName: "Hospital", - }, - ]); + // setData([ + // { + // username: "someUsername", + // resourceProviderName: "Resource Provider Name", + // availability: "UNUPDATED", + // resources: [ + // { + // resource: "Oxygen refilling", + // quantity: 32, + // updated: "06:00 PM, 27 APRIL", + // }, + // { + // resource: "Hospital Beds", + // quantity: 23, + // updated: "06:00 PM, 27 APRIL", + // }, + // { + // resource: "Remdesivir Vials", + // quantity: 65, + // updated: "06:00 PM, 27 APRIL", + // }, + // ], + // address: "Provider Address", + // contactPersonName: "Contact Person's Name", + // phoneNumber: "9821095754", + // serviceName: "Service Provided", + // }, + // { + // username: "anotherUsername", + // resourceProviderName: "Free oxygen seva vijaya nagar", + // availability: "AVAILABLE", + // resources: [ + // { + // resource: "Oxygen refilling", + // quantity: 32, + // updated: "06:00 PM, 27 APRIL", + // }, + // { + // resource: "Hospital Beds", + // quantity: 23, + // updated: "06:00 PM, 27 APRIL", + // }, + // { + // resource: "Remdesivir Vials", + // quantity: 65, + // updated: "06:00 PM, 27 APRIL", + // }, + // ], + // address: "Free oxygen seva, near gurudwara, delhi", + // contactPersonName: "Jaspal Singh", + // phoneNumber: "9821095754", + // serviceName: "Oxygen refilling", + // }, + // { + // username: "anotherUsername2", + // resourceProviderName: "Apex Hospital", + // availability: "UNAVAILABLE", + // resources: [ + // { + // resource: "Oxygen Cylinders", + // quantity: 0, + // updated: "06:00 PM, 27 APRIL", + // }, + // { + // resource: "Hospital Beds", + // quantity: 0, + // updated: "06:00 PM, 27 APRIL", + // }, + // { + // resource: "Remdesivir Vials", + // quantity: 0, + // updated: "06:00 PM, 27 APRIL", + // }, + // ], + // address: "Apex Hospital, Kalyan West, Mumbai", + // contactPersonName: "Dr. D P Goel", + // phoneNumber: "9789965234", + // serviceName: "Hospital", + // }, + // ]); }; - - const renderResroucesCards = function (data) { + const renderResourcesCards = () => { return (
    - +
    ); }; - - return ( -
    -
    - -
    - - -
    -

    - -

    -

    - Find resources that you need -

    -
    -
    -
    - -
    -
    - {renderResroucesCards(data)} -
    - ); + if (data.allProviders) { + return ( +
    +
    + +
    + + +
    +

    + +

    +

    + Find resources that you need +

    +
    +
    +
    + +
    +
    + {renderResourcesCards()} +
    + ); + } } diff --git a/client/src/CoviSource/Components/Pages/OrganisationPage/Resources.js b/client/src/CoviSource/Components/Pages/OrganisationPage/Resources.js index f0c55cb..8fd0f13 100644 --- a/client/src/CoviSource/Components/Pages/OrganisationPage/Resources.js +++ b/client/src/CoviSource/Components/Pages/OrganisationPage/Resources.js @@ -33,6 +33,7 @@ export default function Resources({ providerID }) {
    {data.getResource.map((item, id) => { + var date = new Date(parseInt(item.updatedAt)); return (
  • @@ -44,7 +45,8 @@ export default function Resources({ providerID }) {
    - {item.updatedAt.toString()}, 2021
    + {date.toLocaleString()} +
  • diff --git a/client/src/CoviSource/Components/Pages/RegistrationPage/RegistrationPage.js b/client/src/CoviSource/Components/Pages/RegistrationPage/RegistrationPage.js index 44f8459..51d8e57 100644 --- a/client/src/CoviSource/Components/Pages/RegistrationPage/RegistrationPage.js +++ b/client/src/CoviSource/Components/Pages/RegistrationPage/RegistrationPage.js @@ -46,7 +46,7 @@ export default function RegistrationPage(props) { const classes = useStyles(); const { ...rest } = props; - const [addUser, { data, loading }] = useMutation(ADD_USER); + const [addUser, { data, loading, error }] = useMutation(ADD_USER); const scrollChangeData = { height: 5, @@ -72,8 +72,18 @@ export default function RegistrationPage(props) { }, }, }); - if (!loading && !data) { - alert("Registration successfull!"); + if (loading); + if (error) { + alert(error); + } + if (data) { + if (data.register.errors) { + alert(data.register.errors[0].message); + } + if (data.register.user) { + alert("Registration sucessful!"); + window.location.assign("/"); + } } }; diff --git a/client/src/CoviSource/Components/UtilityComponents/ResourcesCardSection/CardView.js b/client/src/CoviSource/Components/UtilityComponents/ResourcesCardSection/CardView.js index b6a26df..ba88e0e 100644 --- a/client/src/CoviSource/Components/UtilityComponents/ResourcesCardSection/CardView.js +++ b/client/src/CoviSource/Components/UtilityComponents/ResourcesCardSection/CardView.js @@ -14,6 +14,8 @@ import Button from "CoviSource/Components/UtilityComponents/Button/Button.js"; import styles from "assets/jss/material-kit-react/views/componentsSections/basicsStyle.js"; import "./CardView.scss"; import { isMobile } from "CoviSource/UtilityFunctions"; +import { useQuery } from "@apollo/client"; +import { GET_RESOURCES } from "CoviSource/graphql/queries/Provider/GetResources"; const useStyles = makeStyles(styles); const status = { @@ -30,6 +32,9 @@ CardView.propTypes = { export default function CardView(props) { const [data, setData] = useState(props.data); + if (data === []) { + return <>No data; + } const [resourceType, setResourceType] = useState("ALL"); // oneOf["ALL", "AVAILABLE", "UNUPDATED", "UNAVAIBALE"] if (data === null) { setData(""); @@ -94,91 +99,59 @@ export default function CardView(props) {

- {details.phoneNumber} + {provider.phoneNumber}

-
  • +
  • -
    {details.serviceName}
    +
    {provider.serviceName}

    - - {details.resourceProviderName} - + {provider.providerName}

    @@ -219,7 +186,7 @@ export default function CardView(props) {
    More details ...
    @@ -237,3 +204,54 @@ export default function CardView(props) {
  • ); } + +function ResourceDetail(Providerid) { + const { loading, data, error } = useQuery(GET_RESOURCES, { + variables: { + id: Providerid, + }, + }); + if (loading) return <>Loading...; + if (error) { + alert(error); + return <>Error!; + } + if (data) { + if (data.getResource) { + return ( +
      + {data.getResource.map((resource, id) => { + var date = new Date(parseInt(resource.updatedAt)); + return ( +
    • +
      +
      +
      {resource.name}
      +
      +
      +

      + {resource.quantity} available +

      +
      +
      +
      +
      +
      updated
      +
      +
      +

      + {date.toLocaleString()} +

      +
      +
      +
    • + ); + })} +
    + ); + } + } +} diff --git a/client/src/CoviSource/graphql/queries/Provider/GetAllProviders.js b/client/src/CoviSource/graphql/queries/Provider/GetAllProviders.js index a76db49..f70612b 100644 --- a/client/src/CoviSource/graphql/queries/Provider/GetAllProviders.js +++ b/client/src/CoviSource/graphql/queries/Provider/GetAllProviders.js @@ -3,7 +3,7 @@ import { gql } from "@apollo/client"; export const GET_ALL_PROVIDERS = gql` query GetAllProviders { allProviders { - id + _id providerName address location { diff --git a/docker-compose.yml b/docker-compose.yml index 435b814..e99a4dd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,8 +16,7 @@ services: depends_on: - redis environment: - REDIS_HOST: redis - REDIS_PORT: 6379 + REDIS_URL: redis:6379 DATABASE_URL: postgresql://postgres:postgres@database:5432/covisourcetestdb CORS_ORIGIN: http://localhost:3000 SESSION_SECRET: somerandomsecret @@ -37,7 +36,7 @@ services: REACT_APP_SERVER_URL: http://localhost:4000/graphql redis: - image: redis + image: redis:alpine container_name: covisource-redis command: redis-server @@ -46,7 +45,7 @@ services: database: container_name: covisource-database - image: postgres + image: postgres:alpine env_file: - database.env volumes: diff --git a/server/.env b/server/.env index dd44e90..b5c7922 100644 --- a/server/.env +++ b/server/.env @@ -2,5 +2,4 @@ CORS_ORIGIN=http://localhost:3000 SESSION_SECRET=somerandomsecret DATABASE_URL=postgresql://postgres:postgres@localhost:5432/covisourcetestdb PORT=4000 -REDIS_PORT=6379 -REDIS_HOST=127.0.0.1 +REDIS_URL=127.0.0.1:6379 diff --git a/server/.env.example b/server/.env.example index b932fb5..9aef3cb 100644 --- a/server/.env.example +++ b/server/.env.example @@ -2,5 +2,4 @@ CORS_ORIGIN= SESSION_SECRET= DATABASE_URL= PORT= -REDIS_PORT= -REDIS_HOST= \ No newline at end of file +REDIS_URL= \ No newline at end of file diff --git a/server/src/entities/Provider.ts b/server/src/entities/Provider.ts index e0ce839..95af145 100644 --- a/server/src/entities/Provider.ts +++ b/server/src/entities/Provider.ts @@ -18,11 +18,13 @@ export class Provider extends BaseEntity { @Column() address!: string; - @OneToMany(() => Resource, resource => resource.provider) + @Field(() => [Resource], { nullable: true }) + @OneToMany(() => Resource, resource => resource.provider, { eager: true }) @JoinColumn() resources: Resource[]; - @OneToMany(() => Contact, contact => contact.provider) + @Field(() => [Contact], { nullable: true }) + @OneToMany(() => Contact, contact => contact.provider, { eager: true }) @JoinColumn() contacts: Contact[]; diff --git a/server/src/env.d.ts b/server/src/env.d.ts index bf9450f..ed636d9 100644 --- a/server/src/env.d.ts +++ b/server/src/env.d.ts @@ -4,7 +4,6 @@ declare namespace NodeJS { SESSION_SECRET: string; DATABASE_URL: string; PORT: string; - REDIS_PORT: string; - REDIS_HOST: string; + REDIS_URL: string; } } \ No newline at end of file diff --git a/server/src/index.ts b/server/src/index.ts index 5890454..89d5b26 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -22,10 +22,9 @@ const main = async () => { const app = express(); const RedisStore = connectRedis(session); - const redis = new Redis({ - port: process.env.REDIS_PORT as unknown as number, - host: process.env.REDIS_HOST, - }); + const redis = new Redis(process.env.REDIS_URL); + + app.set("trust proxy", 1); app.use( cors({ @@ -45,7 +44,8 @@ const main = async () => { maxAge: COOKIE_MAX_AGE, httpOnly: true, secure: __prod__, - sameSite: 'lax' + sameSite: 'lax', + domain: __prod__ ? '.emperoryp.live' : undefined, }, saveUninitialized: false, secret: process.env.SESSION_SECRET, @@ -56,16 +56,21 @@ const main = async () => { const apolloServer = new ApolloServer({ schema: await buildSchema({ resolvers: [ProviderResolver, UserResolver, ResourceResolver, ContactResolver], - validate: false + validate: false, }), - context: ({ req, res }) : MyContext => ({ req, res, redis }) + context: ({ req, res }): MyContext => ({ req, res, redis }), }); - apolloServer.applyMiddleware({ app, cors: false }); + apolloServer.applyMiddleware({ + app, + cors: false, + }); app.listen(parseInt(process.env.PORT), () => { console.log("connected to DB!"); }); }; -main(); +main().catch((err) => { + console.error(err); +}); diff --git a/server/src/resolvers/Provider.ts b/server/src/resolvers/Provider.ts index b780ffb..39e6d2c 100644 --- a/server/src/resolvers/Provider.ts +++ b/server/src/resolvers/Provider.ts @@ -4,6 +4,7 @@ import slugify from 'slugify'; import { MyContext } from 'src/types'; import { isAuth } from '../middleware/isAuth'; import { isRegistered } from '../middleware/isRegistered'; +import { getRepository } from 'typeorm'; @InputType() class LocationTemplate { @@ -30,7 +31,8 @@ class NewProviderInput { export class ProviderResolver { @Query(() => [Provider]) allProviders(): Promise { - return Provider.find(); + const providerRepository = getRepository(Provider); + return providerRepository.find(); } @Query(() => Provider, { nullable: true }) @@ -107,4 +109,5 @@ export class ProviderResolver { } return true; } + } diff --git a/server/src/resolvers/Resource.ts b/server/src/resolvers/Resource.ts index 2aff551..1de7423 100644 --- a/server/src/resolvers/Resource.ts +++ b/server/src/resolvers/Resource.ts @@ -108,6 +108,7 @@ export class ResourceResolver { @UseMiddleware(isAuth, isRegistered) async updateResource( @Arg('input') input: ResourceUpdateInput, + @Ctx() { req } : MyContext ): Promise { if (input.name.length <= 3) { return { @@ -134,9 +135,12 @@ export class ResourceResolver { }] } } else { - await Resource.update(input.id, { + await Resource.update({ name: input.name, quantity: input.quantity + }, { + id: input.id, + providerID: req.session.providerID }); return { resource }; From 14a8b8b2522b8807085b231ad02f30f166e452ed Mon Sep 17 00:00:00 2001 From: Soumyabrata Bairagi <69338695+sb2356-iiitr@users.noreply.github.com> Date: Fri, 14 May 2021 09:34:44 +0400 Subject: [PATCH 5/6] =?UTF-8?q?Removed=20unnecessary=20directories=20?= =?UTF-8?q?=F0=9F=97=91=EF=B8=8F=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/.eslintrc.js | 6 + client/src/components/Badge/Badge.js | 35 --- client/src/components/Clearfix/Clearfix.js | 25 -- .../CustomDropdown/CustomDropdown.js | 195 ---------------- .../CustomDropdown/CustomDropdown.jsx | 214 ------------------ .../CustomLinearProgress.js | 41 ---- .../src/components/CustomTabs/CustomTabs.js | 104 --------- client/src/components/InfoArea/InfoArea.js | 56 ----- client/src/components/NavPills/NavPills.js | 131 ----------- .../src/components/Pagination/Pagination.js | 64 ------ .../components/Snackbar/SnackbarContent.js | 72 ------ client/src/components/Typography/Danger.js | 23 -- client/src/components/Typography/Info.js | 23 -- client/src/components/Typography/Muted.js | 23 -- client/src/components/Typography/Primary.js | 23 -- client/src/components/Typography/Quote.js | 25 -- client/src/components/Typography/Small.js | 23 -- client/src/components/Typography/Success.js | 23 -- client/src/components/Typography/Warning.js | 23 -- 19 files changed, 6 insertions(+), 1123 deletions(-) delete mode 100755 client/src/components/Badge/Badge.js delete mode 100755 client/src/components/Clearfix/Clearfix.js delete mode 100755 client/src/components/CustomDropdown/CustomDropdown.js delete mode 100755 client/src/components/CustomDropdown/CustomDropdown.jsx delete mode 100755 client/src/components/CustomLinearProgress/CustomLinearProgress.js delete mode 100755 client/src/components/CustomTabs/CustomTabs.js delete mode 100755 client/src/components/InfoArea/InfoArea.js delete mode 100755 client/src/components/NavPills/NavPills.js delete mode 100755 client/src/components/Pagination/Pagination.js delete mode 100755 client/src/components/Snackbar/SnackbarContent.js delete mode 100755 client/src/components/Typography/Danger.js delete mode 100755 client/src/components/Typography/Info.js delete mode 100755 client/src/components/Typography/Muted.js delete mode 100755 client/src/components/Typography/Primary.js delete mode 100755 client/src/components/Typography/Quote.js delete mode 100755 client/src/components/Typography/Small.js delete mode 100755 client/src/components/Typography/Success.js delete mode 100755 client/src/components/Typography/Warning.js diff --git a/client/.eslintrc.js b/client/.eslintrc.js index e254df4..06edd8a 100644 --- a/client/.eslintrc.js +++ b/client/.eslintrc.js @@ -18,4 +18,10 @@ module.exports = { "plugin:react/recommended", "plugin:prettier/recommended", ], + rules: { + 'prettier/prettier': [ + 'error', + {endOfLine: 'auto'} + ] + }, }; diff --git a/client/src/components/Badge/Badge.js b/client/src/components/Badge/Badge.js deleted file mode 100755 index 3d29d5a..0000000 --- a/client/src/components/Badge/Badge.js +++ /dev/null @@ -1,35 +0,0 @@ -import React from "react"; -// nodejs library to set properties for components -import PropTypes from "prop-types"; - -// @material-ui/core components -import { makeStyles } from "@material-ui/core/styles"; - -import styles from "assets/jss/material-kit-react/components/badgeStyle.js"; - -const useStyles = makeStyles(styles); - -export default function Badge(props) { - const classes = useStyles(); - const { color, children } = props; - return ( - {children} - ); -} - -Badge.defaultProps = { - color: "gray", -}; - -Badge.propTypes = { - color: PropTypes.oneOf([ - "primary", - "warning", - "danger", - "success", - "info", - "rose", - "gray", - ]), - children: PropTypes.node, -}; diff --git a/client/src/components/Clearfix/Clearfix.js b/client/src/components/Clearfix/Clearfix.js deleted file mode 100755 index c95a1bc..0000000 --- a/client/src/components/Clearfix/Clearfix.js +++ /dev/null @@ -1,25 +0,0 @@ -import React from "react"; - -// mterial-ui components -import { makeStyles } from "@material-ui/core/styles"; - -const styles = { - clearfix: { - "&:after,&:before": { - display: "table", - content: '" "', - }, - "&:after": { - clear: "both", - }, - }, -}; - -const useStyles = makeStyles(styles); - -export default function Clearfix() { - const classes = useStyles(); - return
    ; -} - -Clearfix.propTypes = {}; diff --git a/client/src/components/CustomDropdown/CustomDropdown.js b/client/src/components/CustomDropdown/CustomDropdown.js deleted file mode 100755 index 6c176db..0000000 --- a/client/src/components/CustomDropdown/CustomDropdown.js +++ /dev/null @@ -1,195 +0,0 @@ -import React from "react"; -// nodejs library that concatenates classes -import classNames from "classnames"; -// nodejs library to set properties for components -import PropTypes from "prop-types"; - -// @material-ui/core components -import { makeStyles } from "@material-ui/core/styles"; -import MenuItem from "@material-ui/core/MenuItem"; -import MenuList from "@material-ui/core/MenuList"; -import ClickAwayListener from "@material-ui/core/ClickAwayListener"; -import Paper from "@material-ui/core/Paper"; -import Grow from "@material-ui/core/Grow"; -import Divider from "@material-ui/core/Divider"; -import Icon from "@material-ui/core/Icon"; -import Popper from "@material-ui/core/Popper"; - -// core components -import Button from "components/CustomButtons/Button.js"; - -import styles from "assets/jss/material-kit-react/components/customDropdownStyle.js"; - -const useStyles = makeStyles(styles); - -export default function CustomDropdown(props) { - const [anchorEl, setAnchorEl] = React.useState(null); - const handleClick = (event) => { - if (anchorEl && anchorEl.contains(event.target)) { - setAnchorEl(null); - } else { - setAnchorEl(event.currentTarget); - } - }; - const handleClose = (param) => { - setAnchorEl(null); - if (props && props.onClick) { - props.onClick(param); - } - }; - const handleCloseAway = (event) => { - if (anchorEl.contains(event.target)) { - return; - } - setAnchorEl(null); - }; - const classes = useStyles(); - const { - buttonText, - buttonIcon, - dropdownList, - buttonProps, - dropup, - dropdownHeader, - caret, - hoverColor, - left, - rtlActive, - noLiPadding, - } = props; - const caretClasses = classNames({ - [classes.caret]: true, - [classes.caretActive]: Boolean(anchorEl), - [classes.caretRTL]: rtlActive, - }); - const dropdownItem = classNames({ - [classes.dropdownItem]: true, - [classes[hoverColor + "Hover"]]: true, - [classes.noLiPadding]: noLiPadding, - [classes.dropdownItemRTL]: rtlActive, - }); - let icon = null; - switch (typeof buttonIcon) { - case "object": - icon = ; - break; - case "string": - icon = {props.buttonIcon}; - break; - default: - icon = null; - break; - } - return ( -
    -
    - -
    - - {() => ( - - - - - {dropdownHeader !== undefined ? ( - handleClose(dropdownHeader)} - className={classes.dropdownHeader} - > - {dropdownHeader} - - ) : null} - {dropdownList.map((prop, key) => { - if (prop.divider) { - return ( - handleClose("divider")} - className={classes.dropdownDividerItem} - /> - ); - } - return ( - handleClose(prop)} - className={dropdownItem} - > - {prop} - - ); - })} - - - - - )} - -
    - ); -} - -CustomDropdown.defaultProps = { - caret: true, - hoverColor: "primary", -}; - -CustomDropdown.propTypes = { - hoverColor: PropTypes.oneOf([ - "black", - "primary", - "info", - "success", - "warning", - "danger", - "rose", - ]), - buttonText: PropTypes.node, - buttonIcon: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), - dropdownList: PropTypes.array, - buttonProps: PropTypes.object, - dropup: PropTypes.bool, - dropdownHeader: PropTypes.node, - rtlActive: PropTypes.bool, - caret: PropTypes.bool, - left: PropTypes.bool, - noLiPadding: PropTypes.bool, - // function that retuns the selected item - onClick: PropTypes.func, -}; diff --git a/client/src/components/CustomDropdown/CustomDropdown.jsx b/client/src/components/CustomDropdown/CustomDropdown.jsx deleted file mode 100755 index d7c1719..0000000 --- a/client/src/components/CustomDropdown/CustomDropdown.jsx +++ /dev/null @@ -1,214 +0,0 @@ -import React from "react"; -// nodejs library that concatenates classes -import classNames from "classnames"; -// nodejs library to set properties for components -import PropTypes from "prop-types"; - -// @material-ui/core components -import withStyles from "@material-ui/core/styles/withStyles"; -import MenuItem from "@material-ui/core/MenuItem"; -import MenuList from "@material-ui/core/MenuList"; -import ClickAwayListener from "@material-ui/core/ClickAwayListener"; -import Paper from "@material-ui/core/Paper"; -import Grow from "@material-ui/core/Grow"; -import Divider from "@material-ui/core/Divider"; -import Icon from "@material-ui/core/Icon"; -import Popper from "@material-ui/core/Popper"; - -// core components -import Button from "components/CustomButtons/Button.jsx"; - -import customDropdownStyle from "assets/jss/material-kit-react/components/customDropdownStyle.jsx"; - -class CustomDropdown extends React.Component { - constructor(props) { - super(props); - this.state = { - open: false, - }; - } - handleClick = () => { - this.setState((state) => ({ open: !state.open })); - }; - handleClose = (param) => { - this.setState({ open: false }); - if (this.props && this.props.onClick) { - this.props.onClick(param); - } - }; - handleCloseAway = (event) => { - if (this.anchorEl.contains(event.target)) { - return; - } - this.setState({ open: false }); - }; - render() { - const { open } = this.state; - const { - classes, - buttonText, - buttonIcon, - dropdownList, - buttonProps, - dropup, - dropdownHeader, - caret, - hoverColor, - left, - rtlActive, - noLiPadding, - } = this.props; - const caretClasses = classNames({ - [classes.caret]: true, - [classes.caretActive]: open, - [classes.caretRTL]: rtlActive, - }); - const dropdownItem = classNames({ - [classes.dropdownItem]: true, - [classes[hoverColor + "Hover"]]: true, - [classes.noLiPadding]: noLiPadding, - [classes.dropdownItemRTL]: rtlActive, - }); - let icon = null; - switch (typeof buttonIcon) { - case "function": - icon = ; - break; - case "object": - if (buttonIcon.type.muiName === "Icon") { - icon = this.props.buttonIcon; - } - break; - case "string": - icon = ( - {this.props.buttonIcon} - ); - break; - default: - icon = null; - break; - } - return ( -
    -
    - -
    - - {({ TransitionProps, placement }) => ( - - - - - {dropdownHeader !== undefined ? ( - this.handleClose(dropdownHeader)} - className={classes.dropdownHeader} - > - {dropdownHeader} - - ) : null} - {dropdownList.map((prop, key) => { - if (prop.divider) { - return ( - this.handleClose("divider")} - className={classes.dropdownDividerItem} - /> - ); - } - return ( - this.handleClose(prop)} - className={dropdownItem} - > - {prop} - - ); - })} - - - - - )} - -
    - ); - } -} - -CustomDropdown.defaultProps = { - caret: true, - hoverColor: "primary", -}; - -CustomDropdown.propTypes = { - classes: PropTypes.object.isRequired, - hoverColor: PropTypes.oneOf([ - "black", - "primary", - "info", - "success", - "warning", - "danger", - "rose", - ]), - buttonText: PropTypes.node, - buttonIcon: PropTypes.oneOfType([ - PropTypes.func, - PropTypes.object, - PropTypes.string, - ]), - dropdownList: PropTypes.array, - buttonProps: PropTypes.object, - dropup: PropTypes.bool, - dropdownHeader: PropTypes.node, - rtlActive: PropTypes.bool, - caret: PropTypes.bool, - left: PropTypes.bool, - noLiPadding: PropTypes.bool, - // function that retuns the selected item - onClick: PropTypes.func, -}; - -export default withStyles(customDropdownStyle)(CustomDropdown); diff --git a/client/src/components/CustomLinearProgress/CustomLinearProgress.js b/client/src/components/CustomLinearProgress/CustomLinearProgress.js deleted file mode 100755 index 78ecb4c..0000000 --- a/client/src/components/CustomLinearProgress/CustomLinearProgress.js +++ /dev/null @@ -1,41 +0,0 @@ -import React from "react"; -// nodejs library to set properties for components -import PropTypes from "prop-types"; - -// @material-ui/core components -import { makeStyles } from "@material-ui/core/styles"; -import LinearProgress from "@material-ui/core/LinearProgress"; -// core components -import styles from "assets/jss/material-kit-react/components/customLinearProgressStyle.js"; - -const useStyles = makeStyles(styles); - -export default function CustomLinearProgress(props) { - const classes = useStyles(); - const { color, ...rest } = props; - return ( - - ); -} - -CustomLinearProgress.defaultProps = { - color: "gray", -}; - -CustomLinearProgress.propTypes = { - color: PropTypes.oneOf([ - "primary", - "warning", - "danger", - "success", - "info", - "rose", - "gray", - ]), -}; diff --git a/client/src/components/CustomTabs/CustomTabs.js b/client/src/components/CustomTabs/CustomTabs.js deleted file mode 100755 index 31190b5..0000000 --- a/client/src/components/CustomTabs/CustomTabs.js +++ /dev/null @@ -1,104 +0,0 @@ -import React from "react"; -// nodejs library that concatenates classes -import classNames from "classnames"; -// nodejs library to set properties for components -import PropTypes from "prop-types"; - -// material-ui components -import { makeStyles } from "@material-ui/core/styles"; -import Tabs from "@material-ui/core/Tabs"; -import Tab from "@material-ui/core/Tab"; -import Icon from "@material-ui/core/Icon"; -// core components -import Card from "components/Card/Card.js"; -import CardBody from "components/Card/CardBody.js"; -import CardHeader from "components/Card/CardHeader.js"; - -import styles from "assets/jss/material-kit-react/components/customTabsStyle.js"; - -const useStyles = makeStyles(styles); - -export default function CustomTabs(props) { - const [value, setValue] = React.useState(0); - - const handleChange = (event, value) => { - setValue(value); - }; - const classes = useStyles(); - const { headerColor, plainTabs, tabs, title, rtlActive } = props; - const cardTitle = classNames({ - [classes.cardTitle]: true, - [classes.cardTitleRTL]: rtlActive, - }); - return ( - - - {title !== undefined ?
    {title}
    : null} - - {tabs.map((prop, key) => { - var icon = {}; - if (prop.tabIcon) { - icon = { - icon: - typeof prop.tabIcon === "string" ? ( - {prop.tabIcon} - ) : ( - - ), - }; - } - return ( - - ); - })} - -
    - - {tabs.map((prop, key) => { - if (key === value) { - return
    {prop.tabContent}
    ; - } - return null; - })} -
    -
    - ); -} - -CustomTabs.propTypes = { - headerColor: PropTypes.oneOf([ - "warning", - "success", - "danger", - "info", - "primary", - "rose", - ]), - title: PropTypes.string, - tabs: PropTypes.arrayOf( - PropTypes.shape({ - tabName: PropTypes.string.isRequired, - tabIcon: PropTypes.object, - tabContent: PropTypes.node.isRequired, - }) - ), - rtlActive: PropTypes.bool, - plainTabs: PropTypes.bool, -}; diff --git a/client/src/components/InfoArea/InfoArea.js b/client/src/components/InfoArea/InfoArea.js deleted file mode 100755 index 82a7f4b..0000000 --- a/client/src/components/InfoArea/InfoArea.js +++ /dev/null @@ -1,56 +0,0 @@ -import React from "react"; -// nodejs library to set properties for components -import PropTypes from "prop-types"; -// nodejs library that concatenates classes -import classNames from "classnames"; -// @material-ui/core components -import { makeStyles } from "@material-ui/core/styles"; - -import styles from "assets/jss/material-kit-react/components/infoStyle.js"; - -const useStyles = makeStyles(styles); - -export default function InfoArea(props) { - const classes = useStyles(); - const { title, description, iconColor, vertical } = props; - const iconWrapper = classNames({ - [classes.iconWrapper]: true, - [classes[iconColor]]: true, - [classes.iconWrapperVertical]: vertical, - }); - const iconClasses = classNames({ - [classes.icon]: true, - [classes.iconVertical]: vertical, - }); - return ( -
    -
    - -
    -
    -

    {title}

    -

    {description}

    -
    -
    - ); -} - -InfoArea.defaultProps = { - iconColor: "gray", -}; - -InfoArea.propTypes = { - icon: PropTypes.object.isRequired, - title: PropTypes.string.isRequired, - description: PropTypes.string.isRequired, - iconColor: PropTypes.oneOf([ - "primary", - "warning", - "danger", - "success", - "info", - "rose", - "gray", - ]), - vertical: PropTypes.bool, -}; diff --git a/client/src/components/NavPills/NavPills.js b/client/src/components/NavPills/NavPills.js deleted file mode 100755 index 0014763..0000000 --- a/client/src/components/NavPills/NavPills.js +++ /dev/null @@ -1,131 +0,0 @@ -import React from "react"; -// nodejs library that concatenates classes -import classNames from "classnames"; -// nodejs library to set properties for components -import PropTypes from "prop-types"; -import SwipeableViews from "react-swipeable-views"; - -// @material-ui/core components -import { makeStyles } from "@material-ui/core/styles"; -import Tabs from "@material-ui/core/Tabs"; -import Tab from "@material-ui/core/Tab"; - -// core components -import GridContainer from "components/Grid/GridContainer.js"; -import GridItem from "components/Grid/GridItem.js"; - -import styles from "assets/jss/material-kit-react/components/navPillsStyle.js"; - -const useStyles = makeStyles(styles); - -export default function NavPills(props) { - const [active, setActive] = React.useState(props.active); - const handleChange = (event, active) => { - setActive(active); - }; - const handleChangeIndex = (index) => { - setActive(index); - }; - const classes = useStyles(); - const { tabs, direction, color, horizontal, alignCenter } = props; - const flexContainerClasses = classNames({ - [classes.flexContainer]: true, - [classes.horizontalDisplay]: horizontal !== undefined, - }); - const tabButtons = ( - - {tabs.map((prop, key) => { - var icon = {}; - if (prop.tabIcon !== undefined) { - icon["icon"] = ; - } - const pillsClasses = classNames({ - [classes.pills]: true, - [classes.horizontalPills]: horizontal !== undefined, - [classes.pillsWithIcons]: prop.tabIcon !== undefined, - }); - return ( - - ); - })} - - ); - const tabContent = ( -
    - - {tabs.map((prop, key) => { - return ( -
    - {prop.tabContent} -
    - ); - })} -
    -
    - ); - return horizontal !== undefined ? ( - - {tabButtons} - {tabContent} - - ) : ( -
    - {tabButtons} - {tabContent} -
    - ); -} - -NavPills.defaultProps = { - active: 0, - color: "primary", -}; - -NavPills.propTypes = { - // index of the default active pill - active: PropTypes.number, - tabs: PropTypes.arrayOf( - PropTypes.shape({ - tabButton: PropTypes.string, - tabIcon: PropTypes.object, - tabContent: PropTypes.node, - }) - ).isRequired, - color: PropTypes.oneOf([ - "primary", - "warning", - "danger", - "success", - "info", - "rose", - ]), - direction: PropTypes.string, - horizontal: PropTypes.shape({ - tabsGrid: PropTypes.object, - contentGrid: PropTypes.object, - }), - alignCenter: PropTypes.bool, -}; diff --git a/client/src/components/Pagination/Pagination.js b/client/src/components/Pagination/Pagination.js deleted file mode 100755 index 728e720..0000000 --- a/client/src/components/Pagination/Pagination.js +++ /dev/null @@ -1,64 +0,0 @@ -import React from "react"; -// nodejs library to set properties for components -import PropTypes from "prop-types"; -// nodejs library that concatenates classes -import classNames from "classnames"; - -// @material-ui/core components -import { makeStyles } from "@material-ui/core/styles"; -import Button from "@material-ui/core/Button"; - -import styles from "assets/jss/material-kit-react/components/paginationStyle.js"; - -const useStyles = makeStyles(styles); - -export default function Pagination(props) { - const classes = useStyles(); - const { pages, color } = props; - return ( -
      - {pages.map((prop, key) => { - const paginationLink = classNames({ - [classes.paginationLink]: true, - [classes[color]]: prop.active, - [classes.disabled]: prop.disabled, - }); - return ( -
    • - {prop.onClick !== undefined ? ( - - ) : ( - - )} -
    • - ); - })} -
    - ); -} - -Pagination.defaultProps = { - color: "primary", -}; - -Pagination.propTypes = { - pages: PropTypes.arrayOf( - PropTypes.shape({ - active: PropTypes.bool, - disabled: PropTypes.bool, - text: PropTypes.oneOfType([ - PropTypes.number, - PropTypes.oneOf(["PREV", "NEXT", "..."]), - ]).isRequired, - onClick: PropTypes.func, - }) - ).isRequired, - color: PropTypes.oneOf(["primary", "info", "success", "warning", "danger"]), -}; diff --git a/client/src/components/Snackbar/SnackbarContent.js b/client/src/components/Snackbar/SnackbarContent.js deleted file mode 100755 index d1c4d45..0000000 --- a/client/src/components/Snackbar/SnackbarContent.js +++ /dev/null @@ -1,72 +0,0 @@ -import React from "react"; -// nodejs library to set properties for components -import PropTypes from "prop-types"; -// @material-ui/core components -import { makeStyles } from "@material-ui/core/styles"; -import Snack from "@material-ui/core/SnackbarContent"; -import IconButton from "@material-ui/core/IconButton"; -import Icon from "@material-ui/core/Icon"; -// @material-ui/icons -import Close from "@material-ui/icons/Close"; -// core components - -import styles from "assets/jss/material-kit-react/components/snackbarContentStyle.js"; - -const useStyles = makeStyles(styles); - -export default function SnackbarContent(props) { - const { message, color, close, icon } = props; - const classes = useStyles(); - var action = []; - const closeAlert = () => { - setAlert(null); - }; - if (close !== undefined) { - action = [ - - - , - ]; - } - let snackIcon = null; - switch (typeof icon) { - case "object": - snackIcon = ; - break; - case "string": - snackIcon = {props.icon}; - break; - default: - snackIcon = null; - break; - } - const [alert, setAlert] = React.useState( - - {snackIcon} - {message} - {close !== undefined ? action : null} -
    - } - classes={{ - root: classes.root + " " + classes[color], - message: classes.message + " " + classes.container, - }} - /> - ); - return alert; -} - -SnackbarContent.propTypes = { - message: PropTypes.node.isRequired, - color: PropTypes.oneOf(["info", "success", "warning", "danger", "primary"]), - close: PropTypes.bool, - icon: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), -}; diff --git a/client/src/components/Typography/Danger.js b/client/src/components/Typography/Danger.js deleted file mode 100755 index ec063e1..0000000 --- a/client/src/components/Typography/Danger.js +++ /dev/null @@ -1,23 +0,0 @@ -import React from "react"; -// nodejs library to set properties for components -import PropTypes from "prop-types"; -// @material-ui/core components -import { makeStyles } from "@material-ui/core/styles"; -// core components -import styles from "assets/jss/material-kit-react/components/typographyStyle.js"; - -const useStyles = makeStyles(styles); - -export default function Danger(props) { - const classes = useStyles(); - const { children } = props; - return ( -
    - {children} -
    - ); -} - -Danger.propTypes = { - children: PropTypes.node, -}; diff --git a/client/src/components/Typography/Info.js b/client/src/components/Typography/Info.js deleted file mode 100755 index bafaf7d..0000000 --- a/client/src/components/Typography/Info.js +++ /dev/null @@ -1,23 +0,0 @@ -import React from "react"; -// nodejs library to set properties for components -import PropTypes from "prop-types"; -// @material-ui/core components -import { makeStyles } from "@material-ui/core/styles"; -// core components -import styles from "assets/jss/material-kit-react/components/typographyStyle.js"; - -const useStyles = makeStyles(styles); - -export default function Info(props) { - const classes = useStyles(); - const { children } = props; - return ( -
    - {children} -
    - ); -} - -Info.propTypes = { - children: PropTypes.node, -}; diff --git a/client/src/components/Typography/Muted.js b/client/src/components/Typography/Muted.js deleted file mode 100755 index 2458a81..0000000 --- a/client/src/components/Typography/Muted.js +++ /dev/null @@ -1,23 +0,0 @@ -import React from "react"; -// nodejs library to set properties for components -import PropTypes from "prop-types"; -// @material-ui/core components -import { makeStyles } from "@material-ui/core/styles"; -// core components -import styles from "assets/jss/material-kit-react/components/typographyStyle.js"; - -const useStyles = makeStyles(styles); - -export default function Muted(props) { - const classes = useStyles(); - const { children } = props; - return ( -
    - {children} -
    - ); -} - -Muted.propTypes = { - children: PropTypes.node, -}; diff --git a/client/src/components/Typography/Primary.js b/client/src/components/Typography/Primary.js deleted file mode 100755 index 6564c9a..0000000 --- a/client/src/components/Typography/Primary.js +++ /dev/null @@ -1,23 +0,0 @@ -import React from "react"; -// nodejs library to set properties for components -import PropTypes from "prop-types"; -// @material-ui/core components -import { makeStyles } from "@material-ui/core/styles"; -// core components -import styles from "assets/jss/material-kit-react/components/typographyStyle.js"; - -const useStyles = makeStyles(styles); - -export default function Primary(props) { - const classes = useStyles(); - const { children } = props; - return ( -
    - {children} -
    - ); -} - -Primary.propTypes = { - children: PropTypes.node, -}; diff --git a/client/src/components/Typography/Quote.js b/client/src/components/Typography/Quote.js deleted file mode 100755 index b8f087e..0000000 --- a/client/src/components/Typography/Quote.js +++ /dev/null @@ -1,25 +0,0 @@ -import React from "react"; -// nodejs library to set properties for components -import PropTypes from "prop-types"; -// @material-ui/core components -import { makeStyles } from "@material-ui/core/styles"; -// core components -import styles from "assets/jss/material-kit-react/components/typographyStyle.js"; - -const useStyles = makeStyles(styles); - -export default function Quote(props) { - const { text, author } = props; - const classes = useStyles(); - return ( -
    -

    {text}

    - {author} -
    - ); -} - -Quote.propTypes = { - text: PropTypes.node, - author: PropTypes.node, -}; diff --git a/client/src/components/Typography/Small.js b/client/src/components/Typography/Small.js deleted file mode 100755 index 54101ac..0000000 --- a/client/src/components/Typography/Small.js +++ /dev/null @@ -1,23 +0,0 @@ -import React from "react"; -// nodejs library to set properties for components -import PropTypes from "prop-types"; -// @material-ui/core components -import { makeStyles } from "@material-ui/core/styles"; -// core components -import styles from "assets/jss/material-kit-react/components/typographyStyle.js"; - -const useStyles = makeStyles(styles); - -export default function Small(props) { - const classes = useStyles(); - const { children } = props; - return ( -
    - {children} -
    - ); -} - -Small.propTypes = { - children: PropTypes.node, -}; diff --git a/client/src/components/Typography/Success.js b/client/src/components/Typography/Success.js deleted file mode 100755 index 2ae7c47..0000000 --- a/client/src/components/Typography/Success.js +++ /dev/null @@ -1,23 +0,0 @@ -import React from "react"; -// nodejs library to set properties for components -import PropTypes from "prop-types"; -// @material-ui/core components -import { makeStyles } from "@material-ui/core/styles"; -// core components -import styles from "assets/jss/material-kit-react/components/typographyStyle.js"; - -const useStyles = makeStyles(styles); - -export default function Success(props) { - const classes = useStyles(); - const { children } = props; - return ( -
    - {children} -
    - ); -} - -Success.propTypes = { - children: PropTypes.node, -}; diff --git a/client/src/components/Typography/Warning.js b/client/src/components/Typography/Warning.js deleted file mode 100755 index f7dc6d3..0000000 --- a/client/src/components/Typography/Warning.js +++ /dev/null @@ -1,23 +0,0 @@ -import React from "react"; -// nodejs library to set properties for components -import PropTypes from "prop-types"; -// @material-ui/core components -import { makeStyles } from "@material-ui/core/styles"; -// core components -import styles from "assets/jss/material-kit-react/components/typographyStyle.js"; - -const useStyles = makeStyles(styles); - -export default function Warning(props) { - const classes = useStyles(); - const { children } = props; - return ( -
    - {children} -
    - ); -} - -Warning.propTypes = { - children: PropTypes.node, -}; From 5b4c2ea7dc2efe661ed5d69132327f2db45b7210 Mon Sep 17 00:00:00 2001 From: "Yash Pandey (YP)" Date: Sun, 16 May 2021 01:49:44 +0530 Subject: [PATCH 6/6] =?UTF-8?q?Added=20Google=20OAuth=20=F0=9F=94=91=20=20?= =?UTF-8?q?(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added Google OAuth Signed-off-by: Yash Pandey (YP) * cleared off console.logs * Handled User navigation --- client/.env.development | 1 + client/package.json | 1 + .../Pages/CreateProvider/CreateProvider.js | 16 +- .../Pages/LandingPage/LandingPage.js | 168 +----------------- .../Components/Pages/LoginPage/Login.js | 91 ++++++++-- .../OrganisationPage/OrganisationPage.js | 3 - .../RegistrationPage/RegistrationPage.js | 86 +++++++-- client/yarn.lock | 8 + server/src/index.ts | 4 +- server/src/resolvers/User.ts | 12 ++ 10 files changed, 184 insertions(+), 206 deletions(-) diff --git a/client/.env.development b/client/.env.development index b23305d..ab28adf 100644 --- a/client/.env.development +++ b/client/.env.development @@ -1,2 +1,3 @@ REACT_APP_GOOGLE_MAPS_API_KEY=AIzaSyCxttBHhvoDHLXbUgnMtjO3OVDw46iFSQw REACT_APP_SERVER_URL=http://localhost:4000/graphql +REACT_APP_GOOGLE_OAUTH=962299963873-vfn6gg5ig0ilop0v70fgi7bonovplopr.apps.googleusercontent.com diff --git a/client/package.json b/client/package.json index d98e8d6..a871b07 100644 --- a/client/package.json +++ b/client/package.json @@ -27,6 +27,7 @@ "react": "^17.0.2", "react-datetime": "2.16.3", "react-dom": "^17.0.2", + "react-google-login": "^5.2.2", "react-router-dom": "5.2.0", "react-scripts": "4.0.3", "react-slick": "0.26.1", diff --git a/client/src/CoviSource/Components/Pages/CreateProvider/CreateProvider.js b/client/src/CoviSource/Components/Pages/CreateProvider/CreateProvider.js index ad9b2bb..9703981 100644 --- a/client/src/CoviSource/Components/Pages/CreateProvider/CreateProvider.js +++ b/client/src/CoviSource/Components/Pages/CreateProvider/CreateProvider.js @@ -4,7 +4,6 @@ import { makeStyles } from "@material-ui/core/styles"; import InputAdornment from "@material-ui/core/InputAdornment"; // @material-ui/icons import LocationCity from "@material-ui/icons/LocationCity"; -// import People from "@material-ui/icons/People"; import Hospital from "@material-ui/icons/LocalHospital"; // core components import GridContainer from "components/Grid/GridContainer.js"; @@ -23,10 +22,10 @@ import "./CreateProvider.scss"; import image from "assets/img/bg7.jpg"; import CreateContact from "./CreateContact"; -import { useMutation } from "@apollo/client"; +import { useMutation, useQuery } from "@apollo/client"; import { CREATE_PROVIDER } from "CoviSource/graphql/mutations/Provider/CreateProvider"; import CreateResource from "./CreateResource"; -// import Map from "CoviSource/Components/UtilityComponents/Map/Map"; +import { GET_USER } from "CoviSource/graphql/queries/User/GetUser"; const useStyles = makeStyles(styles); @@ -40,6 +39,16 @@ const formReducer = (state, event) => { export default function CreateProvider(props) { const [formData, setFormData] = useReducer(formReducer, {}); const [resourceData, setresourceData] = useState({}); + const { + data: queryData, + error: queryError, + loading: queryLoading, + } = useQuery(GET_USER); + if (queryLoading) return <>Loading...; + if (queryError) return <>Error; + if (queryData.me === null) { + window.location.assign("/login"); + } const [cardAnimaton, setCardAnimation] = useState("cardHidden"); const [numberContact, setNumberContact] = useState(0); const [createProvider, { loading, data, error }] = useMutation( @@ -62,7 +71,6 @@ export default function CreateProvider(props) { name: event.target.name, value: event.target.value, }); - console.log(formData); }; const handleSubmit = (event) => { event.preventDefault(); diff --git a/client/src/CoviSource/Components/Pages/LandingPage/LandingPage.js b/client/src/CoviSource/Components/Pages/LandingPage/LandingPage.js index 517606c..f22365a 100644 --- a/client/src/CoviSource/Components/Pages/LandingPage/LandingPage.js +++ b/client/src/CoviSource/Components/Pages/LandingPage/LandingPage.js @@ -6,11 +6,8 @@ import classNames from "classnames"; // core components import Header from "CoviSource/Components/UtilityComponents/Header/Header"; - -// import Footer from "components/Footer/Footer.js"; import GridContainer from "components/Grid/GridContainer.js"; import GridItem from "components/Grid/GridItem.js"; -// import Button from "components/CustomButtons/Button.js"; import Parallax from "components/Parallax/Parallax.js"; // sections for the page @@ -34,174 +31,11 @@ export default function LandingPage(props) { const { loading, data, error } = useQuery(GET_ALL_PROVIDERS); if (loading) return <>Loading...; if (error) return <>Error; - if (data) console.log(data); - - // const [data, setData] = useState([ - // { - // username: "someUsername", - // resourceProviderName: "Resource Provider Name", - // availability: "UNUPDATED", - // resources: [ - // { - // resource: "Oxygen refilling", - // quantity: 32, - // updated: "06:00 PM, 27 APRIL", - // }, - // { - // resource: "Hospital Beds", - // quantity: 23, - // updated: "06:00 PM, 27 APRIL", - // }, - // { - // resource: "Remdesivir Vials", - // quantity: 65, - // updated: "06:00 PM, 27 APRIL", - // }, - // ], - // address: "Provider Address", - // contactPersonName: "Contact Person's Name", - // phoneNumber: "9821095754", - // serviceName: "Service Provided", - // }, - // { - // username: "anotherUsername", - // resourceProviderName: "Free oxygen seva vijaya nagar", - // availability: "AVAILABLE", - // resources: [ - // { - // resource: "Oxygen refilling", - // quantity: 32, - // updated: "06:00 PM, 27 APRIL", - // }, - // { - // resource: "Hospital Beds", - // quantity: 23, - // updated: "06:00 PM, 27 APRIL", - // }, - // { - // resource: "Remdesivir Vials", - // quantity: 65, - // updated: "06:00 PM, 27 APRIL", - // }, - // ], - // address: "Free oxygen seva, near gurudwara, delhi", - // contactPersonName: "Jaspal Singh", - // phoneNumber: "9821095754", - // serviceName: "Oxygen refilling", - // }, - // { - // username: "anotherUsername2", - // resourceProviderName: "Apex Hospital", - // availability: "UNAVAILABLE", - // resources: [ - // { - // resource: "Oxygen Cylinders", - // quantity: 0, - // updated: "06:00 PM, 27 APRIL", - // }, - // { - // resource: "Hospital Beds", - // quantity: 0, - // updated: "06:00 PM, 27 APRIL", - // }, - // { - // resource: "Remdesivir Vials", - // quantity: 0, - // updated: "06:00 PM, 27 APRIL", - // }, - // ], - // address: "Apex Hospital, Kalyan West, Mumbai", - // contactPersonName: "Dr. D P Goel", - // phoneNumber: "9789965234", - // serviceName: "Hospital", - // }, - // ]); const onSearchButtonClick = function () { console.log("Search Button Clicked"); - - // a fetch operation will be made here which will then update the state -> data; - // setData([ - // { - // username: "someUsername", - // resourceProviderName: "Resource Provider Name", - // availability: "UNUPDATED", - // resources: [ - // { - // resource: "Oxygen refilling", - // quantity: 32, - // updated: "06:00 PM, 27 APRIL", - // }, - // { - // resource: "Hospital Beds", - // quantity: 23, - // updated: "06:00 PM, 27 APRIL", - // }, - // { - // resource: "Remdesivir Vials", - // quantity: 65, - // updated: "06:00 PM, 27 APRIL", - // }, - // ], - // address: "Provider Address", - // contactPersonName: "Contact Person's Name", - // phoneNumber: "9821095754", - // serviceName: "Service Provided", - // }, - // { - // username: "anotherUsername", - // resourceProviderName: "Free oxygen seva vijaya nagar", - // availability: "AVAILABLE", - // resources: [ - // { - // resource: "Oxygen refilling", - // quantity: 32, - // updated: "06:00 PM, 27 APRIL", - // }, - // { - // resource: "Hospital Beds", - // quantity: 23, - // updated: "06:00 PM, 27 APRIL", - // }, - // { - // resource: "Remdesivir Vials", - // quantity: 65, - // updated: "06:00 PM, 27 APRIL", - // }, - // ], - // address: "Free oxygen seva, near gurudwara, delhi", - // contactPersonName: "Jaspal Singh", - // phoneNumber: "9821095754", - // serviceName: "Oxygen refilling", - // }, - // { - // username: "anotherUsername2", - // resourceProviderName: "Apex Hospital", - // availability: "UNAVAILABLE", - // resources: [ - // { - // resource: "Oxygen Cylinders", - // quantity: 0, - // updated: "06:00 PM, 27 APRIL", - // }, - // { - // resource: "Hospital Beds", - // quantity: 0, - // updated: "06:00 PM, 27 APRIL", - // }, - // { - // resource: "Remdesivir Vials", - // quantity: 0, - // updated: "06:00 PM, 27 APRIL", - // }, - // ], - // address: "Apex Hospital, Kalyan West, Mumbai", - // contactPersonName: "Dr. D P Goel", - // phoneNumber: "9789965234", - // serviceName: "Hospital", - // }, - // ]); }; + const renderResourcesCards = () => { return (
    Loading...; + if (queryError) return <>Error; + if (queryData.me) { + window.location.assign("/"); + } const handleChange = (event) => { setFormData({ @@ -62,14 +75,17 @@ export default function Login(props) { }, }, }); - if (!loading) { - if (data) { - if (data.login.errors) { - alert(data.login.errors[0].message); - } else { - alert("Logged In!"); - window.location.assign("/"); - } + if (loading); + if (error) { + alert(error); + return; + } + if (data) { + if (data.login.errors) { + alert(data.login.errors[0].message); + } else { + alert("Logged In!"); + window.location.assign("/"); } } }; @@ -79,6 +95,33 @@ export default function Login(props) { color: "white", }; + const googleSuccess = async (res) => { + await login({ + variables: { + input: { + email: res.profileObj.email, + password: res.qc.login_hint, + }, + }, + }); + if (loading); + if (error) { + alert(error); + return; + } + if (data) { + if (data.login.errors) { + alert(data.login.errors[0].message); + } else { + alert("Logged In!"); + window.location.assign("/"); + } + } + }; + const googleFailure = () => { + alert("Google Signin was unsucessfull."); + }; + return (

    Login

    - + ( + + )} + onSuccess={googleSuccess} + onFailure={googleFailure} + cookiePolicy="single_host_origin" + />

    Or Be Classical

    diff --git a/client/src/CoviSource/Components/Pages/OrganisationPage/OrganisationPage.js b/client/src/CoviSource/Components/Pages/OrganisationPage/OrganisationPage.js index 3435998..291326e 100644 --- a/client/src/CoviSource/Components/Pages/OrganisationPage/OrganisationPage.js +++ b/client/src/CoviSource/Components/Pages/OrganisationPage/OrganisationPage.js @@ -31,9 +31,6 @@ export default function OrganisationPage() { console.log(error); return <>Error; } - if (data) { - console.log(data); - } const getBannerClass = function () { return "banner banner" + status[data.availability]; diff --git a/client/src/CoviSource/Components/Pages/RegistrationPage/RegistrationPage.js b/client/src/CoviSource/Components/Pages/RegistrationPage/RegistrationPage.js index 51d8e57..2c4151b 100644 --- a/client/src/CoviSource/Components/Pages/RegistrationPage/RegistrationPage.js +++ b/client/src/CoviSource/Components/Pages/RegistrationPage/RegistrationPage.js @@ -5,7 +5,6 @@ import InputAdornment from "@material-ui/core/InputAdornment"; // @material-ui/icons import Email from "@material-ui/icons/Email"; import People from "@material-ui/icons/People"; -// import Hospital from "@material-ui/icons/LocalHospital"; import Password from "@material-ui/icons/Lock"; // core components import GridContainer from "components/Grid/GridContainer.js"; @@ -25,11 +24,14 @@ import "./RegistrationPage.scss"; import image from "assets/img/bg2.jpg"; import Phone from "@material-ui/icons/Phone"; -import { useMutation } from "@apollo/client"; +import { useMutation, useQuery } from "@apollo/client"; import { ADD_USER } from "CoviSource/graphql/mutations/User/AddUser"; +import { GET_USER } from "CoviSource/graphql/queries/User/GetUser"; +import GoogleLogin from "react-google-login"; const useStyles = makeStyles(styles); +// To map each entry field to its value const formReducer = (state, event) => { return { ...state, @@ -46,6 +48,19 @@ export default function RegistrationPage(props) { const classes = useStyles(); const { ...rest } = props; + const { + data: queryData, + error: queryError, + loading: queryLoading, + } = useQuery(GET_USER); + + if (queryLoading) return <>Loading...; + if (queryError) return <>Error; + if (queryData.me) { + window.location.assign("/"); + } + + // addUser mutation const [addUser, { data, loading, error }] = useMutation(ADD_USER); const scrollChangeData = { @@ -53,6 +68,7 @@ export default function RegistrationPage(props) { color: "white", }; + // Handling change for individual entries of form data const handleChange = (event) => { setFormData({ name: event.target.name, @@ -60,6 +76,7 @@ export default function RegistrationPage(props) { }); }; + // Submit function to call the mutation const handleSubmit = (event) => { event.preventDefault(); addUser({ @@ -72,6 +89,38 @@ export default function RegistrationPage(props) { }, }, }); + // If loading then do nothing + if (loading); + // If error, alert the user + if (error) { + alert(error); + } + if (data) { + // If backend sends an error, alert the user + if (data.register.errors) { + alert(data.register.errors[0].message); + } + // Success + if (data.register.user) { + alert("Registration sucessful!"); + // Send to homepage + window.location.assign("/"); + } + } + }; + + // On obtaining valid Google OAuth tokens + const googleSuccess = async (res) => { + await addUser({ + variables: { + input: { + name: `${res.profileObj.givenName} ${res.profileObj.familyName}`, + email: res.profileObj.email, + phoneNumber: `${res.profileObj.googleId}`.substring(0, 10), + password: res.qc.login_hint, + }, + }, + }); if (loading); if (error) { alert(error); @@ -87,6 +136,11 @@ export default function RegistrationPage(props) { } }; + // On invalid Google OAuth + const googleFailure = () => { + alert("Google Signup was unsucessfull"); + }; + return (

    Register Yourself

    - + ( + + )} + onSuccess={googleSuccess} + onFailure={googleFailure} + cookiePolicy="single_host_origin" + />

    Or Be Classical

    diff --git a/client/yarn.lock b/client/yarn.lock index dc67243..8655258 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -10839,6 +10839,14 @@ react-event-listener@^0.6.0, react-event-listener@^0.6.2: prop-types "^15.6.0" warning "^4.0.1" +react-google-login@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/react-google-login/-/react-google-login-5.2.2.tgz#a20b46440c6c1610175ef75baf427118ff0e9859" + integrity sha512-JUngfvaSMcOuV0lFff7+SzJ2qviuNMQdqlsDJkUM145xkGPVIfqWXq9Ui+2Dr6jdJWH5KYdynz9+4CzKjI5u6g== + dependencies: + "@types/react" "*" + prop-types "^15.6.0" + react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" diff --git a/server/src/index.ts b/server/src/index.ts index 89d5b26..3ea63db 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -44,8 +44,8 @@ const main = async () => { maxAge: COOKIE_MAX_AGE, httpOnly: true, secure: __prod__, - sameSite: 'lax', - domain: __prod__ ? '.emperoryp.live' : undefined, + sameSite: 'lax', // CSRF + domain: __prod__ ? '.covisource.tech' : undefined, }, saveUninitialized: false, secret: process.env.SESSION_SECRET, diff --git a/server/src/resolvers/User.ts b/server/src/resolvers/User.ts index af7fe21..abc8967 100644 --- a/server/src/resolvers/User.ts +++ b/server/src/resolvers/User.ts @@ -67,6 +67,18 @@ export class UserResolver { return User.find(); } + @Mutation(() => Boolean) + async deleteUser( + @Arg('id') id: number, + ): Promise { + try { + await User.delete(id); + return true; + } catch (err) { + return false; + } + } + @Mutation(() => UserResponse) async register( @Arg('input') input: UserRegisterInput,