Skip to content
This repository was archived by the owner on Feb 2, 2023. It is now read-only.

Login and signup frontend integration #155

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions notes.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
~/W/s/notowork   feature/start-whole-app
-> Zmiany
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@
"lib": "lib"
},
"scripts": {
"start": "run-p server client",
"start": "run-p server:start client:start",
"test": "run-p server:test client:test",
"build": "lerna run build",
"server": "lerna run start --scope @notowork/server",
"client": "lerna run start --scope @notowork/client",
"server:start": "lerna run start --scope @notowork/server",
"client:start": "lerna run start --scope @notowork/client",
"server:test": "lerna run test --scope @notowork/server",
"client:test": "lerna run test --scope @notowork/client",
"init": "npm run bootstrap",
"bootstrap": "lerna bootstrap",
"lerna": "lerna",
Expand Down
106 changes: 60 additions & 46 deletions packages/client/src/auth/Provider.tsx
Original file line number Diff line number Diff line change
@@ -1,56 +1,70 @@
import { Status } from '@notowork/models/interfaces'
import React, { Component } from 'react'
import context, { defaultValue, SignIn, SignOut, Value } from './context'
import { signIn } from './service'

export default class Provider extends Component<{}, ProviderState> {
public constructor(props: {}) {
super(props)

this.state = {
...defaultValue,
signIn: this.signIn,
signOut: this.signOut,
import gql from 'graphql-tag'
import React, { FC, useState } from 'react'
import { useMutation } from 'react-apollo-hooks'
import context, { AuthContextValue, SignIn, SignOut } from './context'

const SIGN_IN = gql`
mutation($email: String!, $password: String!) {
login(email: $email, password: $password) {
token
user {
id
name
email
roles
}
}
}
`

public render() {
return (
<context.Provider value={this.state}>
{this.props.children}
</context.Provider>
)
}
const Provider: FC = ({ children }) => {
const [signedIn, setSignedIn] = useState(false)
const [status, setStatus] = useState()
const [user, setUser] = useState(null)
const [error, setError] = useState<string | undefined>()

const [execSignIn] = useMutation(SIGN_IN)

const signIn: SignIn = async (email, password) => {
setStatus(Status.Pending)

private signIn: SignIn = (email, password) => {
return new Promise(resolve => {
this.setState(
{
status: Status.Pending,
},
async () => {
const maybeUser = await signIn(email, password)

this.setState(
{
signedIn: Boolean(maybeUser),
status: maybeUser ? Status.Success : Status.Failure,
user: maybeUser,
},
() => resolve(),
)
},
)
})
try {
const { data } = await execSignIn({ variables: { email, password } })
const login = (data as any).login

setUser(login.user)
setStatus(login.user ? Status.Success : Status.Failure)
setSignedIn(true)
} catch (e) {
setError(e.message)
setStatus(undefined)
setUser(null)
setSignedIn(false)
}
}

private signOut: SignOut = () => {
this.setState({
signedIn: false,
status: undefined,
user: null,
})
const signOut: SignOut = () => {
setSignedIn(false)
setStatus(undefined)
setUser(null)
}

return (
<context.Provider
value={{
signedIn,
status,
user,
signIn,
signOut,
error,
}}
>
{children}
</context.Provider>
)
}

export type ProviderState = Value
export type ProviderState = AuthContextValue
export default Provider
10 changes: 5 additions & 5 deletions packages/client/src/auth/context.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
import { Status, User } from '@notowork/models/interfaces'
import { Context, createContext } from 'react'

export const defaultValue: Value = {
export const defaultValue: AuthContextValue = {
signIn: () => new Promise<void>(resolve => resolve()),
signOut: () => undefined,
signedIn: false,
status: undefined,
user: null,
}

const context: Context<Value> = createContext(defaultValue)
const context: Context<AuthContextValue> = createContext(defaultValue)

export default context

export type SignIn = (email: string, password: string) => Promise<void>
export type SignOut = () => void
export type MaybeUser = User | null

export interface Value {
export interface AuthContextValue {
signedIn: boolean
status: Status | undefined
user: MaybeUser
user: User | null
signIn: SignIn
signOut: SignOut
error?: string
}
9 changes: 4 additions & 5 deletions packages/client/src/auth/withAuth.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
import React, { ComponentType } from 'react'
import { Subtract } from 'utility-types'
import context, { Value } from './context'
import context, { AuthContextValue } from './context'

const withAuth = <P extends WithAuth>(Component: ComponentType<P>) => {
return class AuthedComponent extends React.Component<Subtract<P, WithAuth>> {
public render() {
return <context.Consumer>{this.renderComponent}</context.Consumer>
}

public renderComponent = (authProps: Value) => {
const props = { auth: authProps, ...this.props }
return <Component {...props as any} />
public renderComponent = (authProps: AuthContextValue) => {
return <Component {...{ auth: authProps, ...this.props } as any} />
}
}
}

export default withAuth

export interface WithAuth {
auth: Value
auth: AuthContextValue
}
Loading