react-apollo#useQuery JavaScript Examples

The following examples show how to use react-apollo#useQuery. 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: index.js    From AdaptivApps-fe with MIT License 6 votes vote down vote up
export default function EventsCalendar() {
  const classes = useStyles();
  const { loading, error, data, refetch } = useQuery(GET_EVENT_LIST);
  // refetches EVENT_LIST without refreshing page
  useEffect(() => {
    refetch();
  }, [refetch]);
  if (loading) return <CircularProgress className={classes.loadingSpinner} />;
  if (error) return `Error! ${error.message}`;

  return (
    <main className={classes.root}>
      <Box className={classes.headingBox} borderBottom={2}>
        <Typography className={classes.heading} variant="h1" gutterBottom>
          Upcoming Events
        </Typography>
      </Box>
      <Grid className={classes.grid}>
        {data &&
          data?.events?.map((event, id) => (
            <EventCard key={id} event={event} />
          ))}
      </Grid>
    </main>
  );
}
Example #2
Source File: index.js    From AdaptivApps-fe with MIT License 6 votes vote down vote up
ManageEvents = () => {
  const classes = useStyles();
  // Getting all events
  const { data: eventsData, refetch: eventsRefetch } = useQuery(GET_EVENTS);

  return (
    <main className={classes.root}>
      <Box className={classes.headingBox} borderBottom={2}>
        <Typography className={classes.heading} variant="h1" gutterBottom>
          Manage Events
        </Typography>
      </Box>
      <Box>
        {/* Call the AdminEventList, which will contain a list of events */}
        {eventsData ? (
          <AdminEventList
            events={eventsData?.events}
            eventsRefetch={eventsRefetch}
          />
        ) : (
          <CircularProgress className={classes.loadingSpinner} />
        )}
      </Box>
    </main>
  );
}
Example #3
Source File: index.js    From AdaptivApps-fe with MIT License 6 votes vote down vote up
export default function MyEventDetails() {
  const classes = useStyles();
  // Retrieves ID of current event from parameters
  const { eventId } = useParams();
  // Retrieves logged in user info from Auth0
  const { user } = useAuth0();
  // Retrieves event details of specified event by ID which user is registered to
  const { loading, error, data, refetch } = useQuery(GET_EVENT_DETAILS, {
    variables: { id: eventId, email: user.email },
  });
  useEffect(() => {
    refetch();
  }, [refetch]);
  if (loading) return <CircularProgress className={classes.loadingSpinner} />;
  if (error) return `Error! ${error.message}`;

  const activeEvent = data.events;

  return (
    <main className={classes.root}>
      <Box className={classes.headingBox} borderBottom={2}>
        <Link href="/myevents" className={classes.linkBack}>
          <ArrowBackIosIcon color="primary" fontSize="large" />
          Back to my events
        </Link>
        <Typography variant="h1" gutterBottom>
          Event Details
        </Typography>
      </Box>
      {activeEvent &&
        activeEvent.map((event, id) => <EventDetails key={id} event={event} />)}
    </main>
  );
}
Example #4
Source File: index.js    From AdaptivApps-fe with MIT License 6 votes vote down vote up
UserProfile = () => {
  const { user } = useAuth0();

  const [createProfile] = useMutation(ADD_USER_PROFILE);
  const [updateProfile] = useMutation(UPDATE_USER_PROFILE);

  // Fetch profile for the user using the email associated with auth0 login
  const { loading, error, data } = useQuery(PROFILE_INFO, {
    variables: { email: user && user.email },
  });
  const profile = data && data.profile;

  // Extract the profile from returning data of useQuery
  useEffect(() => {
    if (error) {
      return <p>Error</p>;
    }
    // If user does not have a profile in backend, create one for them
    if (!loading && !profile) {
      newProfile();
    }

    // eslint-disable-next-line
  }, [profile]);

  // Function that creates a profile for given email
  const newProfile = async () => {
    await createProfile({ variables: { email: user.email } });
  };

  return (
    <ProfileForm
      loading={loading}
      profile={profile ? profile : null}
      user={user}
      updateProfile={updateProfile}
    />
  );
}
Example #5
Source File: index.js    From AdaptivApps-fe with MIT License 5 votes vote down vote up
export default function ActivityList() {
  const classes = useStyles();
  const { eventId } = useParams();
  const { loading, error, data: activityData } = useQuery(
    GET_EVENT_ACTIVITIES,
    {
      variables: { id: eventId },
    }
  );
  if (loading) return <CircularProgress className={classes.loadingSpinner} />;
  if (error) return `Error! ${error.message}`;
  return (
    <main className={classes.root}>
      <Box className={classes.headingBox} borderBottom={2}>
        <Typography className={classes.heading} variant="h1" gutterBottom>
          Event Activities
        </Typography>
      </Box>
      <Box className={classes.eventContainer}>
        <Box className={classes.imgContainer}>
          <img
            className={classes.eventImg}
            src={activityData && activityData?.event?.imgUrl}
            alt="Event"
          />
        </Box>
        <Box className={classes.infoContainer}>
          <Typography
            className={classes.date}
            variant="body2"
            color="textSecondary"
            component="p"
          >
            {activityData.event.startDate}-{activityData.event.endDate}
          </Typography>
          <Typography className={classes.title}>
            {activityData.event.title}
          </Typography>
          <Typography
            className={classes.loc}
            variant="body2"
            color="textSecondary"
            component="p"
          >
            {activityData.event.location}
          </Typography>
        </Box>
      </Box>
      <Box className={classes.details}>{activityData.event.details}</Box>
      {activityData.event.activities.length >= 1 ? (
        <Box className={classes.activityC}>
          <p>Activities Schedule</p>
          <table className={classes.table}>
            <tbody>
              <tr className={classes.headerRow}>
                <th className={classes.tableH}>Name</th>
                <th className={classes.tableH}>Date</th>
                {activityData.event.type === "In Person" ? (
                  <th className={classes.tableH}>Location</th>
                ) : null}
                <th className={classes.tableH}>Time</th>
              </tr>
              {activityData &&
                activityData?.event?.activities.map((activity, id) => (
                  <Activities
                    key={id}
                    activity={activity}
                    activityData={activityData}
                  />
                ))}
            </tbody>
          </table>
        </Box>
      ) : null}
    </main>
  );
}
Example #6
Source File: UsersList.js    From AdaptivApps-fe with MIT License 5 votes vote down vote up
UsersList = () => {
  const classes = useStyles();
  const { data } = useQuery(GET_PROFILES);

  return (
    <Container className={classes.root} m="0 2% 0 2%">
      <MaterialTable
        title="Registered Users"
        data={data?.profiles}
        columns={[
          { title: "Firstname", field: "firstName" },
          { title: "Lastname", field: "lastName" },
          { title: "Birthday", field: "birthday" },
          { title: "Disability", field: "disability" },
          { title: "Legal Status", field: "legal" },
        ]}
        options={{
          selection: true,
          search: true,
          showTitle: false,
          paging: true,
          emptyRowsWhenPaging: false,
          filtering: true,
          cellStyle: {
            fontSize: "1.2rem",
          },
          headerStyle: {
            fontSize: "1.2rem",
          },
        }}
        actions={[
          {
            tooltip: "Send a message to all selected users",
            icon: "message",
            onClick: (evt, data) =>
              alert("Send messages to " + data.length + " users?"),
          },
        ]}
      />
    </Container>
  );
}
Example #7
Source File: index.js    From AdaptivApps-fe with MIT License 5 votes vote down vote up
export default function MyEvents() {
  const classes = useStyles();
  // Retrieves logged in user info
  const { user } = useAuth0();
  // Retrieves all events a user is registered to
  const { error, loading, data, refetch } = useQuery(GET_USER_EVENTS, {
    variables: { email: user.email },
  });

  useEffect(() => {
    refetch();
  }, [refetch]);

  if (loading) return <CircularProgress className={classes.loadingSpinner} />;
  if (error) return `Error! ${error.message}`;
  return (
    <main className={classes.root}>
      <Box className={classes.headingBox} borderBottom={2}>
        <Typography className={classes.heading} variant="h1" gutterBottom>
          My Events
        </Typography>
      </Box>
      {data.events.length >= 1 ? (
        <Grid className={classes.grid}>
          {data &&
            data?.events?.map((event, id) => (
              <MyEventCard key={id} event={event} refetch={refetch} />
            ))}
        </Grid>
      ) : (
        <>
          <Typography className={classes.noActiv}>
            You haven't registered for any events yet!
          </Typography>
          <Box className={classes.inlineNotice}>
            <Typography className={classes.noActivBlue}>
              Check out the Events Calendar
            </Typography>
            <Typography>
              , register for an event, then see all of your registered events
              here!
            </Typography>
          </Box>
        </>
      )}
    </main>
  );
}
Example #8
Source File: ViewAllBusiness.panel.jsx    From dineforward with MIT License 5 votes vote down vote up
AddRestaurantPanel = props => {
  const classes = useStyles();

  // const [addBizRequest, { data, loading, error }] = useMutation(CREATE_BIZ, {
  //   onCompleted: data => console.log(`completed - ${data}`),
  //   onError: error => console.log(`error - ${error}`),
  // });

  const { loading, error, data } = useQuery(VIEW_ALL_BUINESSES, gqlEvents);

  const [place, setPlace] = React.useState({});
  const [businessInfo, setBusinessInfo] = React.useState({});
  if (loading) return <b>Loading...</b>;
  if (error) return <b>Error - {error}</b>;
  if (!error && !loading && data) {
    return (
      <Box className={classes.panel}>
        <div className={classes.panelContent}>
          <Grid container spacing={5}>
            <Grid item md={12}>
              <Typography variant="h3">All businesses</Typography>
              <Link href="businesses/new">
                <a>
                  <button>Add a new business</button>
                </a>
              </Link>
            </Grid>
            <Grid item md={12}>
              <MaterialTable
                data={data.allBusinesses}
                columns={[
                  { title: 'Name', field: 'name' },
                  { title: 'Status', field: 'status' },
                  { title: 'Location', field: 'location.formattedAddress' },
                  { title: 'Backers', field: '_backersMeta.count', type: 'numeric' },
                  { title: 'Staff Count', field: '_staffMembersMeta.count', type: 'numeric' },
                ]}
                title="Your businesses"
              />
            </Grid>
          </Grid>
        </div>
      </Box>
    );
  }
}
Example #9
Source File: InfoBar.js    From AdaptivApps-fe with MIT License 4 votes vote down vote up
function InfoBar({ user, setAlertOpen, setNewRoom, setDeleteRoom }) {
    const classes = useStyles();

    const [open, setOpen] = useState(false);
    const [announcement, setAnnouncementOpen] = useState(false);
    const [searchRecipient, setSearchRecipient] = useState("");
    const [results, setResults] = useState([]);

    const { loading, error, data, refetch, subscribeToMore } = useQuery(GET_CHAT_ROOMS, { variables: { email: user.email } });
    const { data: recipients } = useQuery(GET_RECIPIENTS);
    const { data: announcements } = useQuery(GET_ANNOUNCEMENTS, { variables: { isAnnouncementRoom: true } });
    const { data: chats, refetch: refetchProfile }  = useQuery(GET_USER_PROFILE, { variables: { email: user.email } });

    // Chat Room Subscription
    const _subscribeToNewChatRoom = subscribeToMore => {
      subscribeToMore({
        document: CHAT_ROOM_SUBSCRIPTION,
        updateQuery: (prev, {subscriptionData }) => {
          if (!subscriptionData.data) return prev
          const chatRoom = subscriptionData.data.chatRoom
          refetch();
          refetchProfile();
          return Object.assign({}, prev, {
            profile: {
              chatRooms: [chatRoom, ...prev.profile.chatRooms],
              __typename: prev.profile.__typename
            }
          })
        }
      })
    };

    _subscribeToNewChatRoom(subscribeToMore);

    // Convert announcement object to Array & filter out notifications
    const announcementArray = announcements && Object.values(announcements)

    const notifications = announcementArray && announcementArray.map(ann => {
     return ann.filter(item => item.notification.length > 0 && item.notification)})
   
    // Make sure no participants pass through with a null or empty name
    const validParticipants = [];

    recipients && recipients.profiles.map(user => {
      if (user.firstName !== null && user.lastName !== null && 
          user.firstName !== '' && user.lastName !== '') {
            validParticipants.push(user);
      };
    });

    if (loading) return <CircularProgress className={classes.loadingSpinner} />;
    if (error) return `Error! ${error.message}`;

    // Load a user's chat rooms via participant names
    const participants = data && data?.profile.chatRooms.map(item => item !== null && item.participants).concat().flat();

    // Search for a chat room
    const searchRooms = e => {
      e.preventDefault();
      let filter = data && data?.profile.chatRooms.map(room => {
        let users = room.participants.map(user => {
          if (user.firstName !== null && user.lastName !== null &&
              user.firstName !== '' && user.lastName !== '') {
          return `${user.firstName.toLowerCase()} ${user.lastName.toLowerCase()}`;
        }});
        return users.filter(user => {
          if (user.includes(searchRecipient.toLowerCase())) {
            results.push(room);
            return results;
          } else if (searchRecipient === "all" || searchRecipient === "All") {
            return participants;
          };
        });
      });
      setSearchRecipient('');
    };

    const handleOpen = () => {
      setOpen(true);
    };
    
    const handleClose = () => {
      setOpen(false);
    };

    const handleChange = e => {
      setResults([]);
      setSearchRecipient(e.target.value);
    };

    const handleAnnouncementOpen = () => {
      setAnnouncementOpen(true);
    };

    const handleAnnouncementClose = () => {
      setAnnouncementOpen(false);
    };

    return (
      <div className={classes.root}>
        <h1 className={classes.header}>Messages</h1>
        <div className={classes.messageIcons}>
          <CreateIcon className={classes.icons} onClick={handleOpen} />
            <span className={classes.span} onClick={handleOpen} aria-label="New Message Button">New Message</span>
        </div>
        <Modal
          aria-labelledby="transition-modal-title"
          aria-describedby="transition-modal-description"
          className={classes.modal}
          open={open}
          onClose={handleClose}
          closeAfterTransition
          BackdropComponent={Backdrop}
          BackdropProps={{
            timeout: 500,
          }}>
          <RecipientModal user={user} setOpen={setOpen} setNewRoom={setNewRoom} participants={participants} validParticipants={validParticipants} />
        </Modal> 
        {user && user[config.roleUrl].includes("Admin") ? 
        (
          <>
            <div className={classes.messageIcons}>
              <LanguageIcon className={classes.icons} /><span className={classes.span} onClick={handleAnnouncementOpen} aria-label="New Announcement Button">New Announcement</span> 
          </div>
          <Modal
            aria-labelledby="transition-modal-title"
            aria-describedby="transition-modal-description"
            className={classes.modal}
            open={announcement}
            onClose={handleAnnouncementClose}
            closeAfterTransition
            BackdropComponent={Backdrop}
            BackdropProps={{
              timeout: 500,
            }}>
            <AnnouncementModal user={user} validParticipants={validParticipants} setAnnouncementOpen={setAnnouncementOpen} setAlertOpen={setAlertOpen} />
           </Modal>
          </>
        ) : null}
        <div className={classes.chatRoomDiv}>
          <AnnouncementRoom notifications={notifications} key='announcement_room' user={user} chats={chats}/>
          <Divider variant="inset" className={classes.divider} />
          {results.length > 0 ? 
            (results.map((chatRoom, id) => (
              <div className={classes.chatroom} key={id}>
                <ChatRoom chatRoom={chatRoom} user={user} setDeleteRoom={setDeleteRoom} chats={chats}/>
                <Divider variant="inset" className={classes.divider} />
              </div>
            )))
            :
            (data.profile.chatRooms === undefined ? null : 
            (data && data?.profile.chatRooms?.map((chatRoom, id) => (
              <div className={classes.chatroom} key={id}>
                <ChatRoom chatRoom={chatRoom} user={user} setDeleteRoom={setDeleteRoom} chats={chats} />
                <Divider variant="inset" className={classes.divider} />
              </div>
            ))))
          }
        </div>
          <Tooltip title="Type 'all' or 'All' to clear search results">
            <Box component="div" className={classes.box}>
              <TextField
                className={classes.searchBox}
                variant="outlined"
                type="text"
                name="message"
                placeholder="Search Messages..."
                aria-label="Search Chatrooms"
                value={searchRecipient}
                onChange={handleChange}
                InputProps={{
                  endAdornment: 
                  <InputAdornment position="end">
                    <IconButton onClick={searchRooms} aria-label="Search Chatrooms">
                      <SearchIcon fontSize="large" />
                    </IconButton>
                  </InputAdornment>
                }} />
            </Box>
          </Tooltip>
      </div>
    )
}
Example #10
Source File: Announcements.js    From AdaptivApps-fe with MIT License 4 votes vote down vote up
export default function Announcements({ user, setUpdateChat, setDeleteChat }) {
  const classes = useStyles();

  const [announcementOpen, setAnnouncementOpen] = useState(false);
  const [announcementToEdit, setAnnouncementToEdit] = useState();

  const [deleteAnnouncement] = useMutation(DELETE_ANNOUNCEMENT);

  const { loading, error, data } = useQuery(GET_ANNOUNCEMENTS, { variables: { isAnnouncementRoom: true } });

  const announcements = data && data?.announcements?.map((announcement) => {return {
      id: announcement.id,
      title: announcement.title,
      message: announcement.message,
      createdAt: announcement.createdAt,
      notification: announcement.notification      
    }
  });

  // Sets up an auto-scroll to last announcement when new announcement received, or when an announcement is updated/deleted
  const announcementsEndRef = useRef(null)

  const scrollToBottom = () => {
    announcementsEndRef.current && announcementsEndRef.current.scrollIntoView({ behavior: "smooth" });
  };


  useEffect(() => {

    scrollToBottom()
  }, [announcements]);

  const handleClose = () => {
    setAnnouncementOpen(false);
  };

  // Delete an announcement
  const deleteMessage = async (announcement) => {
    await deleteAnnouncement({
      variables: { id: announcement.id }
    });
    setDeleteChat(true);
  };

  if (loading) return <CircularProgress className={classes.loadingSpinner} />;
  if (error) return `Error! ${error.message}`;

  return (
    <div className={classes.root}>
      <div className={classes.messageDiv}>
        {announcements.map((announcement) => (
          <>
            <div key={announcement.id} className={classes.messageBox}>
              <div className={classes.userMessage}>
                <div className={classes.messageHeader}>
                  <p className={classes.sender}>{announcement.title}</p>
                  {user && user[config.roleUrl].includes("Admin") ? (
                  <div className={classes.iconDiv}>
                  <Tooltip title="Edit Announcement">
                    <EditOutlinedIcon className={classes.editIcon} onClick={() => {setAnnouncementOpen(true); setAnnouncementToEdit(announcement)}} />
                  </Tooltip>
                  <Tooltip title="Delete Announcement">
                    <DeleteIcon className={classes.deleteIcon} onClick={() => deleteMessage(announcement)} />
                  </Tooltip>
                  </div>) : null}
                </div>
                <p className={classes.messageText}>{announcement.message}</p>
                <div ref={announcementsEndRef} />
              </div>
            </div>
          </>
        ))}
        <Modal
          aria-labelledby="transition-modal-title"
          aria-describedby="transition-modal-description"
          className={classes.modal}
          open={announcementOpen}
          onClose={handleClose}
          closeAfterTransition
          BackdropComponent={Backdrop}
          BackdropProps={{
            timeout: 500,
          }}>
          <EditAnnouncementModal setAnnouncementOpen={setAnnouncementOpen} announcement={announcementToEdit} setUpdateChat={setUpdateChat} />
        </Modal>
      </div>
    </div>
  )
}
Example #11
Source File: AdminActivityList.js    From AdaptivApps-fe with MIT License 4 votes vote down vote up
AdminActivityList = props => {
  const classes = useStyles();
  // Grab the event id from props
  const event_id = props.event_id;
  // Call backend to fetch the one event associated with event id
  const { data, refetch } = useQuery(GET_ONE_EVENT, {
    variables: {
      id: event_id,
    },
  });

  // Declares C, U, and D for activities
  const [CreateActivity] = useMutation(CREATE_ACTIVITY);
  const [UpdateActivity] = useMutation(UPDATE_ACTIVITY);
  const [DeleteActivity] = useMutation(DELETE_ACTIVITY);

  // Similar to its parent component, activities list will be displayed
  // Using material table.
  return (
    <Grid>
      <MaterialTable
        title=""
        columns={[
          {
            title: "Name",
            field: "name",
            editComponent: props => (
              <>
                <Input
                  type="text"
                  value={props.value}
                  onChange={e => props.onChange(e.target.value)}
                />
                <InputLabel className={classes.label}>*Required</InputLabel>
              </>
            ),
          },
          {
            title: "Date",
            field: "startDate",
            editComponent: props => (
              <>
                <Input
                  type="date"
                  value={props.value}
                  onChange={e => props.onChange(e.target.value)}
                />
                <InputLabel className={classes.label}>*Required</InputLabel>
              </>
            ),
          },
          {
            title: "Time",
            field: "startTime",
            editComponent: props => (
              <>
                <Input
                  type="time"
                  value={props.value}
                  onChange={e => props.onChange(e.target.value)}
                />
                <InputLabel className={classes.label}>*Required</InputLabel>
              </>
            ),
          },
          {
            title: "Location",
            field: "location",
            editComponent: props => (
              <Input
                type="text"
                value={props.value}
                onChange={e => props.onChange(e.target.value)}
              />
            ),
          },
          {
            title: "Link",
            field: "link",
            render: rowData => (
              <div
                style={{
                  fontSize: "1.4rem",
                  width: "22rem",
                  overflow: "scroll",
                }}
              >
                {rowData.link}
              </div>
            ),
            editComponent: props => (
              <Input
                type="text"
                value={props.value}
                onChange={e => props.onChange(e.target.value)}
              />
            ),
          },
          {
            title: "Type",
            field: "type",
            editComponent: props => (
              <Input
                type="text"
                value={props.value}
                onChange={e => props.onChange(e.target.value)}
              />
            ),
          },
          {
            title: "Details",
            field: "details",
            render: rowData => (
              <div
                style={{
                  fontSize: "1.4rem",
                  width: "30rem",
                  maxHeight: "13rem",
                  overflow: "scroll",
                }}
              >
                {rowData.details}
              </div>
            ),
            editComponent: props => (
              <textarea
                style={{
                  fontSize: "1.4rem",
                }}
                rows="7"
                cols="60"
                type="text"
                value={props.value}
                onChange={e => props.onChange(e.target.value)}
              />
            ),
          },
        ]}
        data={data?.event?.activities}
        editable={{
          onRowAdd: async newData => {
            await CreateActivity({
              variables: {
                name: newData.name,
                startDate: newData.startDate,
                startTime: newData.startTime,
                location: newData.location,
                link: newData.link,
                type: newData.type,
                details: newData.details,
                event_id: event_id,
              },
            });
            refetch();
          },
          onRowUpdate: async (newData, oldData) => {
            await UpdateActivity({
              variables: {
                id: oldData.id,
                name: newData.name,
                startDate: newData.startDate,
                startTime: newData.startTime,
                location: newData.location,
                link: newData.link,
                type: newData.type,
                details: newData.details,
              },
            });
            refetch();
          },
          onRowDelete: async oldData => {
            await DeleteActivity({
              variables: {
                id: oldData.id,
              },
            });
            refetch();
          },
        }}
        icons={{
          Add: () => (
            <>
              <AddCircleOutlineIcon
                style={{ color: "#2962FF" }}
                fontSize="large"
              />
              <Button className={classes.addBtn}>Add Activity</Button>
            </>
          ),
          Edit: () => (
            <EditIcon style={{ color: "#2962FF" }} fontSize="large" />
          ),
          Delete: () => (
            <DeleteIcon style={{ color: "#2962FF" }} fontSize="large" />
          ),
        }}
        options={{
          cellStyle: {
            fontSize: "1.4rem",
          },
          headerStyle: {
            fontSize: "3.4rem",
            backgroundColor: "#2962FF",
            color: "#FFF",
          },
          search: false,
          showTitle: true,
          paging: false,
          emptyRowsWhenPaging: false,
          toolbarButtonAlignment: "left",
        }}
      />
    </Grid>
  );
}
Example #12
Source File: EventDetails.js    From AdaptivApps-fe with MIT License 4 votes vote down vote up
export default function EventDetails(props) {
  const classes = useStyles();
  const activeEvent = props.event;
  const eventId = activeEvent.id;
  const { user } = useAuth0();
  const { loading, error, data, refetch } = useQuery(GET_USER_ACTIVITIES, {
    variables: { id: eventId, email: user.email },
  });

  useEffect(() => {
    refetch();
  }, [refetch]);

  if (loading) return <CircularProgress className={classes.loadingSpinner} />;
  if (error) return `Error! ${error.message}`;

  const currentActivities = data.activities;
  return (
    <Box className={classes.root} m={4}>
      <Box className={classes.topContentContainer}>
        <Box>
          <img src={activeEvent.imgUrl} alt="Event" />
        </Box>
        {activeEvent.type === "Webinar" ? (
          <Box className={classes.topContentText} m="2.4rem">
            <p>{activeEvent.startDate}</p>
            <h2>{activeEvent.title}</h2>
            <Typography variant="subtitle1">{activeEvent.location}</Typography>
            <p>Start time: {activeEvent.startTime}</p>
          </Box>
        ) : (
          <Box className={classes.topContentText} m="2.4rem">
            <p>
              {activeEvent.startDate} - {activeEvent.endDate}
            </p>
            <h2>{activeEvent.title}</h2>
            <Typography variant="subtitle1">{activeEvent.location}</Typography>
          </Box>
        )}
        <Link
          className={classes.donateBtn}
          color="primary"
          href="https://app.mobilecause.com/vf/ANGEL"
          target="_blank"
          rel="noopener"
        >
          DONATE NOW
        </Link>
      </Box>
      <Box className={classes.detailsContainer}>
        <Typography className={classes.details} variant="body1">
          {activeEvent.details}
        </Typography>
      </Box>

      {activeEvent.type === "Webinar" ? (
        <Box className={classes.webinarBox}>
          <p>Hosted by: {activeEvent.host}</p>
          <p>Special Guest Speaker(s): {activeEvent.speakers}</p>
          <a href={activeEvent.link} rel="noopener noreferrer" target="_blank">
            Click Here to Join Us!
          </a>
        </Box>
      ) : null}
      <>
        {currentActivities.length >= 1 ? (
          <Box className={classes.myActivitiesBox}>
            <p>My Activities</p>
            <table className={classes.table}>
              <tbody>
                <tr className={classes.headerRow}>
                  <th className={classes.tableH}>Name</th>
                  <th className={classes.tableH}>Date</th>
                  <th className={classes.tableH}>Location</th>
                  <th className={classes.tableH}>Time</th>
                  <th className={classes.tableH}>My Role</th>
                </tr>
                {currentActivities &&
                  currentActivities.map((activity, id) => (
                    <ActivityDetails key={id} activity={activity} />
                  ))}
              </tbody>
            </table>
          </Box>
        ) : null}
      </>
      <Box className={classes.sponsorBox}>
        {activeEvent?.sponsors?.length > 0 ? (
          <Typography variant="h3">Special thanks to our sponsors!</Typography>
        ) : null}
        <ul>
          {activeEvent.sponsors.length > 0
            ? activeEvent?.sponsors
                ?.split(", ")
                .map(sponsor => <li>{sponsor}</li>)
            : null}
        </ul>
      </Box>
    </Box>
  );
}
Example #13
Source File: MyEventCard.js    From AdaptivApps-fe with MIT License 4 votes vote down vote up
export default function MyEventCard({ event, refetch }) {
  const classes = useStyles();
  const navigate = useNavigate();
  // Retrieves current user info from Auth0
  const { user } = useAuth0();
  const { data } = useQuery(GET_PARTICIPANT_IDS, {
    variables: { email: user.email, id: event.id },
    fetchPolicy: "no-cache",
  });
  const [unregisterFromAll] = useMutation(UNREGISTER_FROM_ALL);
  const [unregisterFromEventActivity] = useMutation(
    UNREGISTER_FROM_EVENT_ACTIVITY
  );
  // Unregisters user from specified event and all it's activities
  const unregisterFromEvent = async () => {
    const participantIds = data?.participants?.map(participant => {
      return participant.id;
    });

    const participantIdValue = data?.participants?.map(participant => {
      return participant.id;
    });

    const participantId = JSON.stringify(participantIdValue).replace(
      /[\[\]"]+/g,
      ""
    );

    data && data?.participants?.length === 1
      ? await unregisterFromEventActivity({
          variables: {
            id: event.id,
            email: user.email,
            participantId: participantId,
          },
        })
      : data && data?.participants === null
      ? await unregisterFromEvent({
          variables: {
            id: event.id,
            email: user.email,
          },
        })
      : await unregisterFromAll({
          variables: {
            id: event.id,
            email: user.email,
            participantIds: participantIds,
          },
        });
    await refetch();
  };
  const viewEventDetails = async () => {
    await navigate(`/myevents/${event?.id}`);
  };

  return (
    <Card className={classes.root}>
      <CardActionArea className={classes.card}>
        <Box>
          <div className={classes.banner}>{event.type}</div>
          <CardMedia
            className={classes.cardImg}
            component="img"
            alt="Event"
            width="15rem"
            image={event?.imgUrl}
            title="Angel City Event"
          />
        </Box>
        <CardContent className={classes.content}>
          <Typography
            className={classes.cardDate}
            variant="body2"
            color="textSecondary"
            component="p"
          >
            {event.startDate} - {event.endDate}
          </Typography>
          <Typography
            className={classes.cardTitle}
            gutterBottom
            variant="h5"
            component="h2"
          >
            {event.title}
          </Typography>
          <Typography
            className={classes.cardLoc}
            variant="body2"
            color="textSecondary"
            component="p"
          >
            {event.location}
          </Typography>
        </CardContent>
      </CardActionArea>
      <CardActions className={classes.btnContainer}>
        <Button onClick={viewEventDetails} className={classes.btn}>
          View Details
        </Button>
        <Button className={classes.btn} onClick={unregisterFromEvent}>
          Unregister
        </Button>
      </CardActions>
    </Card>
  );
}
Example #14
Source File: ProfileForm.js    From AdaptivApps-fe with MIT License 4 votes vote down vote up
ProfileForm = ({ loading, profile, user, updateProfile }) => {
  const [updated, setUpdated] = useState(false);
  const [userProfile, setUserProfile] = useState(null);
  const classes = useStyles();

  const { refetch: refetchProfile } = useQuery(GET_USER_PROFILE, { variables: { email: user.email } });

  const { handleSubmit, register, setValue, control } = useForm({
    mode: "onSubmit",
    validationSchema: ProfileSchema,
    defaultValues: {
      email: user && user.email,
      firstName: userProfile && userProfile.firstName,
      lastName: userProfile && userProfile.lastName,
      displayName: userProfile && userProfile.displayName,
      birthday: userProfile && userProfile.birthday,
      bio: userProfile && userProfile.bio,
      disability: userProfile && userProfile.disability,
    },
  });

  // updates profile in the backend and frontend
  const onSubmit = (formValues, e) => {
    e.preventDefault();

    // backend update
    updateProfile({
      variables: {
        email: user.email,
        firstName:
          formValues.firstName === ""
            ? userProfile.firstName
            : formValues.firstName,
        lastName:
          formValues.lastName === ""
            ? userProfile.lastName
            : formValues.lastName,
        displayName:
          formValues.displayName === ""
            ? userProfile.displayName
            : formValues.displayName,
        birthday:
          formValues.birthday === ""
            ? userProfile.birthday
            : formValues.birthday,
        bio: formValues.bio === "" ? userProfile.bio : formValues.bio,
        disability:
          formValues.disability === ""
            ? userProfile.disability
            : formValues.disability,
        legal: formValues.legal === "" ? userProfile.legal : formValues.legal,
      },
    });

    // frontend update
    setUserProfile({
      email: user.email,
      firstName:
        formValues.firstName === ""
          ? userProfile.firstName
          : formValues.firstName,
      lastName:
        formValues.lastName === "" ? userProfile.lastName : formValues.lastName,
      displayName:
        formValues.displayName === ""
          ? userProfile.displayName
          : formValues.displayName,
      birthday:
        formValues.birthday === "" ? userProfile.birthday : formValues.birthday,
      bio: formValues.bio === "" ? userProfile.bio : formValues.bio,
      disability:
        formValues.disability === ""
          ? userProfile.disability
          : formValues.disability,
      legal: formValues.legal === "" ? userProfile.legal : formValues.legal,
    });

    refetchProfile();
  };

  // updates form fields with new values
  useEffect(() => {
    if (!loading && !userProfile) setUserProfile(profile);
    if (!loading && userProfile) {
      setValue([
        { firstName: userProfile && userProfile.firstName },
        { lastName: userProfile && userProfile.lastName },
        { displayName: userProfile && userProfile.displayName },
        { birthday: userProfile && userProfile.birthday },
        { bio: userProfile && userProfile.bio },
        { disability: userProfile && userProfile.disability },
        { legal: userProfile && userProfile.legal },
      ]);
    }
  }, [loading, userProfile, setValue, profile]);

  // alerts user to successful update, handy for screen readers
  const handleUpdated = () => {
    refetchProfile();
    alert("Profile updated successfully!");
    setUpdated(false);
  };

  const userPicture = user && user.picture;

  return (
    <main className={classes.root}>
      <Box className={classes.headingBox} borderBottom={2}>
        <Typography variant="h1" gutterBottom>
          Account Information
        </Typography>
      </Box>
      <Container className={classes.profileContainer}>
        <Box className={classes.profileInfo}>
          <img className={classes.profileImg} src={userPicture} alt="Profile" />
          <Box className={classes.profileText}>
            <Typography>
              {userProfile && userProfile.firstName !== null
                ? `${userProfile && userProfile.firstName} ${userProfile &&
                    userProfile.lastName}`
                : user && user.name}{" "}
            </Typography>
            <Typography>{user && user.email}</Typography>
          </Box>
        </Box>

        <Typography className={classes.personalInfo} variant="h2" gutterBottom>
          Personal Information
        </Typography>
        <form className={classes.form} onSubmit={handleSubmit(onSubmit)}>
          <Box component="div" className={classes.formBox}>
            <Box className={classes.box}>
              <InputLabel className={classes.inputLabel} htmlFor="firstName">
                First Name
              </InputLabel>
              <Controller
                as={<TextField />}
                className={classes.input}
                id="firstName"
                variant="outlined"
                type="text"
                placeholder={userProfile ? userProfile.firstName : ""}
                name="firstName"
                control={control}
                inputProps={{
                  classes: {
                    input: classes.resize,
                  },
                }}
              />
            </Box>
            <Box className={classes.box}>
              <InputLabel className={classes.inputLabel} htmlFor="lastName">
                Last Name
              </InputLabel>
              <Controller
                as={<TextField />}
                className={classes.input}
                id="lastName"
                type="text"
                variant="outlined"
                placeholder={userProfile ? userProfile.lastName : ""}
                name="lastName"
                control={control}
                inputProps={{
                  classes: {
                    input: classes.resize,
                  },
                }}
              />
            </Box>
          </Box>
          <Box className={classes.formBox}>
            <Box className={classes.box}>
              <InputLabel className={classes.inputLabel} htmlFor="displayName">
                Display Name
              </InputLabel>
              <Controller
                as={<TextField />}
                className={classes.input}
                id="displayName"
                type="text"
                variant="outlined"
                placeholder={userProfile ? userProfile.displayName : ""}
                name="displayName"
                control={control}
                inputProps={{
                  classes: {
                    input: classes.resize,
                  },
                }}
              />
            </Box>
            <Box className={classes.box}>
              <InputLabel className={classes.inputLabel} htmlFor="birthday">
                Date of Birth
              </InputLabel>
              <Controller
                as={<TextField />}
                className={classes.input}
                id="birthday"
                type="text"
                variant="outlined"
                name="birthday"
                placeholder={userProfile ? userProfile.birthday : "mm/dd/yyyy"}
                control={control}
                inputProps={{
                  classes: {
                    input: classes.resize,
                  },
                }}
              />
            </Box>
          </Box>

          <Box className={classes.formBox}>
            <Box className={classes.box}>
              <InputLabel className={classes.inputLabel} htmlFor="bio">
                Bio
              </InputLabel>
              <Controller
                as={<TextField />}
                className={classes.bio}
                id="bio"
                name="bio"
                variant="outlined"
                multiline={true}
                rows="8"
                placeholder={userProfile ? userProfile.bio : null}
                control={control}
                inputProps={{
                  classes: {
                    input: classes.resize,
                  },
                }}
              />
            </Box>
          </Box>

          <Box className={classes.formBox}>
            <Box className={classes.box}>
              <InputLabel className={classes.inputLabel} htmlFor="disability">
                Disability Status
              </InputLabel>
              <Controller
                as={<TextField />}
                className={classes.input}
                id="disability"
                type="select"
                variant="outlined"
                name="disability"
                ref={register}
                placeholder={userProfile ? userProfile.disability : null}
                control={control}
                inputProps={{
                  classes: {
                    input: classes.resize,
                  },
                }}
              />
            </Box>
            <Box className={classes.box}>
              <InputLabel className={classes.inputLabel} htmlFor="legal">
                Are you over 18 years old?
              </InputLabel>
              <Controller
                as={
                  <Select value={userProfile?.legal}>
                    <MenuItem value="">
                      {userProfile ? userProfile.legal : ""}
                    </MenuItem>
                    <MenuItem value={`Adult`}>Yes</MenuItem>
                    <MenuItem value={`Minor`}>No</MenuItem>
                  </Select>
                }
                className={classes.input}
                id="legal"
                name="legal"
                variant="outlined"
                control={control}
                inputProps={{
                  classes: {
                    input: classes.resize,
                  },
                }}
              />
            </Box>
          </Box>
          <Box className={classes.formBox}>
            <Button
              className={classes.button}
              variant="outlined"
              color="primary"
              type="submit"
              aria-label="save changes to user profile"
              onClick={() => {
                setUpdated(true);
              }}
            >
              Save
            </Button>
            {updated === true ? handleUpdated() : null}
          </Box>
        </form>
      </Container>
    </main>
  );
}
Example #15
Source File: index.js    From AdaptivApps-fe with MIT License 4 votes vote down vote up
function SideNav(props) {
  const { user } = props;
  const { logout } = useAuth0();
  const { container } = props;
  const classes = useStyles();
  const theme = useTheme();
  const [mobileOpen, setMobileOpen] = React.useState(false);

  // Setup Chat and Announcement Subscriptions
  const { refetch } = useQuery(GET_CHAT_ROOMS, { variables: { email: user.email } });
  const { subscribeToMore: announcementSubscription, refetch: refetchAnnouncements  } = useQuery(GET_ANNOUNCEMENTS, { variables: { isAnnouncementRoom: true } });
  const { subscribeToMore } = useQuery(GET_MESSAGES, { variables: { email: user.email } });
  const { data, refetch: refetchProfile } = useQuery(GET_USER_PROFILE, { variables: { email: user.email } });
  const { subscribeToMore: notificationSubscription } = useQuery(GET_NOTIFICATIONS, { variables: { email: user.email } });

  // Chat Subscription
  const _subscribeToNewChats = subscribeToMore => {
    subscribeToMore({
      document: CHAT_SUBSCRIPTION,
      updateQuery: (prev, { subscriptionData }) => {
        if (!subscriptionData.data) return prev
        const chat = subscriptionData.data.chat
        refetch();
        refetchProfile();
        return Object.assign({}, prev, {
          profile: {
            chats: [chat, ...prev.profile.chats],
            __typename: prev.profile.__typename
          }
        })
      }
    })
  };

  // Announcement Subscription
  const _subscribeToNewAnnouncements = announcementSubscription => {
    announcementSubscription({
      document: ANNOUNCEMENT_SUBSCRIPTION,
      updateQuery: (prev, { subscriptionData }) => {
        if (!subscriptionData.data) return prev
        const announcement = subscriptionData.data.announcement
        refetchAnnouncements();
        refetchProfile();
        return Object.assign({}, prev, {
          announcements: [announcement, ...prev.announcements],
          __typename: prev.__typename
        })
      }
    })
  };

  _subscribeToNewAnnouncements(announcementSubscription);

  // Notification Subscription
  const _subscribeToNewNotifications = notificationSubscription => {
    notificationSubscription({
      document: NOTIFICATION_SUBSCRIPTION,
      updateQuery: (prev, { subscriptionData }) => {
        if (!subscriptionData.data) return prev
        const notification = subscriptionData.data.notification
        refetch();
        refetchAnnouncements();
        refetchProfile();
        return Object.assign({}, prev, {
          profile: {
            notifications: [notification, ...prev.profile.notifications],
            __typename: prev.profile.__typename
          }
        })
      }
    })
  };
  _subscribeToNewNotifications(notificationSubscription);

  const handleDrawerToggle = () => {
    setMobileOpen(!mobileOpen);
  };

  const drawer = (
    <>
      <Box className={classes.imgBox}>
        <img src={acsLogo} alt="ACS Logo" />
      </Box>
      <Box className={classes.navContainer}>
        <NavLink to="calendar" className={classes.navLink}>
          <CalendarTodayIcon className={classes.navIcon} />
          <p>Events Calendar</p>
        </NavLink>
        <NavLink to="myevents" className={classes.navLink}>
          <BookmarkIcon className={classes.navIcon} />
          <p>My Events</p>
        </NavLink>
        <NavLink to="/" className={classes.navLink}>
          <UserIcon className={classes.navIcon} />
          <p>My Profile</p>
        </NavLink>
        {data === undefined || data.profile === null || (data && (data?.profile.firstName === null || data?.profile.lastName === null)) ? 
        (
          <Tooltip title="Please complete your profile information to access Chats">
            <div className={classes.disabledNavLink}>
            {(data && data.profile !== null) && (data && data?.profile.notifications.length > 0) ? (
                <StyledBadge
                 overlap='circle'
                 badgeContent={data.profile.notifications.length}>
                  <ForumOutlinedIcon className={classes.navIcon} />
                </StyledBadge>
              ) : (
                <ForumOutlinedIcon className={classes.navIcon} />
              )}
              <p>Chats</p>
            </div>
          </Tooltip>
        ) 
        : 
        (
          <NavLink to="/chats" className={classes.navLink}>
            {data && data?.profile.notifications.length > 0 ? (
              <StyledBadge 
              overlap='circle'
              badgeContent={data.profile.notifications.length}
              >
                <ForumOutlinedIcon className={classes.navIcon} />
              </StyledBadge>
            ) : (
              <ForumOutlinedIcon className={classes.navIcon} />
            )}
            <p>Chats</p>
          </NavLink>
        )}
        {user && user[config.roleUrl].includes("Admin") ? (
          <>
            <NavLink to="manage" className={classes.navLink}>
              <HomeIcon className={classes.navIcon} />
              <p>Manage Events</p>
            </NavLink>
            <NavLink to="users" className={classes.navLink}>
              <GroupIcon className={classes.navIcon} />
              <p>Manage Users</p>
            </NavLink>
          </>
        ) : null}
      </Box>
      <Box className={classes.logoutContainer}>
        <Button className={classes.logoutBtn} onClick={() => logout()}>
          <IconContext.Provider
            value={{ style: { transform: "rotate(180deg)" } }}
          >
            <FiLogOut className={classes.logoutIcon} />
            <p className={classes.logoutP}>Log Out</p>
          </IconContext.Provider>
        </Button>
      </Box>
    </>
  );

  return (
    <div className={classes.root}>
      <Toolbar position="fixed">
        <IconButton
          color="inherit"
          aria-label="open drawer"
          edge="start"
          onClick={handleDrawerToggle}
          className={classes.menuButton}
        >
          <MenuIcon className={classes.navIcon} />
        </IconButton>
      </Toolbar>
      <nav className={classes.drawer} aria-label="mailbox folders">
        {/* The implementation can be swapped with js to avoid SEO duplication of links. */}
        <Hidden smUp implementation="css">
          <Drawer
            container={container}
            variant="temporary"
            anchor={theme.direction === "rtl" ? "right" : "left"}
            open={mobileOpen}
            onClose={handleDrawerToggle}
            classes={{
              paper: classes.drawerPaper,
            }}
            ModalProps={{
              keepMounted: true, // Better open performance on mobile.
            }}
          >
            {drawer}
          </Drawer>
        </Hidden>
        <Hidden xsDown implementation="css">
          <Drawer
            classes={{
              paper: classes.drawerPaper,
            }}
            variant="permanent"
            open
          >
            {drawer}
          </Drawer>
        </Hidden>
      </nav>
    </div>
  );
}