@apollo/react-hooks#useLazyQuery JavaScript Examples

The following examples show how to use @apollo/react-hooks#useLazyQuery. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: View.jsx    From saasgear with MIT License 6 votes vote down vote up
ViewDocument = () => {
  const match = useRouteMatch();
  const documentId = parseInt(match.params.id, 10);
  const [fetchDocumentDetail, { data: documentData, loading }] = useLazyQuery(
    getDocumentDetailQuery,
  );

  useEffect(() => {
    if (documentId) {
      fetchDocumentDetail({ variables: { id: documentId } });
    }
  }, [documentId]);

  function createMarkup(html) {
    return {
      __html: DOMPurify.sanitize(html),
    };
  }

  return (
    <ContentDocument>
      {loading && <div>Loading...</div>}

      {!loading && documentData?.getDocumentDetail && (
        <>
          <TitlePage>{documentData.getDocumentDetail.name}</TitlePage>
          <ContentPage>
            <div
              dangerouslySetInnerHTML={createMarkup(
                documentData.getDocumentDetail.body,
              )}
            ></div>
          </ContentPage>
        </>
      )}
    </ContentDocument>
  );
}
Example #2
Source File: SubCategoryPage.jsx    From trashpanda-fe with MIT License 5 votes vote down vote up
SubCategoryPage = () => {
  const { subCategoryId } = useParams();
  const [currentData, setCurrentData] = useState(null);
  const history = useHistory();
  const [materialList, setMaterialList] = useState([]);
  const [getMaterials, materialInfo] = useLazyQuery(GET_MATERIALS);
  useEffect(() => {
    const foundData = data.find(dataObj => dataObj.id == subCategoryId);
    setCurrentData(foundData);
  }, [subCategoryId]);

  useEffect(() => {
    if (currentData)
      getMaterials({
        variables: {
          idList: currentData.materialIds
        }
      });
  }, [currentData]);

  useEffect(() => {
    if (materialInfo.data && materialInfo.data.getMaterialByIDS) {
      setMaterialList(materialInfo.data.getMaterialByIDS);
    }
  }, [materialInfo.data]);

  if (materialInfo.loading) return <Spinner />;

  return (
    <Root>
      <Title>{currentData && currentData.title}</Title>
      <Blurb>
        You can find which type of plastic your item is by looking for the
        numbered stamp, usually located near the bottom.
      </Blurb>
      <Container>
        {materialList &&
          materialList.map((material, key) => (
            <GridCard
              svg={getPlasticTypeImage(material.description)}
              name={getPlasticName(material.description)}
              key={key}
              onClick={() => history.push(`/material/${material.material_id}`)}
            />
          ))}
      </Container>
    </Root>
  );
}
Example #3
Source File: index.js    From monorepo-starter with MIT License 5 votes vote down vote up
function HomePage() {
  const { data: authorList, initialLoading, initialError } = useQuery(
    getAuthors
  );
  const [getAuthor, { loading, error, data }] = useLazyQuery(getAuthorDetails);

  if (!authorList) {
    return null;
  }

  return (
    <div
      style={{
        textAlign: "center"
      }}
    >
      <Preamble />
      <h2>
        As a treat, we've got some cool author recs Click on an author to see
        some of their books:
      </h2>
      <div>
        {authorList.authors.map(({ name }) => (
          <Button
            key={name}
            isSelected={data && data.author.name === name}
            onClick={() => {
              getAuthor({ variables: { name } });
            }}
          >
            {name}
          </Button>
        ))}
      </div>
      <div style={{ marginTop: "24px" }}>
        {data ? (
          <div>
            <ul>
              {data.author.books.map(({ title }) => (
                <li style={{ listStyle: "none" }} key={title}>
                  {title}
                </li>
              ))}
            </ul>
          </div>
        ) : null}
      </div>
    </div>
  );
}
Example #4
Source File: PokemonDetail.js    From react-sample-projects with MIT License 5 votes vote down vote up
PokemonDetail = () => {
  const dispatch = useDispatch();
  const pokemonDetail = useSelector((state) => state.pokemonDetail) || {};
  const britishNumberFormatter = new Intl.NumberFormat('en-GB');
  const params = useParams();
  const navigate = useNavigate();
  const { state } = useLocation();

  const [getPokemonDetails, { loading, error, data }] = useLazyQuery(
    GET_POKEMON_DETAILS,
    {
      variables: { id: params.id },
    },
  );

  useEffect(() => {
    if (state && state?.pokemon) {
      dispatch({ type: 'SET_POKEMON_DETAILS', payload: state.pokemon });
    } else if (params.id) {
      getPokemonDetails();
    }
    return () => {};
  }, [dispatch, getPokemonDetails, state, params.id]);

  const goBack = () => {
    navigate(-1);
  };

  if (loading) return <p>Loading ...</p>;
  if (error) return <pre>{error}</pre>;

  if (data) {
    dispatch({ type: 'SET_POKEMON_DETAILS', payload: data.pokemon });
  }

  return (
    <div className="pokemondetail">
      <button onClick={goBack}> Back</button>
      <div className="pokemon">
        <div className="pokemon__name">
          <h1>{pokemonDetail.name}</h1>
        </div>
        <h4>Classification: {pokemonDetail.classification}</h4>
        <div className="pokemon__meta">
          <span>
            maxHP: {britishNumberFormatter.format(pokemonDetail.maxHP)} &nbsp;
          </span>
          <span>
            maxCP: {britishNumberFormatter.format(pokemonDetail.maxCP)}
          </span>
        </div>
        <br />
        <div className="pokemon__image">
          <img src={pokemonDetail.image} alt={pokemonDetail.name} />
        </div>
        <h1>Resistant</h1>
        <div className="pokemon__attacks">
          {pokemonDetail?.resistant?.map((resistant, index) => (
            <span key={index}>{resistant} </span>
          ))}
        </div>
        <h1>Weaknesses</h1>
        <div className="pokemon__attacks">
          {pokemonDetail?.weaknesses?.join(', ')}
        </div>
        <h1>Attacks</h1>
        <div className="pokemon__attacks">
          <p>{pokemonDetail?.attacks?.fast.map((f) => f.name).join(', ')}</p>
          <p>{pokemonDetail?.attacks?.special.map((s) => s.name).join(', ')}</p>
        </div>
      </div>
    </div>
  );
}
Example #5
Source File: ProfilePage.js    From lifebank with MIT License 4 votes vote down vote up
ProfilePage = () => {
  const { t } = useTranslation('translations')
  const classes = useStyles()
  const history = useHistory()
  const [, { logout }] = useUser()
  const [openAlert, setOpenAlert] = useState(false)
  const [messegaAlert, setMessegaAlert] = useState("")
  const [severity, setSeverity] = useState("success")
  const [lastConsentChange, setLastConsentChange] = useState()
  const [currentUser] = useUser()
  const handleOpenAlert = () => {
    setOpenAlert(!openAlert)
  }
  const [
    loadProfile,
    { client, error: errorProfile, loading, data: { profile: { profile } = {} } = {} }
  ] = useLazyQuery(PROFILE_QUERY, { fetchPolicy: 'network-only' })
  const [
    revokeConsent,
    {
      error: errorRevokeConsent,
      loading: revokeConsentLoading,
      data: { revoke_consent: revokeConsentResult } = {}
    }
  ] = useMutation(REVOKE_CONSENT_MUTATION)
  const [
    grantConsent,
    {
      error: errorGrantConsent,
      loading: grantConsentLoading,
      data: { grant_consent: grantConsentResult } = {}
    }
  ] = useMutation(GRANT_CONSENT_MUTATION)

  const handleConsentChange = () => {
    setLastConsentChange(profile?.consent ? 'revoke' : 'grant')
    profile?.consent ? revokeConsent() : grantConsent()
  }

  useEffect(() => {
    if (!currentUser) {
      client && client.resetStore()
      history.replace('/')
      return
    }

    loadProfile()
  }, [currentUser, history, client, loadProfile])

  useEffect(() => {
    if (
      !lastConsentChange ||
      (lastConsentChange === 'grant' && !grantConsentResult) ||
      (lastConsentChange === 'revoke' && !revokeConsentResult)
    ) {
      return
    }

    if (lastConsentChange === 'grant') {
      setSeverity("success")
      setMessegaAlert(t('signup.consentGranted'))
      handleOpenAlert()
    } else {
      setSeverity("success")
      setMessegaAlert(t('signup.consentRevoked'))
      handleOpenAlert()
    }

    loadProfile()
  }, [
    handleOpenAlert,
    t,
    loadProfile,
    grantConsentResult,
    revokeConsentResult,
    lastConsentChange,
    classes
  ])

  useEffect(() => {
    if (profile && !profile.consent) {
      setSeverity("error")
      setMessegaAlert(t('signup.noConsentNoEdit'))
      handleOpenAlert()
    }
  }, [t, setSeverity, setMessegaAlert, profile])

  useEffect(() => {
    if (errorProfile) {
      if (errorProfile.message === 'GraphQL error: Could not verify JWT: JWTExpired') {
        logout()
        history.push('/')
      } else history.push('/internal-error')
    }

  }, [logout, history, errorProfile])

  useEffect(() => {
    if (errorRevokeConsent) {
      if (errorRevokeConsent.message === 'GraphQL error: Could not verify JWT: JWTExpired') {
        logout()
        history.push('/')
      } else {
        setSeverity("error")
        setMessegaAlert(t('signup.consentError'))
        handleOpenAlert()
      }
    }

  }, [t, logout, history, errorRevokeConsent])

  useEffect(() => {
    if (errorGrantConsent) {
      if (errorGrantConsent.message === 'GraphQL error: Could not verify JWT: JWTExpired') {
        logout()
        history.push('/')
      } else {
        setSeverity("error")
        setMessegaAlert(t('signup.consentError'))
        handleOpenAlert()
      }
    }
  }, [t, logout, history, errorGrantConsent])

  return (
    <Box className={classes.contentBody}>
      <Snackbar open={openAlert} autoHideDuration={6000} onClose={handleOpenAlert}>
        <Alert onClose={handleOpenAlert} severity={severity}>
          {messegaAlert}
        </Alert>
      </Snackbar>
      {loading && <CircularProgress />}
      {!loading && currentUser && profile?.role === 'donor' && (
        <Suspense fallback={<CircularProgress />}>
          <ProfilePageDonor
            profile={profile}
            onConsentChange={handleConsentChange}
            loading={grantConsentLoading || revokeConsentLoading}
          />
        </Suspense>
      )}
      {!loading && currentUser && profile?.role === 'sponsor' && (
        <Suspense fallback={<CircularProgress />}>
          <ProfilePageSponsor profile={profile} />
        </Suspense>
      )}
      {!loading && currentUser && profile?.role === 'lifebank' && (
        <Suspense fallback={<CircularProgress />}>
          <ProfilePageLifebank profile={profile} />
        </Suspense>
      )}
      {!currentUser &&
        <Suspense fallback={<CircularProgress />}>
          <ProfilePageGuest />
        </Suspense>}
    </Box>


  )
}
Example #6
Source File: CameraPage.jsx    From trashpanda-fe with MIT License 4 votes vote down vote up
CameraPage = ({
  theme,
  setShutterPress,
  shutterPress,
  setAppCluster,
  setSearchFocus
}) => {
  const [image, setImage] = useState();
  const videoRef = useRef(null);
  const [cameraInstance, setCameraInstance] = useState();
  const [loading, setLoading] = useState(true);
  const [getCluster, ClusterData] = useLazyQuery(GET_CLUSTER);

  const handleShutterButton = () => {
    setShutterPress(true);
  };

  useEffect(() => {
    if (!ClusterData.loading) {
      setLoading(false);
    }

    if (!ClusterData.loading && ClusterData.data) {
      setAppCluster(ClusterData.data.getCluster);
    }
  }, [ClusterData]);

  useEffect(() => {
    if (shutterPress) {
      const config = {
        sizeFactor: 1
      };

      if (cameraInstance) {
        const dataUri = cameraInstance.getDataUri(config);
        setImage({ dataUri });
        cameraInstance.stopCamera();
        getCluster({
          variables: {
            imageData: dataUri
          }
        });
        setLoading(true);
      }
    } else {
      setImage(null);
      setLoading(true);
      startCam(cameraInstance, setLoading);
    }
  }, [shutterPress]);

  useEffect(() => {
    // create video stream
    if (videoRef) {
      const cameraPhoto = new CameraPhoto(videoRef.current);
      setCameraInstance(cameraPhoto);
    }
  }, [videoRef]);

  useEffect(() => {
    startCam(cameraInstance, setLoading);

    return function cleanup() {
      if (cameraInstance && cameraInstance.stream) {
        console.log("running cleanup");
        setImage(null);
        setShutterPress(false);

        cameraInstance
          .stopCamera()
          .then(() => {
            console.log("stopped camera");
          })
          .catch(err => console.log("camera not running"));
      }
    };
  }, [cameraInstance]);

  return (
    <Root>
      {loading && <Spinner />}
      <StyledVideo
        hidden={shutterPress || !videoRef}
        ref={videoRef}
        autoPlay={true}
      />
      {image && <img src={image.dataUri} alt="camera image" />}
      {!ClusterData.loading && (ClusterData.data || ClusterData.error) && (
        <ClusterResult
          shutterPress={shutterPress}
          setShutterPress={setShutterPress}
          ClusterData={ClusterData}
          setSearchFocus={setSearchFocus}
        />
      )}
      {!shutterPress && (
        <FullFrame>
          <StyledShutterButton onClick={handleShutterButton}>
            <ShutterButton theme={theme} />
          </StyledShutterButton>
        </FullFrame>
      )}
    </Root>
  );
}
Example #7
Source File: OffersManagement.js    From lifebank with MIT License 4 votes vote down vote up
OffersManagement = () => {
  const { t } = useTranslation('translations')
  const classes = useStyles()
  const [offers, setOffers] = useState(undefined)
  const [profileIDLoaded, setProfileIDLoaded] = useState(false)
  const [offersLoaded, setOffersLoaded] = useState(false)
  const timezone = moment.tz.guess()
  const [open, setOpen] = useState(false)
  const [openDeleteDialog, setOpenDeleteDialog] = useState(false)
  const [offerIDToDelete, setOfferIDToDelete] = useState()
  const [offerToEdit, setOfferToEdit] = useState()
  const [openGenericFormAddVariant, setOpenGenericFormAddVariant] = useState(
    false
  )
  const [openGenericFormEditVariant, setOpenGenericFormEditVariant] = useState(
    false
  )
  const [clickedOffer, setClickedOffer] = useState()
  const [openSnackbar, setOpenSnackbar] = useState({
    show: false,
    message: '',
    severity: 'success'
  })

  const { refetch: getSponsorOffers } = useQuery(GET_SPONSOR_OFFERS_QUERY, {
    variables: {
      sponsor_id: 17
    },
    skip: true
  })

  const checkAvailableFields = () => {
    let pendingFieldsObject = {}
    if (!profile.address)
      pendingFieldsObject = { ...pendingFieldsObject, address: false }

    if (!profile.about)
      pendingFieldsObject = { ...pendingFieldsObject, about: false }

    if (!profile.logo_url)
      pendingFieldsObject = { ...pendingFieldsObject, logo_url: false }

    if (!profile.name)
      pendingFieldsObject = { ...pendingFieldsObject, name: false }

    if (!profile.telephones)
      pendingFieldsObject = { ...pendingFieldsObject, telephones: false }

    if (!profile.photos)
      pendingFieldsObject = { ...pendingFieldsObject, photos: false }

    if (!profile.social_media_links)
      pendingFieldsObject = {
        ...pendingFieldsObject,
        social_media_links: false
      }

    if (!profile.website)
      pendingFieldsObject = { ...pendingFieldsObject, website: false }

    if (!profile.schedule)
      pendingFieldsObject = { ...pendingFieldsObject, schedule: false }

    if (!profile.location)
      pendingFieldsObject = { ...pendingFieldsObject, location: false }

    if (Object.keys(pendingFieldsObject).length > 0) {
      setOpenGenericFormAddVariant(false)
      setOpenSnackbar({
        show: true,
        message: t("offersManagement.info"),
        severity: 'warning'
      })
    } else {
      setOpenGenericFormAddVariant(true)
    }
  }
  const [
    loadProfileID,
    { data: { profile: { profile } = {} } = {} }
  ] = useLazyQuery(PROFILE_ID_QUERY, { fetchPolicy: 'network-only' })

  const [
    updateOffer,
    { data: { update_offer: updateOfferResult } = {} }
  ] = useMutation(UPDATE_OFFER_AVAILABILITY_MUTATION)

  const [deleteOffer] = useMutation(DELETE_OFFER_MUTATION)

  const deleteOfferRequest = async () => {
    setOpenDeleteDialog(false)
    await deleteOffer({
      variables: {
        id: offerIDToDelete
      }
    })
    setOffers(offers.filter((offer) => offer.id !== offerIDToDelete))
  }

  const handleActionClick = async (action, active, offer_id) => {
    switch (action) {
      case 'delete':
        setOfferIDToDelete(offer_id)
        setOpenDeleteDialog(true)
        break
      case 'deactivate':
        await updateOffer({
          variables: {
            id: offer_id,
            active: !active
          }
        })
        break
      case 'activate':
        await updateOffer({
          variables: {
            id: offer_id,
            active: !active
          }
        })
        break
      case 'edit':
        setOpenGenericFormEditVariant(true)
        setOfferToEdit(offers.find((o) => o.id === offer_id))
        break
      default:
        break
    }
  }

  const [anchorEl, setAnchorEl] = useState(null)

  const handleClick = (event) => {
    setAnchorEl(event.currentTarget)
  };

  const handleCloseMenu = () => {
    setAnchorEl(null)
  };

  const Actions = (active, offer_id) => (
    <div>
      <Button aria-controls="simple-menu" aria-haspopup="true" onClick={handleClick}>
        <MoreVertIcon />
      </Button>
      <Menu
        id="simple-menu"
        anchorEl={anchorEl}
        keepMounted
        value=""
        open={Boolean(anchorEl)}
        onClose={handleCloseMenu}
      >
        <MenuItem onClick={(e) => handleActionClick("edit", active, offer_id)}>{t('common.edit')}</MenuItem>
        <MenuItem onClick={(e) => handleActionClick("delete", active, offer_id)}>{t('common.delete')}</MenuItem>
        <MenuItem onClick={(e) => handleActionClick(active ? 'deactivate' : 'activate', active, offer_id)}>
          {active
            ? t('offersManagement.deactivate')
            : t('offersManagement.activate')}
        </MenuItem>
      </Menu>
    </div>
  )

  const handleOpenClick = (offer) => {
    setOpen(true)
    setClickedOffer(offer)
  }
  const handleCallback = () => {
    setOpenSnackbar({
      show: true,
      message: t('offersManagement.offerCreation'),
      severity: 'success'
    })
  }

  const handleClose = (_event, reason) => {
    if (reason === 'clickaway') return

    setOpenSnackbar({ ...openSnackbar, show: false })
  }

  const getGenericOfferComponent = (editing, data) => {
    return (
      <GenericOfferFormComponent
        open={editing ? openGenericFormEditVariant : openGenericFormAddVariant}
        setOpen={
          editing ? setOpenGenericFormEditVariant : setOpenGenericFormAddVariant
        }
        setOffers={setOffers}
        sponsor_id={profile.id}
        isEditing={editing}
        data={data}
        offerNotification={handleCallback}
      />
    )
  }

  useEffect(() => {
    const getOffers = async () => {
      const { data } = await getSponsorOffers({
        sponsor_id: profile.id
      })

      data && setOffers(data.offer)
      setOffersLoaded(true)
    }

    if (profileIDLoaded) getOffers()
  })

  useEffect(() => {
    loadProfileID()
  }, [loadProfileID])

  useEffect(() => {
    if (profile) setProfileIDLoaded(true)
  }, [profile])

  useEffect(() => {
    if (updateOfferResult) {
      const newArr = [...offers]

      const indexToUpdate = offers.findIndex(
        (o) => o.id === updateOfferResult.returning[0].id
      )

      newArr[indexToUpdate].active = !newArr[indexToUpdate].active
      setOffers(newArr)

      setOpenSnackbar({
        show: true,
        message: t('offersManagement.offerAvailabilityUpdatedMessage'),
        severity: 'success'
      })
    }
  }, [t, offers, updateOfferResult])

  return (
    <Box className={classes.root}>
      {!offersLoaded &&
        <Box className={classes.content}>
          <CircularProgress />
          <Typography className={classes.title} >{t('common.loading')}...</Typography>
        </Box>
      }
      {offersLoaded &&
        <>
          {offers && offers.length > 0 &&
            <Box className={classes.tableContent} >
              <Typography className={classes.title} >{t('offersManagement.offersManagement')}</Typography>
              <MUIDataTable
                title={t('offersManagement.tableTitle')}
                data={offers.map((offer, key) => [
                  <Button
                    key={key}
                    className={classes.offerName}
                    onClick={() => handleOpenClick(offer)}
                    aria-label="delete"
                  >
                    {offer.offer_name}
                  </Button>,
                  offer.active
                    ? t('offersManagement.active')
                    : t('offersManagement.inactive'),
                  offer.start_date
                    ? m(offer.start_date).tz(timezone).format('DD-MM-YYYY')
                    : <Typography className={classes.script}>{t('offersManagement.noProvidedDate')}</Typography>,
                  offer.end_date
                    ? m(offer.end_date).tz(timezone).format('DD-MM-YYYY')
                    : <Typography className={classes.script}>{t('offersManagement.noProvidedDate')}</Typography>,
                  Actions(offer.active, offer.id),
                ])}
                columns={[
                  {
                    name: t('offersManagement.offerName'),
                    options: {
                      filter: true,
                    }
                  },
                  {
                    name: t('offersManagement.status'),
                    options: {
                      filter: true,
                    }
                  },
                  {
                    name: t('offersManagement.startDate'),
                    options: {
                      filter: true,
                    }
                  },
                  {
                    name: t('offersManagement.endDate'),
                    options: {
                      filter: true,
                    }
                  },
                  {
                    name: t('offersManagement.actions'),
                    options: {
                      filter: false,
                    }
                  }
                ]}
                options={{
                  print: false,
                  selectableRowsHideCheckboxes: true,
                  selectableRowsHeader: false,
                  download: false,
                }}
              />
            </Box>
          }
          {offers.length === 0 &&
            <Box className={classes.content}>
              <Typography className={classes.title}>
                {t('offersManagement.youHaveNoAddedOffers')}
              </Typography>
              <Button
                variant="contained"
                color="secondary"
                className={classes.btnAction}
                onClick={checkAvailableFields}
              >
                {t('offersManagement.addOffer')}
              </Button>
            </Box>
          }
        </>
      }
      {open &&
        <OfferDetails offer={clickedOffer} open={open} setOpen={setOpen} />
      }
      <Fab
        size="medium"
        className={classes.fab}
        color="secondary"
        aria-label="add"
        onClick={checkAvailableFields}
      >
        <AddIcon />
      </Fab>
      {openGenericFormAddVariant && profileIDLoaded &&
        getGenericOfferComponent(false, undefined)
      }
      {offerToEdit &&
        getGenericOfferComponent(true, offerToEdit)
      }
      <Dialog open={openDeleteDialog} aria-labelledby="delete-dialog-title">
        <DialogTitle id="delete-dialog-title">
          {t('offersManagement.deleteOfferConfirmation')}
        </DialogTitle>
        <DialogActions>
          <Button
            autoFocus
            onClick={() => setOpenDeleteDialog(false)}
            color="primary"
          >
            {t('common.cancel')}
          </Button>
          <Button onClick={deleteOfferRequest} color="primary" autoFocus>
            {t('offersManagement.yesDeleteIt')}
          </Button>
        </DialogActions>
      </Dialog>
      <Snackbar
        open={openSnackbar.show}
        autoHideDuration={2000}
        onClose={handleClose}
      >
        <Alert severity={openSnackbar.severity}>{openSnackbar.message}</Alert>
      </Snackbar>
    </Box>
  )
}
Example #8
Source File: HistoryDashboard.js    From lifebank with MIT License 4 votes vote down vote up
HistoryDashboard = (user) => {
  const { t } = useTranslation('translations')
  const classes = useStyles()
  const [bodyReceive, setBodyReceive] = useState()
  const [bodySent, setBodySent] = useState()
  const [currentUser] = useUser()
  const [optionSR, setOption] = useState('sent')

  const options = [
    { value: 'sent', label: t('historyDashboard.tableTitleSent') },
    { value: 'received', label: t('historyDashboard.tableTitleReceived') }
  ]

  const [
    getReportQuery,
    { data: { get_report: getReportResult } = {} }
  ] = useLazyQuery(GET_REPORT_QUERY, { fetchPolicy: 'network-only' })

  const formatDataToReport = () => {
    const sent = getReportResult.notifications.sent
    const received = getReportResult.notifications.received
    setBodyReceive(received)
    setBodySent(sent)
  }

  const formatDataToDonorReport = () => {
    const sent = getReportResult.notifications.sent
    const received = getReportResult.notifications.received
    setBodyReceive(received)
    setBodySent(sent)
  }

  const handleChange = (event) => {
    setOption(event.target.value);
  }

  useEffect(() => {
    if (!getReportResult) {
      getReportQuery()
    } else {
      if (currentUser && (currentUser.role === 'lifebank' || currentUser.role === 'sponsor')) formatDataToReport()
      else if (currentUser && currentUser.role === 'donor') formatDataToDonorReport()
      else return
    }
  }, [getReportQuery, currentUser, getReportResult])

  return (
    <>
      <Box className={classes.root} >
        <Typography className={classes.title} >{t('historyDashboard.title')}</Typography>
        <Box className={classes.boxSelect}>
          <FormControl variant="filled" className={classes.formControl}>
            <InputLabel id="demo-simple-select-outlined-label">{t('historyDashboard.dashboard')}</InputLabel>
            <Select
              labelId="demo-simple-select-filled-label"
              id="demo-simple-select-filled"
              value={optionSR}
              onChange={handleChange}
              label="optionSR"
            >
              {options.map((option) => {
                return (
                  <MenuItem
                    key={option.value}
                    value={option.value}
                  >
                    {option.label}
                  </MenuItem>
                )
              })}
            </Select>
          </FormControl>
        </Box>
        <Box className={classes.root}>
          {optionSR === 'sent' && (
            <Box>
              {bodySent && bodySent.length > 0 &&
                <Box className={classes.tableContent} >
                  <MUIDataTable
                    title={t('historyDashboard.tableTitleSent')}
                    data={bodySent.map((notification) => [
                      notification.send_to,
                      notification.created_at_date,
                      notification.created_at_time,
                      notification.tokens
                    ])}
                    columns={[
                      {
                        name: t('historyDashboard.donor'),
                        options: {
                          filter: true,
                        }
                      },
                      {
                        name: t('historyDashboard.date'),
                        options: {
                          filter: true,
                        }
                      },
                      {
                        name: t('historyDashboard.time'),
                        options: {
                          filter: true,
                        }
                      },
                      {
                        name: t('historyDashboard.tokens'),
                        options: {
                          filter: true,
                        }
                      }
                    ]}
                    options={{
                      print: false,
                      selectableRowsHideCheckboxes: true,
                      selectableRowsHeader: false,
                      download: false,
                    }}
                  />
                </Box>
              }
            </Box>)}
          {optionSR === 'received' && (
            <Box>
              {bodyReceive && bodyReceive.length > 0 &&
                <Box className={classes.tableContent} >
                  <MUIDataTable
                    title={t('historyDashboard.tableTitleSent')}
                    data={bodyReceive.map((notification) => [
                      notification.send_to,
                      notification.created_at_date,
                      notification.created_at_time,
                      notification.tokens
                    ])}
                    columns={[
                      {
                        name: t('historyDashboard.donor'),
                        options: {
                          filter: true,
                        }
                      },
                      {
                        name: t('historyDashboard.date'),
                        options: {
                          filter: true,
                        }
                      },
                      {
                        name: t('historyDashboard.time'),
                        options: {
                          filter: true,
                        }
                      },
                      {
                        name: t('historyDashboard.tokens'),
                        options: {
                          filter: true,
                        }
                      }
                    ]}
                    options={{
                      print: false,
                      selectableRowsHideCheckboxes: true,
                      selectableRowsHeader: false,
                      download: false,
                    }}
                  />
                </Box>
              }
            </Box>)}
        </Box>
      </Box>
    </>
  )
}
Example #9
Source File: EditProfile.js    From lifebank with MIT License 4 votes vote down vote up
EditProfilePage = () => {
  const { t } = useTranslation('translations')
  const classes = useStyles()
  const history = useHistory()
  const [, { logout }] = useUser()
  const [currentUser] = useUser()
  const [openSnackbar, setOpenSnackbar] = useState(false)
  const theme = useTheme()
  const isDesktop = useMediaQuery(theme.breakpoints.up('md'), {
    defaultMatches: false
  })
  const [
    loadProfile,
    { error: errorProfile, loading, data: { profile: { profile } = {} } = {} }
  ] = useLazyQuery(PROFILE_QUERY, { fetchPolicy: 'network-only' })
 
  const [
    revokeConsent,
    {
      error: errorRevokeConsent,
      loading: revokeConsentLoading,
      data: { revoke_consent: revokeConsentResult } = {}
    }
  ] = useMutation(REVOKE_CONSENT_MUTATION)

  const [
    grantConsent,
    {
      error: errorGrantConsent,
      loading: grantConsentLoading,
      data: { grant_consent: grantConsentResult } = {}
    }
  ] = useMutation(GRANT_CONSENT_MUTATION)

  const [
    editProfile,
    { error: errorEditResults, loading: editLoading, data: { edit_profile: editProfileResult } = {} }
  ] = useMutation(EDIT_PROFILE_MUTATION)

  const [setUsername] = useMutation(SET_USERNAME)

  const handleConsentChange = () => {
    profile?.consent ? revokeConsent() : grantConsent()
  }

  const handleUpdateUser = (userEdited, userNameEdited, account) => {
    editProfile({
      variables: {
        profile: userEdited
      }
    })
    if (account && userNameEdited) {
      setUsername({
        variables: {
          account: account,
          username: userNameEdited
        }
      })
    }
  }
  const handleCloseSnackBar = () => {
    setOpenSnackbar({ ...openSnackbar, show: false })
  }
  useEffect(() => {
    if (!currentUser) {
      return
    }

    loadProfile()
  }, [currentUser, loadProfile])

  useEffect(() => {
    if (grantConsentResult || revokeConsentResult) {
      loadProfile()
    }
  }, [grantConsentResult, revokeConsentResult, loadProfile])

  useEffect(() => {
    if (!editProfileResult) return

    const { success } = editProfileResult

    if (success) {
      history.push({
        pathname: '/profile',
        state: true
      })

    } else if (!success) {
      setOpenSnackbar({
        show: true,
        message: t('editProfile.duringSaveProfileData'),
        severity: 'error'
      })
    }
  }, [t, history, editProfileResult])


  useEffect(() => {
    if (errorProfile) {
      if (errorProfile.message === 'GraphQL error: Could not verify JWT: JWTExpired') {
        logout()
        history.push('/')
      } else history.push('/internal-error')
    }
  }, [logout, history, errorProfile])

  useEffect(() => {
    if (errorRevokeConsent || errorGrantConsent || errorEditResults) {
      setOpenSnackbar({
        show: true,
        message: t('editProfile.duringSaveProfileData'),
        severity: 'error'
      })
    }

  }, [t, errorRevokeConsent, errorGrantConsent, errorEditResults])


  return (
    <>
      {isDesktop && (
        <Box className={classes.wrapper}>
          {loading && <CircularProgress />}
          {!loading && currentUser && profile?.role === 'donor' && (
            <Suspense fallback={<CircularProgress />}>
              <EditProfileDonor
                profile={profile}
                onConsentChange={handleConsentChange}
                loading={grantConsentLoading || revokeConsentLoading || editLoading}
                onSubmit={handleUpdateUser}
              />
            </Suspense>
          )}
          {!loading && currentUser && profile?.role === 'sponsor' && (
            <Suspense fallback={<CircularProgress />}>
              <EditProfileSponsor
                profile={profile}
                onSubmit={handleUpdateUser}
                loading={editLoading}
              />
            </Suspense>
          )}
          {!loading && currentUser && profile?.role === 'lifebank' && (
            <Suspense fallback={<CircularProgress />}>
              <EditProfileBank
                profile={profile}
                userName={profile.username}
                onSubmit={handleUpdateUser}
                loading={editLoading}
              />
            </Suspense>
          )}
        </Box >
      )}

      {!isDesktop && (
        <Box className={classes.wrapperMobile}>
          {loading && <CircularProgress />}
          {!loading && currentUser && profile?.role === 'lifebank' && (
            <Suspense fallback={<CircularProgress />}>
              <EditProfileBankMobile
                profile={profile}
                userName={profile.username}
                onSubmit={handleUpdateUser}
                loading={editLoading}
              />
            </Suspense>
          )}
          {!loading && currentUser && profile?.role === 'sponsor' && (
            <Suspense fallback={<CircularProgress />}>
              <EditProfileSponsorMobile
                profile={profile}
                onSubmit={handleUpdateUser}
                loading={editLoading}
              />
            </Suspense>
          )}
          {!loading && currentUser && profile?.role === 'donor' && (
            <Suspense fallback={<CircularProgress />}>
              <EditProfileDonor
                profile={profile}
                onConsentChange={handleConsentChange}
                loading={grantConsentLoading || revokeConsentLoading || editLoading}
                onSubmit={handleUpdateUser}
              />
            </Suspense>
          )}
        </Box>
      )}
      <Snackbar open={openSnackbar.show} autoHideDuration={4000} onClose={handleCloseSnackBar}>
        <Alert
          severity={openSnackbar.severity}
          action={
            <IconButton
              aria-label="close"
              color="inherit"
              size="small"
              onClick={handleCloseSnackBar}
            >
              <CloseIcon fontSize="inherit" />
            </IconButton>
          }
        >
          <AlertTitle>{t('editProfile.error')}</AlertTitle>
          {openSnackbar.message}
        </Alert>
      </Snackbar>
    </>
  )
}
Example #10
Source File: TransactionReport.js    From lifebank with MIT License 4 votes vote down vote up
TransactionReport = ({ dateFrom, dateTo, saveReport, onReportSaved }) => {
  const { t } = useTranslation('translations')
  const [currentUser] = useUser()
  const [headReceive, setHeadReceived] = useState()
  const [bodyReceive, setBodyReceive] = useState()
  const [bodySent, setBodySent] = useState()

  const [
    loadProfile,
    { data: { profile: { profile } = {} } = {} }
  ] = useLazyQuery(PROFILE_QUERY, { fetchPolicy: 'network-only' })

  const headSent = [
    [
      t('report.donor'),
      t('report.date'),
      t('report.time'),
      t('report.tokens')
    ]
  ]

  const [
    getReportQuery,
    { data: { get_report: getReportResult } = {} }
  ] = useLazyQuery(GET_REPORT_QUERY, { fetchPolicy: 'network-only' })

  useEffect(() => {
    if (!profile) loadProfile()
  }, [loadProfile, profile])

  useEffect(() => {
    if (!getReportResult) {
      getReportQuery({
        variables: {
          dateFrom: dateFrom,
          dateTo: dateTo
        }
      })
    } else {
      if (currentUser && currentUser.role === 'lifebank') formatDataToLifebankReport()
      else if (currentUser && currentUser.role === 'sponsor') formatDataToSponsorReport()
      else return
    }
  }, [getReportQuery, currentUser, dateFrom, dateTo, getReportResult])

  const formatDataToLifebankReport = () => {
    const received = getReportResult.notifications.received.map((notification) => {
      return [
        notification.business,
        notification.created_at_date,
        notification.created_at_time,
        notification.tokens
      ]
    })

    const sent = getReportResult.notifications.sent.map((notification) => {
      return [
        notification.send_to,
        notification.created_at_date,
        notification.created_at_time,
        notification.tokens
      ]
    })

    setHeadReceived([
      [
        t('report.business'),
        t('report.date'),
        t('report.time'),
        t('report.tokens')
      ]
    ]
    )
    setBodyReceive(received)
    setBodySent(sent)
  }

  const formatDataToSponsorReport = () => {
    const received = getReportResult.notifications.received.map((notification) => {
      return [
        notification.payerUser,
        notification.offer ? notification.offer.offer_name : '',
        notification.created_at_date,
        notification.created_at_time,
        notification.offer ? notification.offer.cost_in_tokens : '']
    })

    setHeadReceived([
      [
        t('report.user'),
        t('report.offer'),
        t('report.date'),
        t('report.time'),
        t('report.tokens')
      ]
    ]
    )
    setBodyReceive(received)
  }

  const downloadReport = () => {
    const doc = new jsPDF()
    const pageWidth = doc.internal.pageSize.getWidth()
    const pageHeight = doc.internal.pageSize.getHeight()


    if (currentUser && currentUser.role === 'lifebank') {
      doc.autoTable({
        margin: { top: 30, bottom: 30 },
        pageBreak: 'auto',
        head: headReceive,
        body: bodyReceive
      })

      doc.autoTable({
        margin: { top: 30, bottom: 30 },
        pageBreak: 'auto',
        head: headSent,
        body: bodySent,
      })
    } else if (currentUser && currentUser.role === 'sponsor') {
      doc.autoTable({
        margin: { top: 30, bottom: 30 },
        pageBreak: 'auto',
        head: headReceive,
        body: bodyReceive,
      })
    }
    else return

    for (let i = 1; i < doc.internal.pages.length; i++) {
      doc.setPage(i)
      doc.setFontSize(14)
      doc.text(profile ? profile.name : '', pageWidth / 2, 10, { align: 'center' })
      doc.text(new Date().toISOString().slice(0, 10), pageWidth / 2, 16, { align: 'center' })
      if (dateFrom && dateTo) {
        doc.text(
          t('report.pdfHeader').concat(' ', t('report.from'), ' ', dateFrom, ' ', t('report.to'), ' ', dateTo),
          pageWidth / 2, 22, { align: 'center' }
        )
      } else doc.text(t('report.pdfHeader'), pageWidth / 2, 22, { align: 'center' })
      doc.text(t('report.pdfFooter'), pageWidth / 2, pageHeight - 20, { align: 'center', maxWidth: pageWidth - 50 })
    }

    doc.save(t('report.reportDownloadName'))
    onReportSaved()
  }

  useEffect(() => {
    if (saveReport) downloadReport()
  }, [saveReport])

  return (
    <>
    </>
  )
}
Example #11
Source File: Settings.js    From lifebank with MIT License 4 votes vote down vote up
Settings = ({ onCloseSetting }) => {
  const { t } = useTranslation('translations')
  const classes = useStyles()
  const theme = useTheme()
  const [user, setUser] = useState({})
  const [openSnackbar, setOpenSnackbar] = useState(false)
  const [open, setOpen] = useState(true)
  const [showPassword, setShowPassword] = useState(false)
  const [showNewPassword, setShowNewPassword] = useState(false)
  const [validEmailFormat, setValidEmailFormat] = useState(false)
  const fullScreen = useMediaQuery(theme.breakpoints.down('sm'))
  const [currentUser, { logout }] = useUser()
  const history = useHistory()
  const [
    loadProfile,
    { error: errorProfile, loading, data: { profile: { profile } = {} } = {} }
  ] = useLazyQuery(PROFILE_QUERY, { fetchPolicy: 'network-only' })

  const [
    changePassword,
    { loading: loadingChangePassword, error: errorChangePassword, data: { change_password: responseChangePassword } = {} }
  ] = useMutation(CHANGE_PASSWORD)

  const [
    changeEmail,
    { loading: loadingChangeEmail, error: errorChangeEmail, data: { change_email: responseChangeEmail } = {} }
  ] = useMutation(CHANGE_EMAIL)

  const [
    updateEmailSubscription,
    { data: { update_user: updateEmailSubscriptionResult } = {} }
  ] = useMutation(UPDATE_EMAIL_SUBSCRIPTION_MUTATION)

  const [
    closeAccount,
    { loading: loadingCloseAccount, error: errorCloseAccount, data: { close_account: resultCloseAccount } = {} }
  ] = useMutation(CLOSE_ACCOUNT_MUTATION)

  const [
    getAccountSignupMethod,
    { data: { signup_method: getAccountSignupMethodResult } = {} }
  ] = useMutation(GET_ACCOUNT_SIGNUP_METHOD)

  const handleCloseSnackBar = () => {
    setOpenSnackbar({ ...openSnackbar, show: false })
  }

  const handleOpen = () => {
    setOpen(!open)
    onCloseSetting()
  }

  const handleClickShowPassword = () => {
    setShowPassword(!showPassword)
  }

  const handleClickShowNewPassword = () => {
    setShowNewPassword(!showNewPassword)
  }

  const handleSetField = (field, value) => {
    setUser({ ...user, [field]: value })
  }

  const handleSetFieldEmail = (field, value) => {
    const regularExpresion = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/
    if (regularExpresion.test(value)) setValidEmailFormat(true)
    else setValidEmailFormat(false)
    setUser({ ...user, [field]: value })
  }

  const handleSubmitChangePassword = async () => {
    if (getAccountSignupMethodResult && getAccountSignupMethodResult.password_changable) {
      changePassword({
        variables: {
          email: profile.email,
          newPassword: user.newPassword,
          currentPassword: user.currentPassword,
          emailContent: {
            subject: t('emailMessage.subjectChangePassword'),
            title: t('emailMessage.titleChangePassword'),
            message: t('emailMessage.messageChangePassword')
          }
        }
      })
    } else setOpenSnackbar({
      show: true,
      message: t('setting.passwordNotChangeable'),
      severity: 'error'
    })
  }

  const handleSubmitChangeEmail = async () => {
    if (user && profile) {
      changeEmail({
        variables: {
          account: profile.account,
          email: user.email,
        }
      })
      user.email = null
    }
  }

  const handleChangeCheckBox = (event) => {
    updateEmailSubscription({
      variables: {
        account: profile.account,
        state: event.target.checked
      }
    })
  }

  const onCloseAccontClick = async () => {
    setOpen(false)
    await closeAccount()
  }

  useEffect(() => {
    loadProfile()
  }, [loadProfile, updateEmailSubscriptionResult])

  useEffect(() => {
    if (errorProfile)
      setOpenSnackbar({
        show: true,
        message: t('credentialsRecovery.emailError'),
        severity: 'error'
      })
  }, [errorProfile, t])

  useEffect(() => {
    if (errorChangeEmail)
      setOpenSnackbar({
        show: true,
        message: t('setting.emailError'),
        severity: 'error'
      })
    if (responseChangeEmail)
      setOpenSnackbar({
        show: true,
        message: t('setting.emailChanged'),
        severity: 'success'
      })
    loadProfile()
  }, [t, loadProfile, changeEmail, errorChangeEmail, responseChangeEmail])

  useEffect(() => {
    if (responseChangePassword) {
      if (responseChangePassword.success)
        setOpenSnackbar({
          show: true,
          message: t('setting.passwordChanged'),
          severity: 'success'
        })
      else
        setOpenSnackbar({
          show: true,
          message: t('setting.passwordError'),
          severity: 'error'
        })
    }
  }, [t, responseChangePassword])

  useEffect(() => {
    if (errorChangePassword) {
      if (errorChangePassword.message === `GraphQL error: Cannot read property 'secret' of null`)
        setOpenSnackbar({
          show: true,
          message: t('credentialsRecovery.emailError'),
          severity: 'error'
        })
      else setOpenSnackbar({
        show: true,
        message: errorChangePassword.message.replace('GraphQL error: ', ''),
        severity: 'error'
      })
    }
  }, [errorChangePassword, t])

  useEffect(() => {
    if (!currentUser) {
      return
    }

    loadProfile()
  }, [currentUser, loadProfile])

  useEffect(() => {
    if (profile) {
      getAccountSignupMethod({
        variables: {
          email: profile.email
        }
      })
    }
  }, [getAccountSignupMethod, profile])

  useEffect(() => {
    if (resultCloseAccount) {
      setOpen(false)
      logout()
      history.push('/')
    }
  }, [logout, history, resultCloseAccount])

  useEffect(() => {
    if (errorCloseAccount) {
      setOpenSnackbar({
        show: true,
        message: t('setting.errorCloseAccount'),
        severity: 'error'
      })
    }
  }, [t, errorCloseAccount])

  function executeCredentialsRecovery(e) {
    if (e.key === 'Enter' && (user.newPassword && user.currentPassword)) {
      e.preventDefault()
    }
    else if (e.key === 'Enter' && (!loading)) {
      e.preventDefault()
    }
  }

  function executeEmailChange(e) {
    if (e.key === 'Enter' && validEmailFormat) {
      e.preventDefault()
    }
    else if (e.key === 'Enter' && (!loading)) {
      e.preventDefault()
    }
  }

  return (
    <>
      <Dialog
        open={open}
        onClose={handleOpen}
        aria-labelledby="transition-modal-title"
        aria-describedby="transition-modal-description"
        fullScreen={fullScreen}
        closeAfterTransition
        BackdropComponent={Backdrop}
        BackdropProps={{
          timeout: 500
        }}
      >
        <Box className={classes.closeIcon}>
          <IconButton
            aria-label="close"
            color="inherit"
            size="small"
            onClick={handleOpen}
          >
            <CloseIcon fontSize="inherit" />
          </IconButton>
        </Box>
        <Box className={classes.textFieldWrapper}>
          <Typography variant="h3" className={classes.title}>
            {t('setting.setting')}
          </Typography>
        </Box>
        <DialogContent className={classes.dimensions} >
          <form autoComplete="off">
            <Grid container>
              <Grid container spacing={2}>
                <Grid item xs={6}>
                  <Box className={classes.boxSecondVersion}>
                    <Typography variant="h3" className={classes.text}>
                      {t('setting.language')}
                    </Typography>
                  </Box>
                  <Box className={classes.boxSecondVersion}>
                    <LanguageSelector alt="settings" />
                  </Box>
                </Grid>
                <Divider orientation="vertical" flexItem />
                <Grid item xs={5}>
                  <Box className={classes.boxSecondVersion}>
                    <Typography variant="h3" className={classes.text}>
                      {t('setting.suscribeSection')}
                    </Typography>
                  </Box>
                  <Box className={classes.checkBox}>
                    <FormControlLabel
                      disabled={loading}
                      checked={profile ? profile.email_subscription : true}
                      control={
                        <Checkbox
                          color="primary"
                          onChange={handleChangeCheckBox}
                        />
                      }
                      label={t('setting.checkBoxSuscribe')}
                      labelPlacement="start"
                    />
                  </Box>
                </Grid>
              </Grid>
              <Grid container item xs={12}>
                <Box className={classes.boxThirdVersion}>
                  <Divider className={classes.dividerSecondVersion} />
                  <Typography variant="h3" className={classes.text}>
                    {t('setting.changeEmail')}
                  </Typography>
                  <Grid item xs={12}>
                    <TextField
                      id="currentEmail"
                      variant="filled"
                      InputLabelProps={{ shrink: true }}
                      InputProps={{
                        endAdornment: (
                          <>
                            <InputLabel id="select-label">
                              {profile ? profile.email : ''}
                            </InputLabel>
                          </>
                        )
                      }}
                      onChange={(event) =>
                        handleSetFieldEmail('email', event.target.value)
                      }
                      onKeyPress={(event) =>
                        executeEmailChange(event)
                      }
                      className={classes.box}
                    >
                    </TextField>
                  </Grid>
                  <Box className={classes.box}>
                    <Button
                      disabled={(!validEmailFormat || !user.email) || loadingChangeEmail || loading}
                      variant="contained"
                      color="secondary"
                      onClick={handleSubmitChangeEmail}
                      className={classes.button}
                    >
                      {t('setting.changeEmail')}
                    </Button>
                  </Box>
                  <Box className={classes.loadingBox}>
                    {loadingChangeEmail && <CircularProgress />}
                  </Box>
                </Box>
              </Grid>
              <Grid container item xs={12}>
                <Box className={classes.box}>
                  <Divider className={classes.dividerSecondVersion} />
                  <Typography variant="h3" className={classes.text}>
                    {t('setting.changePassword')}
                  </Typography>
                  <Grid item xs={12}>
                    <TextField
                      id="currentPassword"
                      variant="filled"
                      type={showPassword ? 'text' : 'password'}
                      InputLabelProps={{ shrink: true }}
                      InputProps={{
                        endAdornment: (
                          <>
                            <InputLabel id="select-label">
                              {t('setting.currentPassword')}
                            </InputLabel>
                            <InputAdornment position="end">
                              <IconButton
                                aria-label="toggle password visibility"
                                onClick={handleClickShowPassword}
                                edge="end"
                              >
                                {showPassword ? <Visibility /> : <VisibilityOff />}
                              </IconButton>
                            </InputAdornment>
                          </>
                        )
                      }}
                      value={user.currentPassword || ''}
                      onChange={(event) =>
                        handleSetField('currentPassword', event.target.value)
                      }
                      onKeyPress={(event) =>
                        executeCredentialsRecovery(event)
                      }
                      className={classes.box}
                    />
                  </Grid>
                  <Grid item xs={12}>
                    <TextField
                      id="newPassword"
                      type={showNewPassword ? 'text' : 'password'}
                      variant="filled"
                      InputLabelProps={{ shrink: true }}
                      InputProps={{
                        endAdornment: (
                          <>
                            <InputLabel id="select-label">
                              {t('setting.newPassword')}
                            </InputLabel>
                            <InputAdornment position="end">
                              <IconButton
                                aria-label="toggle password visibility"
                                onClick={handleClickShowNewPassword}
                                edge="end"
                              >
                                {showNewPassword ? <Visibility /> : <VisibilityOff />}
                              </IconButton>
                            </InputAdornment>
                          </>
                        )
                      }}
                      value={user.newPassword || ''}
                      onChange={(event) =>
                        handleSetField('newPassword', event.target.value)
                      }
                      onKeyPress={(event) =>
                        executeCredentialsRecovery(event)
                      }
                      className={classes.box}
                    />
                  </Grid>
                  <Box>
                    <Button
                      disabled={(!user.newPassword || !user.currentPassword) || loadingChangePassword}
                      variant="contained"
                      color="secondary"
                      onClick={handleSubmitChangePassword}
                      className={classes.button}
                    >
                      {t('setting.changePassword')}
                    </Button>
                  </Box>
                </Box>
              </Grid>

              <Grid container item xs={12}>
                <Box className={classes.box}>
                  <Divider className={classes.dividerSecondVersion} />
                  <Typography variant="h3" className={classes.text}>
                    {t('setting.closeAccount')}
                  </Typography>
                  <Box>
                    <Button
                      disabled={loadingCloseAccount}
                      variant="contained"
                      color="secondary"
                      onClick={onCloseAccontClick}
                      className={classes.button}
                    >
                      {t('setting.closeAccountButton')}
                    </Button>
                  </Box>
                  <Box className={classes.loadingBox}>
                    {loadingCloseAccount && <CircularProgress />}
                    {loading && <CircularProgress />}
                  </Box>
                </Box>
              </Grid>

            </Grid>
          </form>
        </DialogContent>

        <Snackbar open={openSnackbar.show} autoHideDuration={4000} onClose={handleCloseSnackBar}>
          <Alert
            className={classes.alert}
            severity={openSnackbar.severity}
          >
            {openSnackbar.message}
          </Alert>
        </Snackbar>
      </Dialog>
    </>
  )
}
Example #12
Source File: DonationsDashboard.js    From lifebank with MIT License 4 votes vote down vote up
DonationsDashboard = ({ isDesktop, currentUser, isOffer, selectOffer }) => {
  const { t } = useTranslation('translations')
  const [maxWidth] = useState('md')
  const [maxWidthQr] = useState('xs')
  const [open, setOpen] = useState(false)
  const [accountTo, setAccountTo] = useState()
  const [openModalQR, setOpenModalQR] = useState(false)
  const [scanValue, setScanValue] = useState()
  const [tokens, setTokens] = useState(0)
  const [role] = useState(currentUser.role)
  const [account] = useState(currentUser.account)
  const classes = useStyles()
  const [openSnackbar, setOpenSnackbar] = useState(false)
  const [state, setState] = useState({
    bottom: false
  })
  const theme = useTheme()
  const isSmallScreen = useMediaQuery(theme.breakpoints.down(370))
  const history = useHistory()
  const [
    loadProfile,
    { error: errroLoadProfile, data: { profile: { profile } = {} } = {}, client }
  ] = useLazyQuery(PROFILE_QUERY, { fetchPolicy: 'network-only' })

  const { data: tokenUser = {} } = useSubscription(
    TOKEN_SUBSCRIPTION, { variables: { account } }
  )
  const [
    donate,
    { loading, error, data: { donate: donateResult } = {} }
  ] = useMutation(DONATE_MUTATION)

  const handleSnackbarClose = () => {
    setOpenSnackbar({ ...openSnackbar, show: false })
    setAccountTo()
  }

  useEffect(() => {
    if (!error)
      return

    setOpenSnackbar({
      show: true,
      message: t('donations.donationsError'),
      severity: 'error'
    })
  }, [t, error])

  useEffect(() => {
    if (errroLoadProfile) {
      handleOpen()
      setOpenSnackbar({
        show: true,
        message: t('donations.donationsProfileError'),
        severity: 'error'
      })
    }

  }, [t, errroLoadProfile])

  useEffect(() => {
    if (!donateResult)
      return

    setOpenSnackbar({
      show: true,
      message: t('donations.succesful'),
      severity: 'success'
    })
  }, [t, donateResult])

  useEffect(() => {
    if (!currentUser) {
      client && client.resetStore()
      history.replace('/')

      return
    }

    if (state.bottom === true || open === true)
      loadProfile()

  }, [currentUser, history, client, loadProfile, state, open, donateResult])

  useEffect(() => {
    if (tokenUser.user) {
      setTokens(parseInt(tokenUser.user[0].token))
    } else {
      setTokens(role === "donor" && profile?.balance.length ? profile.balance.join(',').split(' ')[0] : 0)
    }
  }, [role, profile, tokenUser])

  const anchor = 'bottom'

  const toggleDrawer = (anchor, open) => (event) => {
    if (event) {
      if (
        event.type === 'keydown' &&
        (event.key === 'Tab' || event.key === 'Shift')
      )
        return

      setState({ ...state, [anchor]: open })
    }
  }

  const handleOpen = () => setOpen(!open)

  const handleOpenModalQr = () => setOpenModalQR(!openModalQR)

  const handlerTransferTokens = (account) => {
    setAccountTo(account)
  }

  useEffect(() => {
    if (profile && accountTo) {
      let tempMemo
      if (role === "donor") tempMemo = t("donations.memoDonor")
      else tempMemo = t("donations.memoLifebank")

      const tokensQuantity = 1

      const payload = {
        to: accountTo.toLowerCase().replace(/\s/g, ''),
        memo: tempMemo,
        quantity: tokensQuantity,
        emailContent: {
          'subject': t('emailDonorCongratulation.subject'),
          'content': t('emailDonorCongratulation.hi').concat(
            ' ',
            accountTo,
            ', ',
            '<br><br>',
            t('emailDonorCongratulation.youComplete'),
            ' ',
            profile.name,
            ' ',
            t('emailDonorCongratulation.receivedTokens'),
            ' ',
            tokensQuantity,
            ' ',
            tokensQuantity > 1? t('emailDonorCongratulation.lifeTokensMany'): t('emailDonorCongratulation.lifeTokens'),
            ' ',
            t('emailDonorCongratulation.thanksYou'),
            '<br><br>',
            t('emailDonorCongratulation.growingCommunity'),
          ),
          "badge": t('emailDonorCongratulation.badgeUrl'),
          "content2": t('emailDonorCongratulation.downloadBadge').concat(
            '<br><br>',
            t('emailDonorCongratulation.thanksAgain')
          )
        }
      }
      donate({
        variables: {
          ...payload
        }
      })
    }
  }, [t, donate, role, accountTo])


  const DashboardContent = () => {
    const [accountInput, setAccountInput] = useState("")

    const handleChangeAccountInput = (event) => {
      setAccountInput(event.target.value)
    }
    
    useEffect(() => {
      if (scanValue) setAccountInput(scanValue)
    }, [scanValue])

    return (
      <Box className={classes.dashboardContent}>
        {isDesktop && (
          <>
            <Box className={classes.closeIcon}>
              <IconButton
                aria-label="close"
                color="inherit"
                size="small"
                onClick={handleOpen}
              >
                <CloseIcon fontSize="inherit" />
              </IconButton>
            </Box>
            {role === "donor" &&
              <Typography className={classes.draweTitleDesktop}>
                {t('donations.donate')}
              </Typography>
            }
            {role === "lifebank" &&
              <Typography className={classes.draweTitleDesktop}>
                {t('donations.transferTokens')}
              </Typography>
            }
            {role === "sponsor" &&
              <Typography className={classes.draweTitleDesktop}>
                {t('donations.claimReward')}
              </Typography>
            }
          </>
        )}
        {!isDesktop && (
          <>
            <Box className={classes.closeIcon}>
              <IconButton
                aria-label="close"
                color="inherit"
                size="small"
                onClick={toggleDrawer(anchor, false)}
              >
                <CloseIcon fontSize="inherit" />
              </IconButton>
            </Box>
            {role === "donor" &&
              <Typography className={classes.draweTitle}>
                {t('donations.yourDonationsAndRewards')}
              </Typography>
            }
            {role === "lifebank" &&
              <Typography className={classes.draweTitle}>
                {t('donations.transferTokens')}
              </Typography>
            }
            {role === "sponsor" &&
              <Typography className={classes.draweTitle}>
                {t('donations.claimReward')}
              </Typography>
            }
            <Divider className={classes.dividerTitle} />
          </>
        )}
        {role === "donor" &&
          <Box className={classes.boxBalance}>
            <Typography className={classes.balanceText}>
              {t('donations.youOwn')}
            </Typography>
            <EmptyHeartSVG balance={parseInt(tokens)} isDesktop={isDesktop} />
            <Typography className={classes.balanceText}>
              {t('miscellaneous.tokens')}
            </Typography>
          </Box>
        }
        { (role === "donor" || role === "sponsor") &&
          <Box>
            {role === "donor" &&
              <Box>
                <Typography className={classes.sectionTitle}>
                  {t('donations.receiveTokens')}
                </Typography>
                <Divider className={classes.dividerSection} />
                <Typography className={classes.sectionText}>
                  {t('donations.toReceiveTokens')}
                </Typography>
              </Box>
            }
            {role === "sponsor" &&
              <Typography className={classes.sectionText}>
                {t('donations.toReceiveTokensDonor')}
              </Typography>
            }
            <Box className={classes.boxQR}>
              <QRCode value={account} size={100} />
              <Typography className={classes.accountText}>
                {account}
              </Typography>
            </Box>
          </Box>
        }
        { (role === "donor" || role === "lifebank") &&
          <Box>
            {role === "donor" &&
              <Box>
                <Typography className={classes.sectionTitle}>
                  {t('donations.sendTokens')}
                </Typography>
                <Divider className={classes.dividerSection} />
                <Typography className={classes.sectionText}>
                  {t('donations.toSendTo')}
                </Typography>
              </Box>
            }
            {role === "lifebank" &&
              <Typography className={classes.sectionText}>
                {t('donations.toSendToDonor')}
              </Typography>
            }
            <Box className={classes.boxTexfield}>
              <form autoComplete="off">
                <TextField
                  className={classes.inputText}
                  id="paylod-account"
                  label={role === "lifebank" ? t('donations.enterDonorUsername') : t('donations.enterSponsorUsername')}
                  variant="filled"
                  value={accountInput}
                  onChange={handleChangeAccountInput}
                />
                <QrReaderModal setAccountInput={setAccountInput} />
              </form>
            </Box>
            <Box className={classes.boxButtonSendToken}>
              {loading &&
                <>
                  <CircularProgress />
                  <br />
                  <br />
                </>
              }
              <Button className={classes.sendTokenButton} variant="contained" color="secondary"
                onClick={() => {
                  handlerTransferTokens(accountInput)
                }}
                disabled={
                  !accountInput ||
                  loading
                }
              >
                {t('donations.sendToken')}
              </Button>
            </Box>
          </Box>
        }
      </Box>
    )
  }

  const Transition = forwardRef(function Transition(props, ref) {
    return <Slide direction="up" ref={ref} {...props} />
  })

  const QrReaderModal = () => {
    const theme = useTheme()
    const fullScreen = useMediaQuery(theme.breakpoints.down('sm'))
    const [cameraSelection, setCameraSelction] = useState("rear")
    const succesefulScan = (value) => {
      if (value) {
        setOpenModalQR(false)
        setScanValue(value)
      }
    }

    useEffect(() => {
      if (openModalQR) {
        setScanValue("")
      }
    }, [openModalQR])

    const handleChangeCamera = () => {
      if (cameraSelection === "rear") setCameraSelction("front")
      else setCameraSelction("rear")
    }

    return (
      <>
        <IconButton aria-label="delete" className={classes.camaraButtonIcon} onClick={handleOpenModalQr}>
          <CameraAltIcon className={classes.camaraIcon} />
        </IconButton>
        <Dialog
          fullScreen={fullScreen}
          maxWidth={maxWidthQr}
          open={openModalQR}
          onClose={handleOpenModalQr}
          aria-labelledby="transition-modal-title"
          aria-describedby="transition-modal-description"
          closeAfterTransition
          BackdropComponent={Backdrop}
          BackdropProps={{
            timeout: 500
          }}
          TransitionComponent={Transition}
        >
          {fullScreen &&
            <AppBar className={classes.appBar}>
              <Toolbar>
                <IconButton
                  className={classes.backIcon}
                  onClick={handleOpenModalQr}
                  aria-label="close"
                >
                  <KeyboardBackspaceIcon />
                </IconButton>
                <Typography variant="h6" className={classes.titleScanQR}>
                  {t('donations.scanQR')}
                </Typography>
                <IconButton
                  className={classes.switchCamaraIcon}
                  onClick={handleChangeCamera}
                  aria-label="close"
                >
                  <FlipCameraIosIcon />
                </IconButton>
              </Toolbar>
            </AppBar>
          }
          {!fullScreen &&
            <Box className={classes.dialog}>
              <Box className={classes.closeIcon}>
                <IconButton
                  aria-label="close"
                  color="inherit"
                  size="small"
                  onClick={handleOpenModalQr}
                >
                  <CloseIcon fontSize="inherit" />
                </IconButton>
              </Box>
              <Typography className={classes.titleScanQR}>
                {t('donations.scanQR')}
              </Typography>
            </Box>
          }
          {cameraSelection &&
            <QrReader
              delay={100}
              onError={() => { }}
              onScan={(value) => { succesefulScan(value) }}
              facingMode={cameraSelection}
              style={{
                height: "auto",
                width: "100%",
                backgroundColor: '#ffffff',
              }}
            />
          }
        </Dialog>
      </>
    )
  }

  return (
    <>
      {!isDesktop && (
        <>
          { role === "donor" && !isOffer &&
            <Fab
              color="secondary"
              variant="extended"
              className={classes.fabButton}
              onClick={toggleDrawer(anchor, true)}
            >
              <FavoriteIcon className={classes.iconFab} />
              {!isSmallScreen &&
                t('donations.donate')
              }
            </Fab>
          }
          { role === "lifebank" && !isOffer &&
            <Fab
              color="secondary"
              variant="extended"
              className={classes.fabButton}
              onClick={toggleDrawer(anchor, true)}
            >
              <FavoriteIcon className={classes.iconFab} />
              {!isSmallScreen &&
                t('donations.transferTokens')
              }
            </Fab>
          }
          { role === "sponsor" && !isOffer &&
            <Fab
              color="secondary"
              variant="extended"
              className={classes.fabButton}
              onClick={toggleDrawer(anchor, true)}
            >
              <ShoppingCartIcon className={classes.iconFab} />
              {!isSmallScreen &&
                t('donations.claimReward')
              }
            </Fab>
          }
          <Drawer
            anchor={anchor}
            open={state[anchor]}
            onClose={toggleDrawer(anchor, false)}
            PaperProps={{
              elevation: 0,
              style: {
                borderTopLeftRadius: '20px',
                borderTopRightRadius: '20px',
                padding: '16px',
              }
            }}
          >
            <DashboardContent />
          </Drawer >
        </>
      )}
      {isDesktop &&
        <>
          {
            role === "donor" && !isOffer &&
            <Fab
              color="secondary"
              variant="extended"
              className={classes.fabButtonDesktop}
              onClick={handleOpen}
            >
              <FavoriteIcon className={classes.iconFab} />
              {t('donations.donate')}
            </Fab>
          }
          {
            role === "lifebank" && !isOffer &&
            <Fab
              color="secondary"
              variant="extended"
              className={classes.fabButtonDesktop}
              onClick={handleOpen}
            >
              <FavoriteIcon className={classes.iconFab} />
              {t('donations.transferTokens')}
            </Fab>
          }
          {
            role === "sponsor" && !isOffer &&
            <Fab
              color="secondary"
              variant="extended"
              className={classes.fabButtonDesktop}
              onClick={handleOpen}
            >
              <ShoppingCartIcon className={classes.iconFab} />
              {t('donations.claimReward')}
            </Fab>
          }
          <Dialog
            maxWidth={maxWidth}
            open={open}
            onClose={handleOpen}
            aria-labelledby="transition-modal-title"
            aria-describedby="transition-modal-description"
            closeAfterTransition
            BackdropComponent={Backdrop}
            BackdropProps={{
              timeout: 500
            }}
          >
            <Box className={classes.dialog}>
              <DashboardContent />
            </Box>
          </Dialog>
        </>
      }
      <Snackbar open={openSnackbar.show} autoHideDuration={2000} onClose={handleSnackbarClose}>
        <Alert severity={openSnackbar.severity}>
          {openSnackbar.message}
        </Alert>
      </Snackbar>
    </>
  )
}
Example #13
Source File: ConsentComponent.js    From lifebank with MIT License 4 votes vote down vote up
ConsetComponent = () => {
  const [currentUser, { logout }] = useUser()
  const { t } = useTranslation('translations')
  const classes = useStyles()
  const [openConsent, setOpenConsent] = useState(false)
  const [openSnackbar, setOpenSnackbar] = useState(false)
  const theme = useTheme()
  const history = useHistory()
  const fullScreen = useMediaQuery(theme.breakpoints.down('sm'))
  const [maxWidthConset] = useState('sm')
  const [
    signup,
    { error: errorSignup, loading: signupLoading, data: { signup: signupResult } = {} }
  ] = useMutation(SIGNUP_MUTATION)

  const [
    loadProfile,
    { error: errorProfile, data: { profile: { profile } = {} } = {} }
  ] = useLazyQuery(PROFILE_QUERY, { fetchPolicy: 'network-only' })

  const { refetch: accountName } = useQuery(GET_ACCOUNT_NAME, {
    variables: {},
    skip: true
  })

  const [editProfile] = useMutation(EDIT_PROFILE_MUTATION)

  const handleOpenConsent = () => {
    setOpenConsent(!openConsent)
  }

  const handleSingup = () => {
    signup({
      variables: {
        profile
      }
    })
    handleOpenConsent()
  }

  const handleCloseSnackbar = () => {
    setOpenSnackbar({ ...openSnackbar, show: false })
  }

  const updateProfile = async () => {
    const { data: { user } } = await accountName({ account: currentUser.account })
    if (user.length > 0) {
      const name = user[0].name
      editProfile({
        variables: {
          profile: { name }
        }
      })
    }
  }

  useEffect(() => {
    if (currentUser) {
      loadProfile()
    }
  }, [currentUser])

  useEffect(() => {
    if (currentUser && profile && !profile.consent) handleOpenConsent()
  }, [profile, currentUser])

  useEffect(() => {
    if (signupResult) {
      if (signupResult.success) {
        if (profile.role === 'sponsor') updateProfile()
        setOpenSnackbar({
          show: true,
          message: t('signup.consentGranted'),
          severity: 'success'
        })
      } else {
        setOpenSnackbar({
          show: true,
          message: t('signup.consentError'),
          severity: 'error'
        })
      }
    }
  }, [t, signupResult, profile])

  useEffect(() => {
    if (errorProfile) {
      logout()
      history.replace('/reopen-account/' + currentUser.account)
    }
    if (errorSignup) {
      setOpenSnackbar({
        show: true,
        message: t('signup.consentError'),
        severity: 'error'
      })
    }
  }, [t, logout, history, currentUser, errorSignup, errorProfile])

  return (
    <>
      <Dialog
        fullScreen={fullScreen}
        maxWidth={maxWidthConset}
        open={openConsent}
        onClose={handleOpenConsent}
        aria-labelledby="transition-modal-title"
        aria-describedby="transition-modal-description"
        closeAfterTransition
        BackdropComponent={Backdrop}
        BackdropProps={{
          timeout: 500
        }}
      >
        <Box className={classes.dialogConset}>
          <Box className={classes.closeIcon}>
            <IconButton
              aria-label="close"
              color="inherit"
              size="small"
              onClick={handleOpenConsent}
            >
              <CloseIcon fontSize="inherit" />
            </IconButton>
          </Box>
          <Box>
            <Box className={classes.stepperContent}>
              <Typography className={classes.titleConsent}> {t('signup.termsAndConditions')}</Typography>
              <Typography variant="body1" className={classes.textConsent}>{t('signup.termsAndConditionsInfo')}</Typography>
            </Box>
            <SignupAccount account={profile ? profile.account : ""} />
            <SignupConsent onSubmit={handleSingup} loading={signupLoading} />
          </Box>
        </Box>
      </Dialog>
      <Snackbar open={openSnackbar.show} autoHideDuration={6000} onClose={handleCloseSnackbar}>
        <Alert severity={openSnackbar.severity}>
          {openSnackbar.message}
        </Alert>
      </Snackbar>
    </>
  )
}
Example #14
Source File: AcceptInvitation.jsx    From saasgear with MIT License 4 votes vote down vote up
function AcceptInvitation() {
  const { invitationToken } = useParams();
  const [teamInfo, setTeamInfo] = useState(null);
  const history = useHistory();
  const [verify, { data, loading, error }] = useLazyQuery(verifyTokenQuery);
  const {
    data: userInfo,
    error: getProfileError,
    loading: getProfileLoading,
  } = useQuery(getProfileQuery);
  const [joinTeam] = useMutation(joinTeamQuery);

  useEffect(() => {
    if (!getProfileLoading && userInfo?.profileUser) {
      if (userInfo?.profileUser) verify({ variables: { invitationToken } });
      else history.replace(`/auth/signin?invitation=${invitationToken}`);
    }
  }, [getProfileError, userInfo]);

  useEffect(() => {
    if (!loading && data?.verifyInvitationToken) {
      setTeamInfo(data.verifyInvitationToken);
    }
    if (error) {
      history.push('/auth/signin');
    }
  }, [data, error, loading]);

  async function handleUserJoinTeam(type) {
    try {
      await joinTeam({ variables: { token: invitationToken, type } });
      history.replace('/');
    } catch (e) {
      console.error(e);
    }
  }

  return loading && getProfileLoading ? (
    <div> Loading ....</div>
  ) : (
    <ForgotPasswordWrapper>
      <Overlay />
      <ForgotPasswordContainer>
        <div>
          <Logo />
        </div>
        <ForgotPasswordText>Accept Invitation?</ForgotPasswordText>
        <ForgotPasswordDescription>
          You&apos; ve been invitated to join{' '}
          <strong>{teamInfo?.teamName}</strong> by{' '}
          <strong>{teamInfo?.owner}</strong>
        </ForgotPasswordDescription>
        <ButtonGroup>
          <Button color="primary" onClick={() => handleUserJoinTeam('accept')}>
            Accept
          </Button>
          <Button onClick={() => handleUserJoinTeam('decline')}>Decline</Button>
        </ButtonGroup>
        <SquareIconTop>
          <svg
            width="496"
            height="482"
            viewBox="0 0 496 482"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
          >
            <path
              d="M0 1H445C472.614 1 495 23.3858 495 51V481H50C22.3858 481 0 458.614 0 431V1Z"
              stroke="#2291FF"
            />
          </svg>
        </SquareIconTop>
        <SmallSquareBottom>
          <svg
            width="195"
            height="195"
            viewBox="0 0 195 195"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
          >
            <path
              d="M0 0H145C172.614 0 195 22.3858 195 50V195H50C22.3858 195 0 172.614 0 145V0Z"
              fill="#0075E8"
            />
          </svg>
        </SmallSquareBottom>
        <SmallSquareTop>
          <svg
            width="114"
            height="121"
            viewBox="0 0 114 121"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
          >
            <path
              d="M0 0H64C91.6142 0 114 22.3858 114 50V121H50C22.3858 121 0 98.6142 0 71V0Z"
              fill="#1788F8"
            />
          </svg>
        </SmallSquareTop>
        <SmallSquareGrid>
          <svg
            width="131"
            height="123"
            viewBox="0 0 131 123"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
          >
            <g opacity="0.5">
              <path
                d="M129.844 121.5H1"
                stroke="white"
                strokeWidth="2"
                strokeLinecap="round"
                strokeLinejoin="round"
                strokeDasharray="1 40"
              />
              <path
                d="M129.844 81.5H1"
                stroke="white"
                strokeWidth="2"
                strokeLinecap="round"
                strokeLinejoin="round"
                strokeDasharray="1 40"
              />
              <path
                d="M129.844 41.5H1"
                stroke="white"
                strokeWidth="2"
                strokeLinecap="round"
                strokeLinejoin="round"
                strokeDasharray="1 40"
              />
              <path
                d="M129.844 1.5H1"
                stroke="white"
                strokeWidth="2"
                strokeLinecap="round"
                strokeLinejoin="round"
                strokeDasharray="1 40"
              />
            </g>
          </svg>
        </SmallSquareGrid>
        <SquareIconBottom>
          <svg
            width="594"
            height="523"
            viewBox="0 0 594 523"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
          >
            <path
              d="M1 1H544C571.614 1 594 23.3858 594 51V529H51C23.3858 529 1 506.614 1 479V1Z"
              stroke="#2291FF"
            />
          </svg>
        </SquareIconBottom>
        <CircleIcon>
          <svg
            width="60"
            height="60"
            viewBox="0 0 60 60"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
          >
            <circle cx="30" cy="30" r="29" stroke="#2291FF" />
          </svg>
        </CircleIcon>
      </ForgotPasswordContainer>
    </ForgotPasswordWrapper>
  );
}
Example #15
Source File: PlanSetting.jsx    From saasgear with MIT License 4 votes vote down vote up
PlanSetting = () => {
  const [isYearly, setIsYearly] = useState(false);
  const [selectedPlan, setSelectedPlan] = useState('');
  const { data: currentPlan } = useSelector((state) => state.userPlan);
  const [deleteUserPlanMutation, { error: errorDelete, loading: isDeletingUserPlan }] = useMutation(deleteUserPlanQuery);
  const [updateUserPlanMutation, { error: errorUpdate, loading: isUpdatingUserPlan }] = useMutation(updateUserPlanQuery);
  const [createUserPlanMutation, { error: errorCreate, loading: isCreatingUserPlan }] = useMutation(createUserPlanQuery);
  const [fetchUserPlan, { data: userPlanData }] = useLazyQuery(getUserPlanQuery);
  const dispatch = useDispatch();

  useEffect(() => {
    if (!isEmpty(currentPlan)) {
      setSelectedPlan(currentPlan.productType);
      setIsYearly(currentPlan.priceType === 'yearly');
    }
  }, [currentPlan])

  useEffect(() => {
    if (userPlanData?.getUserPlan) {
      dispatch(setUserPlan({ data: userPlanData?.getUserPlan }));
    }
  }, [userPlanData])

  function toggle() {
    setIsYearly(!isYearly);
  }

  function changePlan(name) {
    setSelectedPlan(name);
  }

  function checkIsCurrentPlan(planId) {
    return currentPlan.productType === planId && ((currentPlan.priceType === 'monthly' && !isYearly) || (currentPlan.priceType === 'yearly' && isYearly))
  }

  async function handleCancelSubscription() {
    await deleteUserPlanMutation({
      variables: { userPlanId: currentPlan.id }
    });
    fetchUserPlan();
  }

  async function createPaymentMethodSuccess(token) {
    const data = {
      paymentMethodToken: token,
      planName: planChanged.id,
      billingType: isYearly ? 'YEARLY' : 'MONTHLY',
    }
    await createUserPlanMutation({ variables: data});
    fetchUserPlan();
  }

  async function handleChangeSubcription() {
    await updateUserPlanMutation({ variables: {
      userPlanId: currentPlan.id,
      planName: planChanged.id,
      billingType: isYearly ? 'YEARLY' : 'MONTHLY',
    }});

    fetchUserPlan();
  }

  const planChanged = !!selectedPlan && plans.find(item => item.id === selectedPlan) || {};
  const amountCurrent = currentPlan.amount || 0;
  const amountNew = planChanged ? planChanged.price : 0;

  return (
    <ContentPage>
      <TitleContentStyle>Plan</TitleContentStyle>
      <Description>This is your subscription</Description>
      <Content>
        <LeftContent>
          <ToggleYearly>
            <Toggle onChange={toggle} label="Bill Yearly" />
          </ToggleYearly>
          <Plans
            plans={plans}
            onChange={changePlan}
            planChanged={planChanged}
            isYearly={isYearly}
            checkIsCurrentPlan={checkIsCurrentPlan}
          />
        </LeftContent>
        {!isEmpty(planChanged) && (
          <RightContent>
            {checkIsCurrentPlan(planChanged.id) ? (
              <CurrentPlanWrapper>
                {currentPlan.deletedAt ? (
                  <p>Plan will expire on <b>{dayjs(currentPlan.expiredAt).format('YYYY-MM-DD HH:mm')}</b></p>
                ) : (
                  <Button
                    color="primary"
                    disabled={isDeletingUserPlan}
                    onClick={handleCancelSubscription}
                  >Cancel Subcription</Button>
                )}
              </CurrentPlanWrapper>
            ) : (
              <PaymentWrapper>
                <SummaryTitle>Order Summary</SummaryTitle>
                <AmountList>
                  <AmountItem>
                    <AmoutText>Current subcription</AmoutText>
                    <Amount>${amountCurrent}</Amount>
                  </AmountItem>
                  <AmountItem>
                    <AmoutText>New subcription</AmoutText>
                    <Amount>${isYearly ? amountNew * 9 : amountNew}</Amount>
                  </AmountItem>
                  <AmountItem>
                    <AmoutText>Balance due right now</AmoutText>
                    <Amount>${Math.max((isYearly ? amountNew * 9 : amountNew) - amountCurrent, 0)}</Amount>
                  </AmountItem>
                </AmountList>
                {(isEmpty(currentPlan) || (currentPlan && currentPlan.deletedAt)) ? (
                  <StripeContainer
                    onSubmitSuccess={createPaymentMethodSuccess}
                    apiLoading={isCreatingUserPlan}
                    submitText={currentPlan && currentPlan.deletedAt && 'Change plan'}
                  />
                ) : (
                  <Button
                    color="primary"
                    onClick={handleChangeSubcription}
                    disabled={isUpdatingUserPlan}
                  >{isUpdatingUserPlan ? 'Please wait' : 'Change Subcription'}</Button>
                )}
              </PaymentWrapper>
            )}

            {errorCreate?.message && (
              <ErrorText message={errorCreate.message} />
            )}

            {errorUpdate?.message && (
              <ErrorText message={errorUpdate.message} />
            )}

            {errorDelete?.message && (
              <ErrorText message={errorDelete.message} />
            )}
          </RightContent>
        )}
      </Content>
    </ContentPage>
  );
}
Example #16
Source File: Action.jsx    From saasgear with MIT License 4 votes vote down vote up
ActionDocument = () => {
  const match = useRouteMatch();
  const history = useHistory();
  const documentId = parseInt(match.params.id, 10);
  const { handleSubmit, control, register, errors, setValue } = useForm({
    resolver: yupResolver(ActionDocumentSchema),
    mode: 'onChange',
  });
  const [
    createDocumentMutation,
    { loading: isCreating, error: createError },
  ] = useMutation(createDocumentQuery);
  const [
    updateDocumentMutation,
    { loading: isUpdating, error: updateError },
  ] = useMutation(updateDocumentQuery);
  const [fetchDocumentDetail, { data: documentData }] = useLazyQuery(
    getDocumentDetailQuery,
  );
  const [editorContent, setEditorContent] = useState('');

  useEffect(() => {
    if (documentId) {
      fetchDocumentDetail({ variables: { id: documentId } });
    }
  }, [documentId]);

  useEffect(() => {
    if (documentData?.getDocumentDetail) {
      const values = documentData.getDocumentDetail;
      setValue('name', values.name);
      setEditorContent(values.body);
    }
  }, [documentData]);

  async function onSubmit(data) {
    if (documentId) {
      await updateDocumentMutation({
        variables: {
          ...data,
          id: documentId,
        },
      });
    } else {
      await createDocumentMutation({ variables: data });
    }

    if (!createError && !updateError) {
      history.push('/document');
    }
  }

  return (
    <div>
      <Header>
        <TitlePageStyle>
          {documentData?.getDocumentDetail?.name
            ? documentData.getDocumentDetail.name
            : 'New Document'}
        </TitlePageStyle>
        <SaveBtn
          color="primary"
          onClick={handleSubmit(onSubmit)}
          disabled={isCreating || isUpdating}
        >
          {isCreating || isUpdating ? 'Please wait' : 'Save'}
        </SaveBtn>
      </Header>
      <ContentPage>
        <DocumentForm
          editorContent={editorContent}
          onSubmit={handleSubmit(onSubmit)}
          control={control}
          register={register}
          isSubmitting={isCreating || isUpdating}
          formErrors={errors}
          apiError={createError?.message || updateError?.message}
        />
      </ContentPage>
    </div>
  );
}
Example #17
Source File: LocationsPage.jsx    From trashpanda-fe with MIT License 4 votes vote down vote up
LocationsPage = ({ theme }) => {
  const { materialId } = useParams();
  const [zip, setZip] = useState("");
  const [loading, setLoading] = useState(false);
  const [locations, setLocations] = useState([]);
  const gps = JSON.parse(localStorage.getItem("gps"));
  const [getLocations, locationInfo] = useLazyQuery(GET_LOCATIONS);
  const [getPostal, postalInfo] = useLazyQuery(GET_POSTAL);
  const [getZip, zipInfo] = useLazyQuery(GET_ZIP);

  useEffect(() => {
    if (gps) {
      const { latitude, longitude } = gps;
      //Set zip code field to contain current users zip code location
      getZip({
        variables: {
          latitude: latitude.toString(),
          longitude: longitude.toString()
        }
      });

      //Search for nearby centers automatically
      setLoading(true);
      getLocations({
        variables: {
          latitude,
          longitude,
          material_id: parseInt(materialId)
        }
      });
    }
  }, [location]);

  useEffect(() => {
    if (zipInfo.called && zipInfo.data) {
      setZip(zipInfo.data.getZip.postal_code.slice(0, 5));
    }
  }, [zipInfo]);

  useEffect(() => {
    if (postalInfo.called && postalInfo.data) {
      const { longitude, latitude } = postalInfo.data.postal_code;
      getLocations({
        variables: {
          latitude,
          longitude,
          material_id: parseInt(materialId)
        }
      });
    }
    //invalid postal_codes still return objects but nothing that is resolved by our backend
    if (
      !postalInfo.loading &&
      postalInfo.postal_code !== 0 &&
      !locationInfo.loading &&
      locationInfo.called
    ) {
      setLoading(false);
    }
  }, [postalInfo]);

  useEffect(() => {
    if (locationInfo.called && locationInfo.data && !locationInfo.loading) {
      setLocations(locationInfo.data.locations);
      setLoading(false);
    }
  }, [locationInfo.loading, locationInfo.called, locationInfo.data]);

  const handleClick = () => {
    if (
      postalInfo.variables &&
      postalInfo.variables.postal_code &&
      postalInfo.variables.postal_code === zip
    ) {
      return;
    }

    if (validateZip(zip)) {
      setLoading(true);
      console.log("Searching for ", zip);
      getPostal({
        variables: {
          postal_code: zip
        }
      });
    } else alert("Please enter a valid 5-digit US zip code");
  };

  const handleKeyDown = e => {
    if (e.key === "Enter") if (zip.length >= 5) handleClick();
  };

  return (
    <Container>
      <Blurb>Where can I bring this?</Blurb>
      <ZipSearchBar
        handleClick={handleClick}
        value={zip}
        onChange={e => setZip(e.target.value)}
        btnDisabled={zip.length < 5 || loading}
        onKeyDown={handleKeyDown}
      />

      {loading ? (
        <Spinner />
      ) : (
        renderLocations(locations, locationInfo.called, theme)
      )}
    </Container>
  );
}