@chakra-ui/core#Icon JavaScript Examples

The following examples show how to use @chakra-ui/core#Icon. 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 here-covid-19-tracker with MIT License 6 votes vote down vote up
NavigationTabs = () => {
  const updateTab = useTabStore(state => state.updateTab)
  const currentTab = useTabStore(state => state.currentTab)

  const handleTabChange = index => {
    updateTab(index)
  }

  return (
    <Box
      display={["block", null, "none"]}
      position="fixed"
      bottom="0"
      left="0"
      right="0"
      bg="white"
      zIndex={999999}
      boxShadow="0 -0.25rem 0.75rem rgba(0,0,0,0.1)"
    >
      <Tabs variantColor="orange" onChange={handleTabChange} defaultIndex={1} index={currentTab}>
        <TabList display="flex" justifyContent="space-between">
          <Tab width={1/3} height="3rem" fontWeight={600} _focus={{ boxShadow: "none" }}>
            <Icon name="list" mr="0.25rem"/>
            { "Cases" }
          </Tab>
          <Tab width={1/3} height="3rem" fontWeight={600} _focus={{ boxShadow: "none" }}>
            <Icon name="globe" mr="0.25rem"/>
            { "Map" }
          </Tab>
          <Tab width={1/3} height="3rem" fontWeight={600} _focus={{ boxShadow: "none" }}>
            <Icon name="info" mr="0.25rem"/>
            { "About" }
          </Tab>
        </TabList>
      </Tabs>
    </Box>
  )
}
Example #2
Source File: LoadMore.js    From opensource.builders with MIT License 5 votes vote down vote up
export function LoadMore({ alts }) {
  const [show, setShow] = useState(false)

  const fiveAlts = alts.slice(0, 5)
  const restAlts = alts.slice(5, alts.length)

  return (
    <>
      {fiveAlts.map((alt) => (
        <AltListItem alt={alt} />
      ))}
      {show && restAlts.map((alt) => <AltListItem alt={alt} />)}
      <Box cursor="pointer" width="100%" display="flex" justifyContent="center">
        <Text
          display="flex"
          alignItems="center"
          bg="white"
          pl={3}
          pr={2}
          py={1}
          letterSpacing="wide"
          boxShadow="sm"
          borderRadius={3}
          fontWeight={600}
          color="gray.500"
          textTransform="uppercase"
          fontSize="xs"
          mt={2}
          onClick={() => setShow(!show)}
        >
          {show ? (
            <>
              Hide
              <Icon ml={1} size={4} name="chevron-up" />
            </>
          ) : (
            <>
              {alts.length - 5} More Alternative{alts.length - 5 !== 1 && "s"}
              <Icon ml={1} size={4} name="chevron-down" />
            </>
          )}
        </Text>
      </Box>
    </>
  )
}
Example #3
Source File: Signup.js    From allay-fe with MIT License 4 votes vote down vote up
Signup = ({ signup, isLoading, history }) => {
  const { handleSubmit, errors, register, formState } = useForm()
  const [show, setShow] = useState(false)
  const [moreInfo, setMoreInfo] = useState(false)
  const handleClick = () => setShow(!show)
  //location state
  const [location, setLocation] = useState({})
  const [newLocation, setNewLocation] = useState({})
  const stateHelper = (value) => {
    setLocation(value)
  }
  const [profile_image, setProfile_Image] = useState('')
  const [profile_resume, setProfile_resume] = useState('')
  //validation
  function validateFirstName(value) {
    let error
    let nameRegex = /^[0-9*#+]+$/
    if (!value) {
      error = 'First Name is required'
    } else if (value.length < 2) {
      error = 'First Name must be at least 2 characters'
    } else if (nameRegex.test(value)) {
      error = 'First Name can only contain letters'
    }
    return error || true
  }

  function validateLastName(value) {
    let error
    let nameRegex = /^[0-9*#+]+$/
    if (!value) {
      error = 'Last Name is required'
    } else if (value.length < 2) {
      error = 'Last Name must be at least 2 characters'
    } else if (nameRegex.test(value)) {
      error = 'Last Name can only contain letters'
    }
    return error || true
  }

  function validateEmail(value) {
    let error
    if (!value) {
      error = 'Email is required'
    } else if (!value.includes('@')) {
      error = 'Must be a valid email'
    }
    return error || true
  }

  function validateTrack(value) {
    let error
    if (!value) {
      error = 'Lambda track is required'
    }
    return error || true
  }

  function validateCohort(value) {
    let error
    if (!value) {
      error = 'Cohort is required'
    }
    return error || true
  }

  function validatePassword(value) {
    let error
    if (!value) {
      error = 'Password is required'
    } else if (value.length < 8) {
      error = 'Password must be at least 8 characters'
    }
    return error || true
  }

  function validateFieldOfStudy(value) {
    let error
    let nameRegex = /^[0-9*#+]+$/
    if (nameRegex.test(value)) {
      error = 'Field of study can only contain letters'
    }
    return error || true
  }
  // end validation

  //add image to cloudinary
  const uploadImage = async (e) => {
    const files = e.target.files
    const data = new FormData()
    data.append('file', files[0])
    data.append('upload_preset', 'upload')
    const res = await fetch(
      '	https://api.cloudinary.com/v1_1/takija/image/upload',
      {
        method: 'POST',
        body: data,
      }
    )
    const file = await res.json()
    setProfile_Image(...profile_image, file.secure_url)
  }

  //upload resume to cloudinary
  const uploadResume = async (e) => {
    const files = e.target.files
    const data = new FormData()
    data.append('file', files[0])
    data.append('upload_preset', 'upload')
    const res = await fetch(
      '	https://api.cloudinary.com/v1_1/takija/image/upload',
      {
        method: 'POST',
        body: data,
      }
    )
    const file = await res.json()
    console.log('here', file)
    setProfile_resume(...profile_resume, file.secure_url)
  }

  const submitForm = (creds) => {
    // correcting grad date format
    let graduated = null
    if (creds.gradMonth && creds.gradYear) {
      graduated = `${creds.gradYear}-${creds.gradMonth}-01`
    }

    // correcting employed date format
    let employed_start = null
    if (creds.workMonth && creds.workYear) {
      employed_start = `${creds.workYear}-${creds.workMonth}-01`
    }

    if (creds.confirmPassword === creds.password) {
      // formatting the signup state to match the back end columns
      signup({
        email: creds.email,
        password: creds.password,
        track_id: Number(creds.track_id),
        first_name: creds.firstName,
        last_name: creds.lastName,
        cohort: creds.cohort,
        contact_email: creds.contact_email || null,
        location: newLocation
          ? `${newLocation.myCity} ${newLocation.myState}`
          : null,
        graduated: graduated,
        highest_ed: creds.highest_ed || null,
        field_of_study: creds.field_of_study || null,
        prior_experience: creds.prior_experience
          ? JSON.parse(creds.prior_experience)
          : false,
        tlsl_experience: creds.tlsl_experience
          ? JSON.parse(creds.tlsl_experience)
          : false,
        employed_company: creds.employed_company || null,
        employed_title: creds.employed_title || null,
        employed_remote: creds.employed_remote
          ? JSON.parse(creds.employed_remote)
          : false,
        employed_start: employed_start,
        resume: profile_resume || null,
        linked_in: creds.linked_in || null,
        slack: creds.slack || null,
        github: creds.github || null,
        dribble: creds.dribble || null,
        profile_image: profile_image || null,
        portfolio: creds.portfolio_URL || null,
      }).then(() => history.push('/dashboard'))
    } else {
      alert('Your Passwords must match!')
    }
    ReactGA.event({
      category: 'User',
      action: `Button Sign Up`,
    })
  }

  const switchMoreInfo = () => {
    setMoreInfo(!moreInfo)
  }

  const gaLogin = () => {
    ReactGA.event({
      category: 'User',
      action: `Link Already have an account`,
    })
  }

  if (isLoading) {
    return (
      <Flex justify="center" align="center" w="100vh" h="100vh">
        <Flex>
          <CustomSpinner />
        </Flex>
      </Flex>
    )
  }

  return (
    <Flex className="RegisterSplash" w="100%" minH="100vh" justify="center">
      <Flex maxW="1440px" w="100%">
        <Flex
          w="833px"
          mx="auto"
          justify="center"
          align="center"
          flexDir="column"
        >
          <form onSubmit={handleSubmit(submitForm)}>
            <Flex
              w="833px"
              // h='825px'
              p="6"
              flexDir="column"
              background="#FDFDFF"
              justify="center"
            >
              <Flex
                as="h2"
                w="653"
                fontSize="36px"
                fontWeight="600"
                fontFamily="Poppins"
                justify="center"
                my="68px"
              >
                Let's get started!
              </Flex>

              {/* FIRST NAME, LAST NAME */}
              <Flex wrap="wrap" w="653" justify="center">
                <FormControl isRequired isInvalid={errors.username}>
                  <FormLabel color="#131C4D" fontSize="18px" fontFamily="Muli">
                    First Name
                  </FormLabel>
                  <SignupLoginInput
                    w="318px"
                    mb="30px"
                    mr="17px"
                    type="text"
                    name="firstName"
                    label="firstName"
                    placeholder="John"
                    autoCapitalize="none"
                    ref={register({ validate: validateFirstName })}
                  />
                  <FormErrorMessage>
                    {errors.firstName && errors.firstName.message}
                  </FormErrorMessage>
                </FormControl>
                <FormControl isRequired isInvalid={errors.username}>
                  <FormLabel color="#131C4D" fontSize="18px" fontFamily="Muli">
                    Last Name
                  </FormLabel>
                  <SignupLoginInput
                    w="318px"
                    mb="30px"
                    type="text"
                    name="lastName"
                    label="lastName"
                    placeholder="Doe"
                    autoCapitalize="none"
                    ref={register({ validate: validateLastName })}
                  />
                  <FormErrorMessage>
                    {errors.lastName && errors.lastName.message}
                  </FormErrorMessage>
                </FormControl>
              </Flex>

              {/* EMAIL */}
              <Flex wrap="wrap" w="653" justify="center">
                <FormControl isRequired isInvalid={errors.email}>
                  <FormLabel color="#131C4D" fontSize="18px" fontFamily="Muli">
                    Email
                  </FormLabel>
                  <SignupLoginInput
                    w="653px"
                    mb="30px"
                    type="email"
                    name="email"
                    label="email"
                    placeholder="[email protected]"
                    autoCapitalize="none"
                    ref={register({ validate: validateEmail })}
                  />
                  <FormErrorMessage>
                    {errors.email && errors.email.message}
                  </FormErrorMessage>
                </FormControl>
              </Flex>

              {/* TRACK */}
              <Flex wrap="wrap" w="411px%" justify="center">
                <FormControl isRequired isInvalid={errors.track_name}>
                  <FormLabel color="#131C4D" fontSize="18px" fontFamily="Muli">
                    Track
                  </FormLabel>
                  <Select
                    mb="30px"
                    mr="17px"
                    h="68px"
                    py="16px"
                    w="318px"
                    rounded="2px"
                    variant="outline"
                    backgroundColor="#FDFDFF"
                    focusBorderColor="#344CD0"
                    borderColor="#EAF0FE"
                    color="#BBBDC6"
                    _focus={{ color: '#17171B' }}
                    _hover={{ borderColor: '#BBBDC6' }}
                    name="track_id"
                    label="track_id"
                    ref={register({ validate: validateTrack })}
                  >
                    <option fontFamily="Muli" value="">
                      Select Your Lambda Track
                    </option>
                    <option fontFamily="Muli" value={1}>
                      Android
                    </option>
                    <option fontFamily="Muli" value={2}>
                      DS
                    </option>
                    <option fontFamily="Muli" value={3}>
                      WEB
                    </option>
                    <option fontFamily="Muli" value={4}>
                      IOS
                    </option>
                    <option fontFamily="Muli" value={5}>
                      UX
                    </option>
                  </Select>
                  <FormErrorMessage>
                    {errors.track_id && errors.track_id.message}
                  </FormErrorMessage>
                </FormControl>
                <FormControl isRequired isInvalid={errors.username}>
                  <FormLabel color="#131C4D" fontSize="18px" fontFamily="Muli">
                    Cohort
                  </FormLabel>
                  <SignupLoginInput
                    w="318px"
                    mb="30px"
                    type="text"
                    name="cohort"
                    label="cohort"
                    placeholder="Ex: FT 1 or PT 1"
                    autoCapitalize="none"
                    ref={register({ validate: validateCohort })}
                  />
                  <FormErrorMessage>
                    {errors.cohort && errors.cohort.message}
                  </FormErrorMessage>
                </FormControl>
              </Flex>

              {/* PASSWORD, CONFIRM PASSWORD */}
              <Flex wrap="wrap" w="411px%" justify="center">
                <FormControl isRequired isInvalid={errors.password}>
                  <FormLabel color="#131C4D" fontSize="18px" fontFamily="Muli">
                    Password
                  </FormLabel>
                  <InputGroup>
                    <SignupLoginInput
                      w="318px"
                      // mb='30px'
                      mr="17px"
                      type={show ? 'text' : 'password'}
                      name="password"
                      label="Password"
                      placeholder="********"
                      autoCapitalize="none"
                      ref={register({ validate: validatePassword })}
                    />
                    <InputRightElement width="4.5rem" pr="22px" py="32px">
                      <Button
                        h="1.75rem"
                        color="rgba(72, 72, 72, 0.1)"
                        border="none"
                        size="sm"
                        backgroundColor="#FDFDFF"
                        onClick={handleClick}
                      >
                        {show ? 'Hide' : 'Show'}
                      </Button>
                    </InputRightElement>
                  </InputGroup>
                  <FormHelperText mb="45px" color="#9194A8">
                    Must be at least 8 characters
                  </FormHelperText>
                  <FormErrorMessage>
                    {errors.password && errors.password.message}
                  </FormErrorMessage>
                </FormControl>
                <FormControl isRequired>
                  <FormLabel color="#131C4D" fontSize="18px" fontFamily="Muli">
                    Confirm Password
                  </FormLabel>
                  <InputGroup>
                    <SignupLoginInput
                      w="318px"
                      mb="30px"
                      type={show ? 'text' : 'password'}
                      name="confirmPassword"
                      label="Confirm Password"
                      placeholder="********"
                      autoCapitalize="none"
                      ref={register}
                    />
                    <InputRightElement width="4.5rem" py="32px">
                      <Button
                        data-cy="registerSubmit"
                        h="1.75rem"
                        color="rgba(72, 72, 72, 0.1)"
                        border="none"
                        size="sm"
                        backgroundColor="#FDFDFF"
                        onClick={handleClick}
                      >
                        {show ? 'Hide' : 'Show'}
                      </Button>
                    </InputRightElement>
                  </InputGroup>
                </FormControl>
              </Flex>

              {/* CLICK FOR LONGFORM SIGNUP */}
              <Flex
                wrap="wrap"
                w="653px"
                mx="auto"
                mb={moreInfo ? '0' : '55px'}
                cursor="pointer"
                justify="flex-start"
                data-cy="longFormDropdown"
                onClick={switchMoreInfo}
              >
                <Flex justify="flex-start">
                  {moreInfo ? (
                    <Icon
                      fontWeight="bold"
                      name="chevron-down"
                      textAlign="left"
                      size="30px"
                      mr="5px"
                      ml="-8px"
                      pt="3px"
                    />
                  ) : (
                    <Icon
                      fontWeight="bold"
                      name="chevron-right"
                      textAlign="left"
                      size="30px"
                      mr="5px"
                      ml="-8px"
                      pt="3px"
                    />
                  )}
                  <Text fontWeight="bold" fontSize="20px" fontFamily="Muli">
                    {' '}
                    Add Additional Information
                  </Text>
                </Flex>
              </Flex>

              {/* ADDITIONAL INFO COMPONENT */}
              {moreInfo ? (
                <SignupAdditional
                  profile_resume={profile_resume}
                  profile_image={profile_image}
                  uploadImage={uploadImage}
                  uploadResume={uploadResume}
                  register={register}
                  errors={errors}
                  location={location}
                  newLocation={newLocation}
                  setNewLocation={setNewLocation}
                  stateHelper={stateHelper}
                  validateFieldOfStudy={validateFieldOfStudy}
                />
              ) : null}

              <Flex w="100%" justify="center">
                <Button
                  mb="30px"
                  border="none"
                  rounded="50px"
                  h="58px"
                  w="653px"
                  my="2%"
                  size="lg"
                  color="white"
                  backgroundColor="#344CD0"
                  _hover={{ backgroundColor: '#4254BA', cursor: 'pointer' }}
                  isLoading={formState.isSubmitting}
                  type="submit"
                  data-cy="registerSubmit"
                >
                  Sign up
                </Button>
              </Flex>
              <Flex m="15px" justify="center" fontWeight="light">
                <Text fontSize="16px" color="#17171B" fontFamily="Muli">
                  Already have an account?{' '}
                  <Link
                    to="/"
                    onClick={gaLogin}
                    style={{
                      textDecoration: 'none',
                      fontWeight: 'bold',
                      color: '#344CD0',
                      fontSize: '16px',
                    }}
                  >
                    Sign in here!
                  </Link>
                </Text>
              </Flex>
            </Flex>
          </form>
        </Flex>
      </Flex>
    </Flex>
  )
}
Example #4
Source File: NavBar.js    From allay-fe with MIT License 4 votes vote down vote up
function NavBar({
  history,
  isLoading,
  isBlocked,
  setSearchResults,
  trackFilters,
  setTrackFilters,
  typeFilters,
  setTypeFilters,
  getUser,
  userData,
}) {
  const userId = window.localStorage.getItem('userId')
  // use to navigate to review form
  const navToReviewForm = () => {
    history.push('/dashboard/add-review')
    ReactGA.event({
      category: 'Review',
      action: `Add new review`,
    })
  }

  // image helper
  const [imageTimeout, setImageTimeout] = useState(true)
  useEffect(() => {
    setTimeout(function () {
      setImageTimeout(false)
    }, 1500)
  }, [])

  const logout = () => {
    localStorage.clear('token')
    localStorage.clear('userId')
    history.push('/')
  }

  const handleInputChange = (event) => {
    event.preventDefault()
    setSearchResults(event.target.value.toLowerCase())
  }

  // We could get this fronm the DB if we had endpoints
  const types = [
    { id: 1, criteria: 'type', name: 'Interview' },
    { id: 2, criteria: 'type', name: 'Company' },
  ]

  const tracks = [
    { id: 1, criteria: 'track', name: 'WEB' },
    { id: 2, criteria: 'track', name: 'UX' },
    { id: 3, criteria: 'track', name: 'DS' },
    { id: 4, criteria: 'track', name: 'iOS' },
    { id: 5, criteria: 'track', name: 'Android' },
  ]

  //track badge colors and background color picker
  const trackFontColor = (trackName) => {
    switch (trackName) {
      case 'DS':
        return '#35694F'
        break
      case 'WEB':
        return '#474EA7'
        break
      case 'iOS' || 'IOS':
        return '#8E3D19'
        break
      case 'Android':
        return '#4B3569'
        break
      case 'UX':
        return '#9F3A5A'
        break
      default:
        return
    }
  }
  const trackColorPicker = (trackName) => {
    switch (trackName) {
      case 'DS':
        return '#D3F2CD'
        break
      case 'WEB':
        return '#DBEBFD'
        break
      case 'iOS' || 'IOS':
        return '#F4E6BE'
        break
      case 'Android':
        return '#E9D9FF'
        break
      case 'UX':
        return '#F9E3DE'
        break
      default:
        return
    }
  }
  ///
  //// handle type filter and state for the badge / show
  const [type, setType] = useState([])
  const handleType = (name) => {
    if (typeFilters.includes(name)) {
      setTypeFilters(typeFilters.filter((item) => item !== name))
      setType(type.filter((x) => x !== name))
    } else {
      setTypeFilters(typeFilters.filter((item) => item !== name))
      setTypeFilters([...typeFilters, name])
      setType([...type, name])
    }
  }

  const typeBadge = (name) => {
    return name.map((typeName, index) => (
      <Badge
        key={`ReviewBadge-${index}`}
        backgroundColor="#E2E2E2"
        color="#131C4D"
        fontFamily="Muli"
        fontWeight="normal"
        p="5px 15px"
        m="5px"
        style={{ borderRadius: '50px' }}
        variantColor="green"
      >
        {typeName}
      </Badge>
    ))
  }
  //// handle track filter and state for the badge color / show

  const [track, setTrack] = useState([])
  const handleTrack = (name) => {
    if (trackFilters.includes(name)) {
      setTrackFilters(trackFilters.filter((item) => item !== name))
      setTrack(track.filter((x) => x !== name))
    } else {
      setTrackFilters(trackFilters.filter((item) => item !== name))
      setTrackFilters([...trackFilters, name])
      setTrack([...track, name])
    }
  }

  const trackBadge = (name) => {
    return name
      .map((typeName, index) => {
        if (index < 2) {
          return (
            <Badge
              key={`TrackBadge-${index}`}
              p="5px 15px"
              m="2px"
              fontFamily="Muli"
              fontWeight="normal"
              backgroundColor={trackColorPicker(typeName)}
              color={trackFontColor(typeName)}
              style={{ borderRadius: '50px' }}
              variantColor="green"
            >
              {typeName}
            </Badge>
          )
        } else {
          return (
            <Badge
              key={`TrackBadge-${index}`}
              backgroundColor="#E2E2E2"
              color="#131C4D"
              fontFamily="Muli"
              fontWeight="normal"
              p="5px 15px"
              m="2px"
              style={{ borderRadius: '50px' }}
              variantColor="green"
            >
              . . .
            </Badge>
          )
        }
      })
      .filter((item, index) => index < 3)
  }

  useEffect(() => {
    getUser(userId)
  }, [getUser, userId])

  return (
    <Flex
      maxW="1440px"
      w="100%"
      background="#FFFFFF"
      top="0"
      position="fixed"
      zIndex="999"
      direction="column"
    >
      <Flex
        align="center"
        justify="space-between"
        py="28px"
        mb="4%"
        h="100px"
        borderBottom="1px solid #EAF0FE"
      >
        <Flex color="#344CD0" align="center" pl="40px">
          <h1 fontFamily="Poppins" fontWeight="600" fontSize="32px">
            Allay
          </h1>
        </Flex>

        {/* Search bar*/}
        <InputGroup w="40%">
          <InputRightElement>
            <Icon name="search-2" color="#344CD0" />
          </InputRightElement>
          <Input
            width="100%"
            placeholder="Search for company or position..."
            name="searchbar"
            type="text"
            rounded="20px"
            borderColor="rgba(149, 149, 149, 0.2)"
            borderWidth="1px"
            onChange={handleInputChange}
          />
        </InputGroup>

        {/* Profile Icon and user menu*/}
        <Flex pr="40px">
          <Menu position="absolute" height="226px">
            {imageTimeout ? (
              <Spinner />
            ) : (
              <MenuButton
                data-cy="profileButton"
                as={Image}
                size="58px"
                cursor="pointer"
                style={{
                  borderRadius: '50%',
                }}
                src={userData.profile_image}
                fallbackSrc={require('../../icons/user.svg')}
              />
            )}
            <MenuList>
              <MenuItem
                border="none"
                backgroundColor="#FFF"
                onClick={() => history.push(`/profile/${userId}`)}
                data-cy="profileLink"
              >
                Profile
              </MenuItem>
              <MenuItem
                border="none"
                backgroundColor="#FFF"
                onClick={() => history.push(`/profile/${userId}/edit`)}
                data-cy="editProfileMenuOption"
              >
                Account settings
              </MenuItem>
              <MenuItem
                border="none"
                backgroundColor="#FFF"
                onClick={logout}
                data-cy="signOut"
              >
                Log out
              </MenuItem>
            </MenuList>
          </Menu>
        </Flex>
      </Flex>

      <Box>
        {/* Filtered Search Buttons */}
        <Flex
          align="center"
          width="100%"
          margin="0 auto"
          justify="space-between"
          px="40px"
        >
          <Heading
            as="h1"
            fontSize="36px"
            fontFamily="Poppins"
            fontWeight="600"
            color="#131C4D"
          >
            Reviews
          </Heading>
          <Flex>
            <Menu margin="3%" closeOnSelect={false}>
              <MenuButton
                outline="none"
                w="309px"
                h="65px"
                bg="#FFFFFF"
                mr="20px"
                border="2px solid #EAF0FE"
                rounded="32px"
                fontFamily="Muli"
                fontSize="20px"
                fontWeight="bold"
              >
                <Flex
                  justify="space-between"
                  align="center"
                  pl={track.length > 0 ? '10px' : '30px'}
                  pr="18px"
                >
                  <Flex w="100%">
                    {type.length > 0
                      ? typeBadge(type)
                      : 'Filter by review type'}
                  </Flex>

                  <Icon name="triangle-down" color="#344CD0" fontSize="16px" />
                </Flex>
              </MenuButton>
              <MenuList minWidth="240px">
                {types.map((type) => (
                  <MenuOptionGroup
                    key={type.name}
                    defaultValue={typeFilters}
                    type="checkbox"
                  >
                    <MenuItemOption
                      border="none"
                      backgroundColor="#FFF"
                      value={type.name}
                      onClick={() => handleType(type.name)}
                    >
                      {type.name}
                    </MenuItemOption>
                  </MenuOptionGroup>
                ))}
              </MenuList>
            </Menu>
            <Menu closeOnSelect={false}>
              <MenuButton
                outline="none"
                w="260px"
                h="65px"
                bg="#FFFFFF"
                border="2px solid #EAF0FE"
                rounded="32px"
                fontFamily="Muli"
                fontSize="20px"
                fontWeight="bold"
              >
                <Flex
                  justify="space-between"
                  align="center"
                  pl={track.length > 0 ? '10px' : '30px'}
                  pr="18px"
                >
                  <Flex w="100%">
                    {track.length > 0 ? trackBadge(track) : 'Filter by field'}
                  </Flex>

                  <Icon name="triangle-down" color="#344CD0" fontSize="16px" />
                </Flex>
              </MenuButton>
              <MenuList minWidth="240px">
                {tracks.map((track) => (
                  <MenuOptionGroup
                    key={track.name}
                    defaultValue={trackFilters}
                    type="checkbox"
                  >
                    <MenuItemOption
                      border="none"
                      backgroundColor="#FFF"
                      value={track.name}
                      onClick={() => handleTrack(track.name)}
                    >
                      {track.name}
                    </MenuItemOption>
                  </MenuOptionGroup>
                ))}
              </MenuList>
            </Menu>
          </Flex>
          {isBlocked ? (
            <Blocked />
          ) : (
            <Button
              background="#344CD0"
              color="#FDFDFF"
              _hover={{ bg: '#4254BA', cursor: 'pointer' }}
              fontFamily="Muli"
              fontWeight="bold"
              fontSize="20px"
              rounded="35px"
              p="19px 20px"
              w="180px"
              h="63px"
              border="none"
              size="lg"
              isLoading={isLoading}
              onClick={navToReviewForm}
              data-cy="addReviewButton"
            >
              Write a review
            </Button>
          )}
        </Flex>
      </Box>
    </Flex>
  )
}
Example #5
Source File: ReviewCard.js    From allay-fe with MIT License 4 votes vote down vote up
ReviewCard = ({ review, history, deleteReview, isAdmin }) => {
  const singleReview = review

  //deletes the review in question
  const submitDelete = (user_id, review_id) => {
    if (review.user_id && review.review_id) {
      deleteReview(review.user_id, review.review_id).then(() => {
        // window.location.reload();
        history.push('/dashboard')
      })
    } else {
      deleteReview(user_id, review_id).then(() => {
        // window.location.reload();
        history.push('/dashboard')
      })
    }

    ReactGA.event({
      category: 'Review Delete',
      action: `Submit delete`,
    })
  }
  // useEffect(() => {}, [submitDelete])
  // basic usage for the SingleReview modal
  const { isOpen, onOpen, onClose } = useDisclosure()
  const loginId = localStorage.getItem('userId')

  // specifically for the cancel review delete button functionality
  const [isOpen2, setIsOpen2] = useState()
  const onClose2 = () => setIsOpen2(false)
  const cancelRef = useRef()

  //routes to single review
  const navToEditRoute = () =>
    review.review_type === 'Company'
      ? history.push({
          pathname: `/dashboard/review/${review.review_id}`,
          state: singleReview,
        })
      : history.push(`/dashboard/interview/${review.review_id}`)

  //routes to user's profile page
  const navToProfile = (e) => {
    e.preventDefault()
    history.push(`/profile/${review.user_id}`)
  }

  // adjust logo for api call
  // const adjustedName = review.company_name.replace(' ', '+')

  // adjust date of posting
  let tempDate = new Date(review.created_at).toUTCString()
  const tempDay = tempDate.split(' ').slice(1, 2)
  const tempMonth = tempDate.split(' ').slice(2, 3)
  const tempYear = tempDate.split(' ').slice(3, 4)
  const adjustedDate = `${tempMonth} ${tempDay}, ${tempYear}`

  //track name font color picker
  const trackFontColor = (trackName) => {
    switch (trackName) {
      case 'DS':
        return '#35694F'
        break
      case 'WEB':
        return '#474EA7'
        break
      case 'iOS' || 'IOS':
        return '#8E3D19'
        break
      case 'Android':
        return '#4B3569'
        break
      case 'UX':
        return '#9F3A5A'
        break
      default:
        return
    }
  }
  //track name background color picker
  const trackColorPicker = (trackName) => {
    switch (trackName) {
      case 'DS':
        return '#D3F2CD'
        break
      case 'WEB':
        return '#DBEBFD'
        break
      case 'iOS' || 'IOS':
        return '#F4E6BE'
        break
      case 'Android':
        return '#E9D9FF'
        break
      case 'UX':
        return '#F9E3DE'
        break
      default:
        return
    }
  }

  //remove white space from company name for logo usage
  let stripped = review.company_name.replace(/ /g, '')
  let com = '.com'
  const logo = stripped.concat(com)

  const created = moment(review.created_at).fromNow()

  return (
    <>
      {/* ------------------------------------------------------------------------------------------------ */}
      {/* ---------------------------------------Modal Cards (for edit)----------------------------------- */}
      {/* ------------------------------------------------------------------------------------------------ */}

      <Modal
        preserveScrollBarGap
        isOpen={isOpen}
        onClose={onClose}
        size="950px"
      >
        <ModalOverlay />
        <ModalContent w="100%" wrap="nowrap">
          <ModalCloseButton
            data-cy="reviewCloseButton"
            background="none"
            border="none"
          />

          {/* LEFT SIDE MODAL */}
          <Flex
            direction="column"
            justify="space-between"
            align="flex-start"
            position="relative"
            w="261px"
            height="100%"
            top="0"
            left="0"
            pb="50px"
            pt="35px"
            pl="40px"
            bg="#F2F6FE"
            borderRadius="0px 40px 40px 0px"
          >
            {/* USER AVATAR AND NAME */}
            <Flex
              justify="space-evenly"
              align="center"
              mb="30px"
              onClick={navToProfile}
              style={{ cursor: 'pointer' }}
            >
              {review.user_profile_image === 'h' ? (
                <Image
                  size="40px"
                  mr="7px"
                  style={{ opacity: '0.6' }}
                  src={require('../../icons/user.svg')}
                />
              ) : (
                <Image
                  size="40px"
                  mr="7px"
                  style={{ opacity: '0.6', borderRadius: '50%' }}
                  src={review.user_profile_image}
                />
              )}
              <Text color="#131C4D" fontSize="14px" fontFamily="Muli">
                By {review.user_first_name} {review.user_last_name}
              </Text>
            </Flex>
            {/* COMPANY LOGO AND REVIEW STARS */}
            <Flex
              direction="column"
              justify="center"
              align="flex-start"
              mb="20px"
            >
              <Image
                w="148px"
                h="70px"
                src={`https://logo.clearbit.com/${
                  review.logo !== 'unknown' ? review.logo : logo
                }`}
                fallbackSrc={`http://samscct.com/wp-content/uploads/2014/09/no-logo.png`}
              />

              <Flex mt="13px">
                {Array(5)
                  .fill('')
                  .map((_, i) => (
                    <Icon
                      name="star"
                      key={i}
                      color={i < review.overall_rating ? '#F9DC76' : '#DADADD'}
                      ml="4px"
                    />
                  ))}
              </Flex>
            </Flex>
            {/* COMPANY LOCATION AND NAME */}
            <Flex
              direction="column"
              justify="center"
              align="flex-start"
              mb="40px"
            >
              <Flex mb="5px">
                <Box as={GoLocation} size="21px" color="#BBBDC6" mr="7px" />
                <Text color="#BBBDC6" fontSize="14px" fontFamily="Muli">
                  {review.city}, {review.state_name}
                </Text>
              </Flex>
              <Flex>
                <Box as={FaRegBuilding} size="21px" color="#BBBDC6" mr="7px" />
                <Text color="#BBBDC6" fontSize="14px" fontFamily="Muli">
                  {review.company_name}
                </Text>
              </Flex>
            </Flex>
            {/* JOB/INTERVIEW INFORMATION */}
            <Flex direction="column" justify="space-between" align="flex-start">
              <Flex
                direction="column"
                justify="flex-start"
                align="flex-start"
                mb="20px"
              >
                <Text
                  color="#131C4C"
                  fontSize="18px"
                  fontFamily="Muli"
                  fontWeight="bold"
                >
                  {review.job_title}
                </Text>
                <Text
                  color="#9194A8"
                  fontSize="14px"
                  fontFamily="Muli"
                  fontWeight="bold"
                >
                  Job title
                </Text>
              </Flex>
              <Flex
                direction="column"
                justify="flex-start"
                align="flex-start"
                mb="20px"
              >
                <Text
                  color="#131C4C"
                  fontSize="18px"
                  fontFamily="Muli"
                  fontWeight="bold"
                >{`${review.salary}.00`}</Text>
                <Text
                  color="#9194A8"
                  fontSize="14px"
                  fontFamily="Muli"
                  fontWeight="bold"
                >
                  Salary
                </Text>
              </Flex>
              <Flex
                direction="column"
                justify="flex-start"
                align="flex-start"
                mb="20px"
              >
                {review.review_type === 'Company' ? (
                  <Text
                    color="#131C4C"
                    fontSize="18px"
                    fontFamily="Muli"
                    fontWeight="bold"
                  >
                    {review.work_status}
                  </Text>
                ) : review.difficulty_rating === 1 ? (
                  <Text
                    color="#131C4C"
                    fontSize="18px"
                    fontFamily="Muli"
                    fontWeight="bold"
                  >
                    Very easy
                  </Text>
                ) : review.difficulty_rating === 2 ? (
                  <Text
                    color="#131C4C"
                    fontSize="18px"
                    fontFamily="Muli"
                    fontWeight="bold"
                  >
                    Easy
                  </Text>
                ) : review.difficulty_rating === 3 ? (
                  <Text
                    color="#131C4C"
                    fontSize="18px"
                    fontFamily="Muli"
                    fontWeight="bold"
                  >
                    Somewhat easy
                  </Text>
                ) : review.difficulty_rating === 4 ? (
                  <Text
                    color="#131C4C"
                    fontSize="18px"
                    fontFamily="Muli"
                    fontWeight="bold"
                  >
                    Somewhat hard
                  </Text>
                ) : review.difficulty_rating === 5 ? (
                  <Text
                    color="#131C4C"
                    fontSize="18px"
                    fontFamily="Muli"
                    fontWeight="bold"
                  >
                    Hard
                  </Text>
                ) : (
                  <Text
                    color="#131C4C"
                    fontSize="18px"
                    fontFamily="Muli"
                    fontWeight="bold"
                  >
                    N/A
                  </Text>
                )}

                <Text
                  color="#9194A8"
                  fontSize="14px"
                  fontFamily="Muli"
                  fontWeight="bold"
                >
                  {review.review_type === 'Company'
                    ? 'Status'
                    : 'Interview difficulty'}
                </Text>
              </Flex>
              <Flex
                direction="column"
                justify="flex-start"
                align="flex-start"
                mb="20px"
              >
                {review.review_type === 'Company' ? (
                  <Text
                    color="#131C4C"
                    fontSize="18px"
                    fontFamily="Muli"
                    fontWeight="bold"
                  >
                    {review.start_date} -{' '}
                    {review.end_date ? review.end_date : 'Present'}
                  </Text>
                ) : (
                  <Text
                    color="#131C4C"
                    fontSize="18px"
                    fontFamily="Muli"
                    fontWeight="bold"
                  >
                    {review.offer_status}
                  </Text>
                )}
                <Text
                  color="#9194A8"
                  fontSize="14px"
                  fontFamily="Muli"
                  fontWeight="bold"
                >
                  {review.review_type === 'Company' ? 'Dates' : 'Job offer?'}
                </Text>
              </Flex>
            </Flex>
            <Flex>
              {Number(loginId) === Number(review.user_id) ? (
                <Image
                  src={require('../../icons/edit.png')}
                  onClick={navToEditRoute}
                  cursor="pointer"
                  size="1.5em"
                  mr="12px"
                  data-cy="editModalReview"
                />
              ) : null}
              {Number(loginId) === Number(review.user_id) ? (
                <Image
                  data-cy="deleteModalReview"
                  src={require('../../icons/trash.png')}
                  onClick={() => setIsOpen2(true)}
                  cursor="pointer"
                  size="1.5em"
                />
              ) : null}
              <AlertDialog
                isOpen={isOpen2}
                leastDestructiveRef={cancelRef}
                onClose={onClose2}
              >
                <AlertDialogOverlay />
                <AlertDialogContent>
                  <AlertDialogHeader fontSize="lg" fontWeight="bold">
                    Delete review
                  </AlertDialogHeader>

                  <AlertDialogBody>
                    Are you sure? You can't undo this action afterwards.
                  </AlertDialogBody>

                  <AlertDialogFooter>
                    <Flex
                      align="center"
                      justify="center"
                      height="56px"
                      width="30%"
                      color="#344CD0"
                      fontSize="16px"
                      fontWeight="bold"
                      ref={cancelRef}
                      onClick={onClose2}
                    >
                      Cancel
                    </Flex>
                    <Button
                      data-cy="confirmDeleteModalReview"
                      h="56px"
                      rounded="10px"
                      border="none"
                      color="white"
                      variantColor="red"
                      ml={3}
                      onClick={submitDelete}
                    >
                      Delete
                    </Button>
                  </AlertDialogFooter>
                </AlertDialogContent>
              </AlertDialog>
            </Flex>
          </Flex>
          {/* RIGHT SIDE MODAL */}
          <Flex
            direction="column"
            justify="flex-start"
            align="flex-start"
            position="absolute"
            w="575px"
            h="100%"
            ml="291px"
            mb="50px"
            mt="35px"
          >
            {/* TYPE OF REVIEW, TRACK, DATE POSTED */}
            <Flex justify="space-between" w="100%" mb="70px">
              <Flex justify="space-between">
                <Box as={MdRateReview} size="24px" color="#BBBDC6" mr="4px" />
                <Text
                  mr="40px"
                  color="#131C4D"
                  fontFamily="Muli"
                  fontSize="14px"
                >
                  {review.review_type === 'Company'
                    ? 'Company Review'
                    : 'Interview Review'}
                </Text>
                <Badge
                  backgroundColor={
                    review.track_name === 'WEB'
                      ? '#DBEBFD'
                      : review.track_name === 'iOS'
                      ? '#F4E6BE'
                      : review.track_name === 'UX'
                      ? '#F9E3DE'
                      : review.track_name === 'DS'
                      ? '#D3F2CD'
                      : review.track_name === 'Android'
                      ? '#E9D9FF'
                      : '#DBEBFD'
                  }
                  color={
                    review.track_name === 'WEB'
                      ? '#474EA7'
                      : review.track_name === 'iOS'
                      ? '#8E3D19'
                      : review.track_name === 'UX'
                      ? '#9F3A5A '
                      : review.track_name === 'DS'
                      ? '#35694F'
                      : review.track_name === 'Android'
                      ? '#4B3569'
                      : '#474EA7'
                  }
                  fontSize="16px "
                  fontWeight="light"
                  fontFamily="Muli"
                  rounded="full"
                  px="15px"
                  pt="2px"
                  overflow="hidden"
                >
                  {review.track_name}
                </Badge>
              </Flex>
              <Text color="#9194A8" fontSize="14px" fontFamily="Muli">
                {adjustedDate}
              </Text>
            </Flex>
            {/* INTERVIEW TYPES */}
            {review.review_type === 'Interview' ? (
              <Flex color="#9194A8" fontSize="14px" fontFamily="Muli">
                Interviews
              </Flex>
            ) : null}
            {review.review_type === 'Interview' ? (
              <Flex
                justify="flex-start"
                wrap="wrap"
                whiteSpace="nowrap"
                width="100%"
                mb="50px"
              >
                {review.phone_interview ? (
                  <Flex
                    as="p"
                    color="#131C4D"
                    fontSize="16px"
                    fontFamily="Muli"
                    bg="#EAF0FE"
                    px="1%"
                    mt="1.5%"
                    mr="3%"
                    rounded="3px"
                  >
                    Phone screening
                  </Flex>
                ) : null}
                {review.resume_review ? (
                  <Flex
                    as="p"
                    color="#131C4D"
                    fontSize="16px"
                    fontFamily="Muli"
                    bg="#EAF0FE"
                    px="1%"
                    mt="1.5%"
                    mr="3%"
                    rounded="3px"
                  >
                    Resume review
                  </Flex>
                ) : null}
                {review.take_home_assignments ? (
                  <Flex
                    as="p"
                    color="#131C4D"
                    fontSize="16px"
                    fontFamily="Muli"
                    bg="#EAF0FE"
                    px="1%"
                    mt="1.5%"
                    mr="3%"
                    rounded="3px"
                  >
                    Take home assignments
                  </Flex>
                ) : null}
                {review.online_coding_assignments ? (
                  <Flex
                    as="p"
                    color="#131C4D"
                    fontSize="16px"
                    fontFamily="Muli"
                    bg="#EAF0FE"
                    px="1%"
                    mt="1.5%"
                    mr="3%"
                    rounded="3px"
                  >
                    Online coding assignments
                  </Flex>
                ) : null}
                {review.portfolio_review ? (
                  <Flex
                    as="p"
                    color="#131C4D"
                    fontSize="16px"
                    fontFamily="Muli"
                    bg="#EAF0FE"
                    px="1%"
                    mt="1.5%"
                    mr="3%"
                    rounded="3px"
                  >
                    Portfolio review
                  </Flex>
                ) : null}
                {review.screen_share ? (
                  <Flex
                    as="p"
                    color="#131C4D"
                    fontSize="16px"
                    fontFamily="Muli"
                    bg="#EAF0FE"
                    px="1%"
                    mt="1.5%"
                    mr="3%"
                    rounded="3px"
                  >
                    Screen share
                  </Flex>
                ) : null}
                {review.open_source_contribution ? (
                  <Flex
                    as="p"
                    color="#131C4D"
                    fontSize="16px"
                    fontFamily="Muli"
                    bg="#EAF0FE"
                    px="1%"
                    mt="1.5%"
                    mr="3%"
                    rounded="3px"
                  >
                    Open source contribution
                  </Flex>
                ) : null}
                {review.side_projects ? (
                  <Flex
                    as="p"
                    color="#131C4D"
                    fontSize="16px"
                    fontFamily="Muli"
                    bg="#EAF0FE"
                    px="1%"
                    mt="1.5%"
                    mr="3%"
                    rounded="3px"
                  >
                    Side projects
                  </Flex>
                ) : null}
              </Flex>
            ) : null}
            {/* DESCRIPTION */}
            <Flex direction="column">
              <Text color="#9194A8" fontSize="14px" fontFamily="Muli" mb="7px">
                Description
              </Text>
              <Text
                color="#131C4D"
                fontSize="16px"
                fontFamily="Muli"
                lineHeight="23px"
              >
                {review.comment}
              </Text>
            </Flex>
          </Flex>
          {/* ADMIN BUTTONS */}
          <ModalFooter
            w="689px"
            ml="261px"
            mb="20px"
            position="absolute"
            bottom="0"
          >
            <BlockButton user_id={review.user_id} isAdmin={isAdmin} />
            <ContentButton
              isAdmin={isAdmin}
              submitDelete={submitDelete}
              user_id={review.user_id}
              review_id={review.review_id}
            />
          </ModalFooter>
        </ModalContent>
      </Modal>

      {/* ------------------------------------------------------------------------------------------------ */}
      {/* ---------------------------------------DashBoard Cards------------------------------------------ */}
      {/* ------------------------------------------------------------------------------------------------ */}

      {/* Review container */}
      <PseudoBox
        mb="3%"
        mx="2.5%"
        px="1%"
        py="1%"
        border="1px solid #E9F0FF"
        width="408px"
        height="309px"
        borderRadius="12px"
        display="flex"
        flexDir="column"
        _hover={{ bg: '#E9F0FF' }}
        onClick={onOpen}
        data-cy="modalCard"
      >
        {/* Review content container */}
        <Flex flexDir="column">
          {/* headline container  */}
          <Flex maxW="530px">
            <Flex
              height="115px"
              justify="space-between"
              maxW="391px"
              p="2% 5%"
              wrap="wrap"
            >
              <Flex maxW="300px">
                {review.review_type === 'Company' ? (
                  <Image
                    width="106px"
                    height="40px"
                    src={`https://logo.clearbit.com/${
                      review.logo !== 'unknown' ? review.logo : logo
                    }`}
                    fallbackSrc={`http://samscct.com/wp-content/uploads/2014/09/no-logo.png`}
                  />
                ) : (
                  <Text style={{ fontSize: '22px', fontWeight: 'bold' }}>
                    {' '}
                    {review.job_title}
                  </Text>
                )}
              </Flex>
              <i
                style={{ alignSelf: 'center', fontSize: '22px', opacity: '.2' }}
                className="far fa-heart"
              ></i>
              <Flex justify="space-between" width="391px" pt="2%">
                <Flex align="center">
                  {Array(5)
                    .fill('')
                    .map((_, i) => (
                      <Icon
                        name="star"
                        key={i}
                        color={i < review.overall_rating ? '#F9DC76' : '#fff'}
                        ml="8%"
                      />
                    ))}
                </Flex>
                <Flex>
                  <Text
                    style={{
                      color: '#BBBDC6',
                      fontSize: '14px',
                      fontWeight: 'bold',
                    }}
                  >
                    {created}
                  </Text>
                  {/* )} */}
                </Flex>
              </Flex>
              <Flex width="391px" height="45px" pt="15px">
                <Box as={MdRateReview} size="24px" color="#BBBDC6" mr="4px" />
                <span style={{ paddingLeft: '5px' }}>
                  {review.review_type} review
                </span>
              </Flex>
            </Flex>
          </Flex>
        </Flex>
        {/* summary container */}
        <Flex width="100%" height="100px">
          <Flex m="10px 20px" w="348px" h="55px" overflow="hidden">
            <p style={{ fontSize: '14px', color: 'gray' }}>{review.comment}</p>
          </Flex>
        </Flex>
        <Flex
          margin="0px 12px 0px 20px"
          align="center"
          pt="5px"
          height="40px"
          justify="space-between"
        >
          <Flex alignItems="center">
            <Avatar size="md" src={review.user_profile_image} />
            <Text pl="5px" fontSize="14px">
              {review.user_first_name} {review.user_last_name}
            </Text>
          </Flex>
          <Badge
            backgroundColor={trackColorPicker(review.track_name)}
            color={trackFontColor(review.track_name)}
            fontSize="1em"
            fontWeight="light"
            rounded="full"
            textAlign="center"
            pt="5px"
            overflow="hidden"
            ml="10px"
            width="58px"
            height="36px"
          >
            <span>{review.track_name}</span>
          </Badge>
        </Flex>
      </PseudoBox>
    </>
  )
}
Example #6
Source File: index.js    From here-covid-19-tracker with MIT License 4 votes vote down vote up
App = () => {
  const currentTab = useTabStore(state => state.currentTab)

  const { data, error } = useSWR(`https://xyz.api.here.com/hub/spaces/${spaceId}/bbox?west=-180&north=90&east=180&south=-90&access_token=${accessToken}`, fetcher, { focusThrottleInterval: 60000 })
  const points = data ? (data.features || []) : []

  useEffect(() => {
    const cbox = document.getElementsByClassName("main-combobox")[0]
    if (cbox) cbox.focus()
  }, [])

  return (
    <>
      <Box
        display={!currentTab ? "block" : ["none", null, "block"]}
        position="fixed"
        top="0"
        left="0"
        bottom="0"
        zIndex={999999}
        borderTop="0.25rem solid #00AFAA"
        width={["100%", null, "25rem", "30rem"]}
        boxShadow="lg"
        overflow="scroll"
        bg="white"
        pb="5rem"
        style={{
          WebkitOverflowScrolling: "touch",
        }}
      >
        <Box px="1.25rem" pt="1.25rem">
          <Heading fontSize={["1.5rem", "2rem", null, "2.5rem"]} lineHeight={1.125} mb="1.25rem">
            <Text mr="0.75rem" as="span">
              { "Tracking Coronavirus" } <br/>
              { "COVID-19" }
            </Text>
          </Heading>
          { points.length ? <IntroParagraph points={points} /> : null}
          { points.length ? <TimeSlider points={points} /> : null }
        </Box>
        { points.length ? <Listing rows={points} /> : null }
      </Box>

      <Flex
        position="absolute"
        bottom={["3.5rem", null, "1.25rem"]}
        left={["1rem", null, "26.25rem", "32.5rem"]}
        right={["1rem", null, "2rem"]}
        zIndex={2}
        justifyContent="space-between"
        alignItems="flex-end"
      >
        <Flex flexWrap="wrap" justifyContent="space-between" flex="1 1 auto" pr={["0.75rem", null, 0]}>
          <Text as="span" fontSize="xs" color="gray.900" fontWeight={600}>
            {"Data: "}
            <Link href="https://github.com/CSSEGISandData/COVID-19" color="#00AFAA" bg="white" py="0.125rem" px="0.25rem">{"JHU CSSE"}</Link>
            { " and " }
            <Link href="https://ncov.dxy.cn/ncovh5/view/pneumonia?scene=2&clicktime=1579582238&enterid=1579582238&from=singlemessage&isappinstalled=0" color="#00AFAA" bg="white" py="0.125rem" px="0.25rem">
              {"DXY"}
            </Link>
          </Text>
          <Text as="span" fontSize="xs" color="gray.900" fontWeight={600}>
            {"Made with Leaflet, "}
            <Link href="https://developer.here.com/documentation/vector-tiles-api/dev_guide?cid=Freemium-DeveloperPortalTutorial-PJ-0-Javascript-DevPortal-&utm_source=DeveloperPortalTutorial&utm_medium=referral&utm_campaign=Webinar_IOT_2020_Golden-Age-Location-Enabled-AI-Jan-16" color="#00AFAA" bg="white" py="0.125rem" px="0.25rem">{"HERE Vector Map Tiles API"}</Link>
            {" and "}
            <Link href="https://developer.here.com/products/xyz?cid=Freemium-DeveloperPortalTutorial-PJ-0-XYZ-DevPortal-&utm_source=DeveloperPortalTutorial&utm_medium=referral&utm_campaign=CoronaVirusMap" color="#00AFAA" bg="white" py="0.125rem" px="0.25rem">{"HERE Data Hub APIs"}</Link>
            { " | " }
            <Link href="#" color="#00AFAA" bg="white" py="0.125rem" px="0.25rem">
              {"Get the code"}
              <Icon name="github" ml="0.25rem" mt="-0.125rem" />
            </Link>
          </Text>
        </Flex>
        <Link flex="none" href="https://developer.here.com/?cid=Freemium-DeveloperPortalTutorial-PJ-0-Javascript-DevPortal-&utm_source=DeveloperPortalTutorial&utm_medium=referral&utm_campaign=Webinar_IOT_2020_Golden-Age-Location-Enabled-AI-Jan-16">
          <img src={hereLogo} alt="HERE logo" style={{ width: "2.5rem", marginLeft: "0.75rem" }} />
        </Link>
      </Flex>

      <Map points={points} />

      <Search />

      <Box
        position="fixed"
        bottom={["5.5rem", null, "4rem"]}
        right={["1rem", null, "2.5rem"]}
        zIndex={2}
        width={["6rem", "8rem", "10rem"]}
        height={["6rem", "8rem", "10rem"]}
        boxShadow="lg"
        borderRadius="100%"
        bg="white"
        border="0.125rem solid"
        borderColor="gray.50"
        pointerEvents="none"
      >
        <Globe />
      </Box>

      {
        currentTab === 2 ? (
          <Box
            display="block"
            position="fixed"
            top="0"
            left="0"
            bottom="0"
            zIndex={999999}
            borderTop="0.25rem solid #00AFAA"
            width={["100%", null, "25rem", "30rem"]}
            boxShadow="lg"
            overflow="scroll"
            bg="white"
            pb="5rem"
            style={{
              WebkitOverflowScrolling: "touch",
            }}
          >
            <Box px="1.25rem" pt="1.25rem">
              <AboutContent />
            </Box>
          </Box>
        ) : null
      }

      <NavigationTabs />

      <CurrentCircle />

    </>
  )
}
Example #7
Source File: index.js    From here-covid-19-tracker with MIT License 4 votes vote down vote up
Combobox = ({ items = [] }) => {

  const updateMapFocus = useMapFocus(state => state.updateMapFocus)

  const [inputItems, setInputItems] = useState(items)

  const {
    isOpen,
    // selectedItem,
    // getToggleButtonProps,
    // getLabelProps,
    getMenuProps,
    getInputProps,
    getComboboxProps,
    highlightedIndex,
    getItemProps,
    inputValue,
    setInputValue,
  } = useCombobox({
    items: inputItems,
    onSelectedItemChange: ({selectedItem}) => {
      if (selectedItem && selectedItem.simpleLabel) {
        fetch(`${geoCodeBaseUrl}?apiKey=${apiKey}&locationId=${selectedItem.locationId}`)
          .then(d => d.json())
          .then(d => {
            const coordinates = d.Response.View[0].Result[0].Location.DisplayPosition
            updateMapFocus([coordinates.Latitude, coordinates.Longitude], null, 7)
          })
        setInputValue(selectedItem.simpleLabel.replace(/<[^>]*>/g, ""))
      } else {
        setInputValue("")
      }
    },
    onInputValueChange: ({ inputValue }) => {
      fetch(`${baseUrl}?apiKey=${apiKey}&language=en&maxresults=10&matchLevel=city&query=${inputValue.split(" ").join("+")}&beginHighlight=<strong>&endHighlight=</strong>`)
        .then(d => d.json())
        .then(d => {
          if (d.suggestions) {
            setInputItems(d.suggestions.filter(d => d.matchLevel === "city").map(d => {
              return {
                ...d,
                simpleLabel: d.address.city
                  ? `${d.address.city}${d.address.state ? ", " + d.address.state : ""}, ${d.address.country}`
                  : d.address.country
                }
            }))
          } else {
            setInputItems([])
          }
        })
    },
  })

  return (
    <>
      <Box position="relative">
        <Box {...getComboboxProps()}>
          <InputGroup boxShadow="lg" size="lg">
            <Input
              {...getInputProps({ placeholder: "Search the map", className: "main-combobox" })}
              style={{ WebkitAppearance: "none" }}
              borderColor="transparent"
              borderRadius="md"
              _hover={{ borderColor: "transparent" }}
              _focus={{ borderColor: "rgba(236,97,14, 1)", boxShadow: `0 0 0 0.0625rem rgba(236,97,14, 1), 0 0 0 0.25rem rgba(236,97,14, 0.25)` }}
              _placeholder={{ color: "gray.500" }}
            />
            <InputRightElement>
              {
                inputValue ? (
                  <IconButton
                    icon="close"
                    isRound
                    size="sm"
                    aria-label={"toggle menu"}
                    onClick={() => setInputValue("")}
                  />
                ) : (
                  <Icon name="search" color="gray.500" />
                )
              }
            </InputRightElement>
          </InputGroup>
        </Box>
        {
          isOpen && inputItems.length ?
          <Box
            position="absolute"
            top="100%"
            left={0}
            right={0}
            mt="0.5rem"
            bg="white"
            borderRadius="md"
            shadow="md"
            maxHeight="14rem"
            overflow="scroll"
            py="0.75rem"
          >
            <List {...getMenuProps()}>
              {!inputItems.length
                ? (
                  <ListItem py="0.5rem" px="1rem" color="gray.500" alignItems="center" display="flex">
                    <Icon name="not-allowed" mr="0.25rem" />{ "Address not found" }
                  </ListItem>
                )
                : null}
              {inputItems.map((item, index) => {
                const val = item.simpleLabel
                return (
                  <ListItem
                    isTruncated
                    key={`${val}${index}`}
                    style={{
                      backgroundColor: highlightedIndex === index ? colors.orange[50] : "transparent",
                    }}
                    py="0.5rem"
                    px="1rem"
                    {...getItemProps({ item: val, index })}
                    dangerouslySetInnerHTML={{ __html: val }}
                  />
                )
              })
              }
            </List>
          </Box> : null
        }
      </Box>
    </>
  )
}
Example #8
Source File: index.js    From here-covid-19-tracker with MIT License 4 votes vote down vote up
Listing = ({ rows }) => {
  const currentDataType = useDataTypeStore(state => state.currentDataType)
  const tabIndex = currentDataType
  const currentDate = useDataDate(state => state.currentDate)
  const updateMapFocus = useMapFocus(state => state.updateMapFocus)
  const updateTab = useTabStore(state => state.updateTab)

  const handleClick = (coordinates, properties) => {
    updateTab(1)
    updateMapFocus([ coordinates[1], coordinates[0] ], properties)
  }

  const grouped = groupBy(rows.map(d =>
    d.properties.countryregion === "Mainland China" || d.properties.countryregion === "Hong Kong" || d.properties.countryregion === "Macau" || d.properties.countryregion === "Taiwan" ? { ...d, properties: { ...d.properties, countryregion: "China" } } : d),
    // d),
    o => o.properties.countryregion
  )

  const groups = Object.keys(grouped).map(d => {
    return {
      key: d,
      sum: grouped[d].reduce((acc, cur) => acc + parseInt(cur.properties[currentDate] || 0), 0),
      sum2: grouped[d].reduce((acc, cur) => acc + parseInt(cur.properties["deaths_" + currentDate] || 0), 0),
      sum3: grouped[d].reduce((acc, cur) => acc + parseInt(cur.properties["recoveries_" + currentDate] || 0), 0),
      items: grouped[d].filter(d => d.properties[currentDate]).sort((a, b) => b.properties[currentDate] - a.properties[currentDate]),
    }
  }).filter(d => d.sum)
    .sort((a, b) => {
      return tabIndex === 0
        ? b.sum - a.sum
        : tabIndex === 1
          ? b.sum2 - a.sum2
          : b.sum3 - a.sum3
    })

  return (
    <div>

      <DataTypeSwitch rows={rows} />

      <Accordion defaultIndex={[0]} allowMultiple mt="0">

        {
          groups.map((group, i) => {
            return (
              <AccordionItem key={group.key} borderColor={!i ? "transparent" : "gray.200"}>
                <AccordionHeader>
                  <Flex justifyContent="space-between" alignItems="center" flex="1 1 auto" py="0.5rem">
                    <Heading pl="1.25rem" color="gray.500" fontSize="1rem" textTransform="uppercase">
                      {group.key}
                    </Heading>
                    <Box pr="1.25rem" color="gray.500" fontWeight={700}>
                      { tabIndex === 0 ? formatThousand(group.sum) : null }
                      { tabIndex === 1 ? formatThousand(group.sum2) : null }
                      { tabIndex === 2 ? formatThousand(group.sum3) : null }
                    </Box>
                  </Flex>
                  <AccordionIcon mr="1.375rem" />
                </AccordionHeader>
                <AccordionPanel pt="0">
                  {
                    group.items.map(({ properties, geometry }, i) => {

                      const {
                        provincestate,
                        countryregion,
                        ...restProps
                      } = properties

                      return (
                        <PseudoBox
                          tabIndex={0}
                          key={provincestate + i}
                          bg="transparent"
                          borderRadius="lg"
                          py="0.75rem"
                          px="1.25rem"
                          border="0.0625rem solid"
                          borderColor="gray.200"
                          mt="0.5rem"
                          mb="0.75rem"
                          onClick={() => handleClick(geometry.coordinates, properties)}
                          cursor="pointer"
                          _hover={{
                            bg: "gray.100",
                          }}
                          _focus={{
                            bg: "gray.100",
                          }}
                          _active={{
                            bg: "gray.200",
                          }}
                        >
                          <Stack isInline alignItems="top" justifyContent="space-between">
                            <Stack spacing="0.125rem">
                              <Text lineHeight={1.25} color="gray.500" fontSize="xs" fontWeight={600} textTransform="uppercase">
                                {countryregion}
                              </Text>
                              <Text fontSize="lg" lineHeight={1.25} fontWeight={700}>
                                {provincestate || countryregion}
                              </Text>
                            </Stack>
                            <Stack isInline alignItems="center" spacing="1.5rem">
                              <Stack spacing="0.125rem" textAlign="right">
                                <Text lineHeight={1.25} color="gray.500" fontSize="xs" fontWeight={600} textTransform="uppercase">
                                  { tabIndex === 0 ? "Confirmed" : null }
                                  { tabIndex === 1 ? "Deaths" : null }
                                  { tabIndex === 2 ? "Recoveries" : null }
                                </Text>
                                <Text fontSize="lg" fontWeight={700} color="gray.500">
                                  { tabIndex === 0 ? formatThousand(restProps[currentDate] || 0) : null }
                                  { tabIndex === 1 ? formatThousand(restProps["deaths_" + currentDate] || 0) : null }
                                  { tabIndex === 2 ? formatThousand(restProps["recoveries_" + currentDate] || 0) : null }
                                </Text>
                              </Stack>
                              <Icon name="pin" size="1.5rem" color="gray.600"/>
                            </Stack>
                          </Stack>
                        </PseudoBox>
                      )
                    })
                  }
                </AccordionPanel>
              </AccordionItem>
            )
          })
        }
      </Accordion>
    </div>
  )
}
Example #9
Source File: index.js    From here-covid-19-tracker with MIT License 4 votes vote down vote up
Map = ({ points }) => {

  const currentDataType = useDataTypeStore(state => state.currentDataType)

  const updateCenter = useStore(state => state.updateCenter)
  const mapFocus = useMapFocus(state => state.mapFocus)
  const mapZoom = useMapFocus(state => state.mapZoom)
  const updateMapFocus = useMapFocus(state => state.updateMapFocus)
  const currentDate = useDataDate(state => state.currentDate)
  const [loadedMap, setLoadedMap] = useState(false)

  const mapRef = useRef()
  const Leaflet = useRef()
  const sceneRef = useRef()
  const leafletMap = useRef()

  useEffect(() => {
    if (typeof window === undefined || !points.length) return
    const L = require("leaflet")
    const Tangram = require("tangram")
    Leaflet.current = L

    if (leafletMap.current) {
      leafletMap.current.remove()
      leafletMap.current = null
      sceneRef.current = null
    }

    const popup = L.popup({ autoPan: false })

    const map = L.map(mapRef.current, {
      zoomControl: false,
      minZoom: 3,
      maxZoom: 8,
      scrollWheelZoom: true,
    })

    const layer = Tangram.leafletLayer({
      scene,
      attribution: "Loading map",
      webGLContextOptions: {
        antialias: false,
      },
      events: {
        click: selection => {
          if (!selection.feature || (!selection.feature && !selection.feature.properties)) {
            return
          }
          const { lat, long } = selection.feature.properties
          updateMapFocus([lat, long], selection.feature.properties)
        },
        hover: selection => {
          if (!selection.feature || (!selection.feature && !selection.feature.properties)) {
            mapRef.current.style.cursor = "default"
            map.closePopup()
            return
          }

          mapRef.current.style.cursor = "pointer"

          const coords = selection.leaflet_event.latlng
          const sceneDate = sceneRef.current.config.global.currentDate
          const sceneDataType = sceneRef.current.config.global.currentDataType
          const { prefix } = sceneRef.current.config.global

          const num = formatThousand(selection.feature.properties[prefix + sceneDate])

          const isChina = ["Mainland China", "Macau", "Hong Kong", "Taiwan"].includes(selection.feature.properties.countryregion)

          const label = sceneDataType === 0
            ? "Confirmed cases" : sceneDataType === 1 ? "Deaths" : "Recoveries"

          const value = num
            ? `
              <div>
                <div class="tt-address">
                  <p class="tt-zip-code-value">
                    ${selection.feature.properties.provincestate || selection.feature.properties.countryregion}
                  </p>
                  ${
                    selection.feature.properties.provincestate ? `
                      <p class="tt-zip-code-title">
                        ${isChina ? "China" : selection.feature.properties.countryregion}
                      </p>` : ""
                  }
                </div>
                <p class="tt-median-rent-title">${label}</p>
                <p class="tt-median-rent-value">
                  <span>${num}</span>
                </p>
              </div>
            `
            : ""

          popup
            .setLatLng([coords.lat, coords.lng])
            .setContent(`${value}`)
            .openOn(map)

        }
      },
    })

    map.on("move", () => {
      const { lat, lng } = map.getCenter()
      updateCenter([-lng, -lat])
    })

    layer.addTo(map)
    sceneRef.current = layer.scene    
    map.setView([30, 110], 4)
    leafletMap.current = map

    const geojsonData = {
      type: "FeatureCollection",
      features: points,
    }

    const ext = extent(points, d => {
      const headers = d.properties.headers.split(";;")
      const lastDate = headers[headers.length - 1]
      return parseInt(d.properties[lastDate])
    })

    layer.scene.subscribe({
      load: () => {
        layer.scene.config.global.max = ext[1]
        layer.scene.updateConfig()
        layer.scene.setDataSource("dynamic_data", {
          type: "GeoJSON",
          data: geojsonData,
        })
        setLoadedMap(true)
      },
    })

  }, [points])

  const cf = sceneRef.current && sceneRef.current.config

  useEffect(() => {
    if (!mapFocus) return
    leafletMap.current.flyTo(mapFocus, mapZoom || 5, { easeLinearity: 0.01, duration: 1.5 })
  }, [mapFocus, mapZoom])

  useEffect(() => {
    if (!currentDate || !sceneRef.current || !sceneRef.current.config) return
    if (currentDate === sceneRef.current.config.global.currentDate) return
    sceneRef.current.config.global.currentDate = currentDate
    sceneRef.current.updateConfig()
  }, [currentDate, cf])

  useEffect(() => {
    if (!sceneRef.current || !sceneRef.current.config) return
    sceneRef.current.config.global.currentDataType = currentDataType || 0
    sceneRef.current.config.global.prefix = currentDataType === 0
      ? ""
      : currentDataType === 1
        ? "deaths_"
        : "recoveries_"
    sceneRef.current.updateConfig()
  }, [currentDataType, cf])

  const handleZoomIn = () => {
    leafletMap.current.zoomIn()
  }

  const handleZoomOut = () => {
    leafletMap.current.zoomOut()
  }

  return (
    <>
      <Box
        ref={mapRef}
        top="0"
        left={[0, null, "25rem", "30rem"]}
        right="0"
        bottom="0"
        style={{ position: "fixed", transition: "opacity 500ms", opacity: loadedMap ? 1 : 0 }}
      />

      {
        !loadedMap ? (
          <Box
            position="fixed"
            top="50%"
            left={["50%", null, "calc((100% + 25rem) / 2)", "calc((100% + 30rem) / 2)"]}
            zIndex={9999}
            transform="translateX(-50%)"
          >
            <Icon
              name="spinner"
              size="2.5rem"
              color="gray.500"
              animation={`${rotate} 1s linear infinite`}
              mx="auto"
              display="block"
            />
            <Text textAlign="center" color="gray.500" mx="auto" fontSize="sm" mt="0.75rem">
              { "Loading map" }
            </Text>
          </Box>
        ) : null
      }
      
      <Box
        position="fixed"
        bottom={["6rem", "8rem", "5rem"]}
        left={["auto", null, "26.5rem", "32.5rem"]}
        right={["2.75rem", "3.75rem", "auto"]}
        zIndex={2}
        pointerEvents={["none", null, "all"]}
      >

        <Stack spacing="0.5rem" alignItems="center" mb={["6.5rem", null, "1.25rem"]}>
          <Text color="gray.600" width="2.5rem" textAlign="center" fontWeight={700} fontSize="xs" lineHeight="shorter">
            { "more cases" }
          </Text>
          <Box width="2.5rem" height="2.5rem" border="0.125rem solid" borderColor="gray.500" borderRadius="100%" />
          <Box width="1.25rem" height="1.25rem" border="0.125rem solid" borderColor="gray.500" borderRadius="100%" />
          <Box width="0.625rem" height="0.625rem" border="0.125rem solid" borderColor="gray.500" borderRadius="100%" />
          <Text color="gray.600" width="2.5rem" textAlign="center" fontWeight={700} fontSize="xs" lineHeight="shorter">
            { "fewer cases" }
          </Text>
        </Stack>

        <Stack display={["none", null, "block"]} spacing="1.25rem">
          <Flex justifyContent="center">
            <Flex alignItems="center" direction="column" shadow="lg" borderRadius="md">
              <IconButton 
                onClick={handleZoomIn}
                icon="add" bg="white"
                borderRadius="0.25rem 0.25rem 0 0"
                border="0.0625rem solid"
                borderColor="transparent"
                  _hover={{ borderColor: "transparent" }}
                  _focus={{ borderColor: "rgba(236,97,14, 1)", boxShadow: `0 0 0 0.0625rem rgba(236,97,14, 1), 0 0 0 0.25rem rgba(236,97,14, 0.25)` }}
                  _placeholder={{ color: "gray.500" }}
              />
              <Box height="1px" width="100%" bg="gray.100" />
              <IconButton 
                onClick={handleZoomOut}
                icon="minus"
                bg="white"
                borderRadius="0 0 0.25rem 0.25rem"
                border="0.0625rem solid"
                borderColor="transparent"
                  _hover={{ borderColor: "transparent" }}
                  _focus={{ borderColor: "rgba(236,97,14, 1)", boxShadow: `0 0 0 0.0625rem rgba(236,97,14, 1), 0 0 0 0.25rem rgba(236,97,14, 0.25)` }}
                  _placeholder={{ color: "gray.500" }}
              />
            </Flex>
          </Flex>
        </Stack>
      </Box>
    </>
  )
}
Example #10
Source File: index.js    From here-covid-19-tracker with MIT License 4 votes vote down vote up
TimeSlider = ({ points }) => {
  const updateDate = useDataDate(state => state.updateDate)

  const uniqDays = useMemo(() => {
    const headers = points[0].properties.headers.split(";;")
    const allDates = headers
      .filter(d => {
        return d.includes("/" && ":" && "pm") || d.includes("/" && ":" && "am")
      })
      .sort((a, b) => {
        const date1 = new Date(a).getTime() 
        const date2 = new Date(b).getTime()
        return date1 - date2
      })

    const uniqDates = groupBy(allDates, o => {
      return dayjs(o).format("DD-MM-YYYY")
    })

    const uniqDays = Object.keys(uniqDates).map(d => {
      return uniqDates[d][uniqDates[d].length - 1]
    })

    return uniqDays
  }, [points])

  const [currentDate, setCurrentDate] = useState(uniqDays.length - 1)

  const [debouncedCurrentDate] = useDebounce(currentDate, 150)

  useEffect(() => {
    updateDate(uniqDays[debouncedCurrentDate])
  }, [debouncedCurrentDate, uniqDays, updateDate])

  return (
    <Box mt="2rem">

      <Heading fontSize="md" as="h3" mb="0.5rem">
        { "Timeline" }
      </Heading>

      <Flex mb="-0.75rem" zIndex={10} position="relative">
        <Badge display="inline-flex" alignItems="center" bg="#FBDFCF" color="#ec610e" fontSize="sm">
          <BlinkingDot />
            {
              currentDate === uniqDays.length - 1
                ? dayjs(points[0].properties["@ns:com:here:xyz"].updatedAt).format("DD MMM YYYY h:mm a")
                : dayjs(uniqDays[currentDate]).format("DD MMM YYYY") 
            }
        </Badge>
      </Flex>

      <TimeSeries points={points} dates={uniqDays} currentDate={currentDate} />

      <Box mr="2px">
        <Slider
          defaultValue={uniqDays.length - 1}
          min={0}
          max={uniqDays.length - 1}
          value={currentDate}
          onChange={val => setCurrentDate(val)}
        >
          <SliderTrack />
          <SliderFilledTrack bg="#ec610e" />
          <SliderThumb size="1.5rem" ml="-0.25rem">
            <Icon name="arrows" color="#ec610e" />
          </SliderThumb>
        </Slider>
      </Box>

      <Flex justifyContent="space-between">
        <Text fontSize="sm" color="gray.600" mt="-0.5rem">
          { dayjs(uniqDays[0]).format("DD MMM YYYY") }
        </Text>
        <Text fontSize="sm" color="gray.600" mt="-0.5rem">
          { dayjs(uniqDays[uniqDays.length - 1]).format("DD MMM YYYY") }
        </Text>
      </Flex>
    </Box>
  )
}
Example #11
Source File: AltListItem.js    From opensource.builders with MIT License 4 votes vote down vote up
export default function AltListItem({ alt }) {
  return (
    <Box
      width={{ base: "100%" }}
      borderRadius="4px"
      m={2}
      boxShadow="0px 1px 4px rgba(0, 0, 0, 0.16)"
      bg="white"
    >
      <Box as="a" target="_blank" href={alt.site}>
        <Box display="flex" p={2}>
          <Box display="flex">
            <Box
              as="img"
              height="56px"
              width="56px"
              mr={3}
              borderRadius="4px"
              boxShadow="0px 1px 4px rgba(0, 0, 0, 0.16)"
              src={alt.svg}
            />
            <Box
              display="flex"
              flexDirection="column"
              justifyContent="center"
              lineHeight="21px"
            >
              <Text fontSize="md" fontWeight={500}>
                {alt.name}
              </Text>
              <Box
                fontSize={14}
                color="#D69E2E"
                display="flex"
                alignItems="center"
                fontWeight={600}
                mt={1}
              >
                <Icon name="star" size={3} mr={1} /> {alt.stars}
                <Tooltip
                  bg="rgb(45, 55, 72)"
                  color="rgba(255, 255, 255, 0.92);"
                  hasArrow
                  label="Language"
                  placement="top"
                >
                  <Badge ml={3} variantColor="green">
                    {alt.language}
                  </Badge>
                </Tooltip>
                <Tooltip
                  variantColor="blue"
                  hasArrow
                  label="License"
                  placement="top"
                >
                  <Badge
                    ml={3}
                    bg="rgb(206, 237, 255)"
                    color="rgb(21, 62, 117)"
                  >
                    {alt.license}
                  </Badge>
                </Tooltip>
              </Box>
            </Box>
          </Box>
          <Box
            ml="auto"
            display={{ base: "none", sm: "flex" }}
            alignItems="center"
          >
            <Box as="a" href={alt.deploy} target="_blank" mx={5}>
              {alt.deploy ? (
                deployLogo(alt.deploy)
              ) : (
                <Tooltip
                  bg="rgb(45, 55, 72)"
                  color="rgba(255, 255, 255, 0.92);"
                  hasArrow
                  label={"No Deploy Instructions Found"}
                  placement="top"
                >
                  <Box size={4}>
                    <svg
                      viewBox="0 0 24 24"
                      fill="none"
                      xmlns="http://www.w3.org/2000/svg"
                    >
                      <path
                        d="M12 8V12M12 16H12.01M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z"
                        stroke="#718096"
                        strokeWidth="2"
                        strokeLinecap="round"
                        strokeLinejoin="round"
                      />
                    </svg>
                  </Box>
                </Tooltip>
              )}
            </Box>
            <Tooltip
              bg="rgb(45, 55, 72)"
              color="rgba(255, 255, 255, 0.92);"
              hasArrow
              label="Repo"
              placement="top"
            >
              <Box
                as="a"
                href={`https://github.com/${alt.repo}`}
                target="_blank"
              >
                <svg
                  stroke="#718096"
                  fill="#718096"
                  strokeWidth="0"
                  version="1.1"
                  viewBox="0 0 32 32"
                  height="1.1em"
                  width="1.1em"
                  xmlns="http://www.w3.org/2000/svg"
                >
                  <path d="M16 5.343c-6.196 0-11.219 5.023-11.219 11.219 0 4.957 3.214 9.162 7.673 10.645 0.561 0.103 0.766-0.244 0.766-0.54 0-0.267-0.010-1.152-0.016-2.088-3.12 0.678-3.779-1.323-3.779-1.323-0.511-1.296-1.246-1.641-1.246-1.641-1.020-0.696 0.077-0.682 0.077-0.682 1.126 0.078 1.72 1.156 1.72 1.156 1.001 1.715 2.627 1.219 3.265 0.931 0.102-0.723 0.392-1.219 0.712-1.498-2.49-0.283-5.11-1.246-5.11-5.545 0-1.226 0.438-2.225 1.154-3.011-0.114-0.285-0.501-1.426 0.111-2.97 0 0 0.941-0.301 3.085 1.15 0.894-0.25 1.854-0.373 2.807-0.377 0.953 0.004 1.913 0.129 2.809 0.379 2.14-1.453 3.083-1.15 3.083-1.15 0.613 1.545 0.227 2.685 0.112 2.969 0.719 0.785 1.153 1.785 1.153 3.011 0 4.31-2.624 5.259-5.123 5.537 0.404 0.348 0.761 1.030 0.761 2.076 0 1.5-0.015 2.709-0.015 3.079 0 0.299 0.204 0.648 0.772 0.538 4.455-1.486 7.666-5.69 7.666-10.645 0-6.195-5.023-11.219-11.219-11.219z" />
                </svg>
              </Box>
            </Tooltip>

            <Tooltip
              bg="rgb(45, 55, 72)"
              color="rgba(255, 255, 255, 0.92);"
              hasArrow
              label="Website"
              placement="top"
            >
              <Box size={5} mx={3} as="a" href={alt.site} target="_blank">
                <svg viewBox="0 0 24 24" focusable="false" role="presentation">
                  <path
                    fill="#718096"
                    d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"
                  />
                </svg>
              </Box>
            </Tooltip>
          </Box>
        </Box>
        <Divider display={{ sm: "none" }} my={0} borderColor="#edf1f6" />
        <Box
          display={{ base: "flex", sm: "none" }}
          alignItems="center"
          justifyContent="center"
        >
          <Box
            width="33%"
            display="flex"
            alignItems="center"
            justifyContent="center"
            py={1}
          >
            <Box
              as="a"
              href={alt.deploy}
              target="_blank"
              display="flex"
              alignItems="center"
              px={10}
            >
              {alt.deploy ? (
                deployLogo(alt.deploy)
              ) : (
                <Tooltip
                  bg="rgb(45, 55, 72)"
                  color="rgba(255, 255, 255, 0.92);"
                  hasArrow
                  label={"No Deploy Instructions Found"}
                  placement="top"
                >
                  <Box size={4}>
                    <svg
                      viewBox="0 0 24 24"
                      fill="none"
                      xmlns="http://www.w3.org/2000/svg"
                    >
                      <path
                        d="M12 8V12M12 16H12.01M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z"
                        stroke="#718096"
                        strokeWidth="2"
                        strokeLinecap="round"
                        strokeLinejoin="round"
                      />
                    </svg>
                  </Box>
                </Tooltip>
              )}
              <Heading
                fontSize="xs"
                color="gray.500"
                letterSpacing="wide"
                textTransform="uppercase"
                ml={1}
              >
                Deploy
              </Heading>
            </Box>
          </Box>
          <Box
            width="34%"
            display="flex"
            alignItems="center"
            justifyContent="center"
            borderRight="1px solid #edf1f6"
            borderLeft="1px solid #edf1f6"
            py={1}
          >
            <Box
              as="a"
              href={`https://github.com/${alt.repo}`}
              target="_blank"
              display="flex"
              alignItems="center"
            >
              <svg
                stroke="#718096"
                fill="#718096"
                strokeWidth="0"
                version="1.1"
                height="1.2em"
                width="1.2em"
                viewBox="0 0 32 32"
                xmlns="http://www.w3.org/2000/svg"
              >
                <path d="M16 5.343c-6.196 0-11.219 5.023-11.219 11.219 0 4.957 3.214 9.162 7.673 10.645 0.561 0.103 0.766-0.244 0.766-0.54 0-0.267-0.010-1.152-0.016-2.088-3.12 0.678-3.779-1.323-3.779-1.323-0.511-1.296-1.246-1.641-1.246-1.641-1.020-0.696 0.077-0.682 0.077-0.682 1.126 0.078 1.72 1.156 1.72 1.156 1.001 1.715 2.627 1.219 3.265 0.931 0.102-0.723 0.392-1.219 0.712-1.498-2.49-0.283-5.11-1.246-5.11-5.545 0-1.226 0.438-2.225 1.154-3.011-0.114-0.285-0.501-1.426 0.111-2.97 0 0 0.941-0.301 3.085 1.15 0.894-0.25 1.854-0.373 2.807-0.377 0.953 0.004 1.913 0.129 2.809 0.379 2.14-1.453 3.083-1.15 3.083-1.15 0.613 1.545 0.227 2.685 0.112 2.969 0.719 0.785 1.153 1.785 1.153 3.011 0 4.31-2.624 5.259-5.123 5.537 0.404 0.348 0.761 1.030 0.761 2.076 0 1.5-0.015 2.709-0.015 3.079 0 0.299 0.204 0.648 0.772 0.538 4.455-1.486 7.666-5.69 7.666-10.645 0-6.195-5.023-11.219-11.219-11.219z" />
              </svg>
              <Heading
                fontSize="xs"
                color="gray.500"
                letterSpacing="wide"
                textTransform="uppercase"
                ml={1}
              >
                Repo
              </Heading>
            </Box>
          </Box>
          <Box
            width="33%"
            display="flex"
            alignItems="center"
            justifyContent="center"
            py={1}
          >
            <Box
              mx={3}
              as="a"
              href={alt.site}
              target="_blank"
              display="flex"
              alignItems="center"
            >
              <Heading
                fontSize="xs"
                color="gray.500"
                letterSpacing="wide"
                textTransform="uppercase"
              >
                site
              </Heading>
              <svg
                viewBox="0 0 24 24"
                focusable="false"
                role="presentation"
                height="1.2em"
                width="1.2em"
              >
                <path
                  fill="#718096"
                  d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"
                />
              </svg>
            </Box>
          </Box>
        </Box>
      </Box>
    </Box>
  )
}
Example #12
Source File: ClientSearch.js    From opensource.builders with MIT License 4 votes vote down vote up
render() {
    const {
      searchResults,
      searchQuery,
      category,
      language,
      license,
    } = this.state
    const queryResults =
      searchQuery === `` && license === `` && language === `` && category === ``
        ? this.props.comps
        : searchResults

    const compLoad =
      searchQuery === `` && license === `` && language === `` && category === ``
        ? this.props.mainInfo.slice(0, this.props.loadCount)
        : this.props.mainInfo

    const categories = [
      "E-commerce",
      "Developer Tools",
      "Social Media",
      "Communication",
      "Analytics",
      "Password Managers",
      "Form Builder",
      "Cloud",
      "Deployment",
      "Product Management",
      "Automation",
      "CRM",
    ]

    const licenses = [
      "GPL V3",
      "BSD-3",
      "GPL",
      "MIT",
      "OSL-3.0",
      "APACHE 2.0",
      "AGPL V3",
      "CUSTOM",
    ]

    const languages = [
      "GO",
      "JS",
      "PYTHON",
      "PHP",
      "ELIXIR",
      "RUBY",
      "C",
      "C#",
      "C++",
      "SHELL",
      "TS",
      "PERL",
    ]

    return (
      <Box>
        <Box
          bg="white"
          boxShadow="0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)"
        >
          <Box px={{ md: "2rem" }}>
            <Box
              display="flex"
              flexWrap="wrap"
              justifyContent="space-between"
              alignItems="center"
              px="1rem"
            >
              <Box py={5}>
                <Heading as="h2" size="lg">
                  Open-source alternatives
                </Heading>
                <Text fontSize="md" fontWeight={400} color="#939fae" mt={1}>
                  Find open-source alternatives for your favorite apps
                </Text>
              </Box>
            </Box>
          </Box>
        </Box>

        <Box ml="auto" mr="auto" maxWidth="80rem" px={2} py={4}>
          <Box>
            <InputGroup size="lg" mx={1} mb={6}>
              <InputLeftElement
                children={<Icon name="search" color="gray.300" />}
              />
              <Input
                pr="4.5rem"
                placeholder="Search for anything"
                value={searchQuery}
                onChange={(e) => {
                  this.searchData(e.target.value)
                }}
                boxShadow="sm"
              />
            </InputGroup>
            <Box
              display="flex"
              alignItems="flex-start"
              flexDirection={{ base: "column", md: "row" }}
            >
              <Box
                p={3}
                maxWidth={{ base: "100%", md: "18rem" }}
                // bg="#122a4f"
                bg="white"
                boxShadow="md"
                borderRadius={4}
                mx={1}
                mb={6}
              >
                <Box>
                  <Box display="flex" flexDirection="column">
                    <Box mb={5}>
                      <Box color="gray.600" mx={2} mb={1} fontWeight={500}>
                        Categories
                      </Box>
                      <Box display="flex" flexWrap="wrap">
                        <PseudoBox
                          px={3}
                          py={1}
                          m={1}
                          borderRadius={4}
                          color={"white"}
                          fontWeight={600}
                          fontSize="sm"
                          letterSpacing="wide"
                          bg={category === "" ? "#122a4f" : "#2b4a7b"}
                          textTransform="uppercase"
                          _hover={category !== "" && { bg: "#1a3765" }}
                          onClick={() => this.categoryFilter("")}
                          cursor="pointer"
                        >
                          All
                        </PseudoBox>
                        {categories.map((c) => (
                          <PseudoBox
                            px={3}
                            py={1}
                            m={1}
                            borderRadius={4}
                            color={"white"}
                            fontWeight={600}
                            letterSpacing="wide"
                            fontSize="sm"
                            bg={category === c ? "#122a4f" : "#2b4a7b"}
                            textTransform="uppercase"
                            _hover={category !== c && { bg: "#1a3765" }}
                            onClick={() => this.categoryFilter(c)}
                            cursor="pointer"
                          >
                            {c}
                          </PseudoBox>
                        ))}
                      </Box>
                    </Box>
                    <Box mb={5}>
                      <Box color="gray.600" mx={2} mb={1} fontWeight={500}>
                        License
                      </Box>
                      <Box display="flex" flexWrap="wrap">
                        <PseudoBox
                          px={3}
                          py={1}
                          m={1}
                          borderRadius={4}
                          color={"white"}
                          fontWeight={600}
                          letterSpacing="wide"
                          fontSize="sm"
                          bg={license === "" ? "#122a4f" : "#00bf70"}
                          textTransform="uppercase"
                          _hover={license !== "" && { bg: "#029c5d" }}
                          onClick={() => this.licenseFilter("")}
                          cursor="pointer"
                        >
                          All
                        </PseudoBox>
                        {licenses.map((c) => (
                          <PseudoBox
                            px={3}
                            py={1}
                            m={1}
                            borderRadius={4}
                            color={"white"}
                            fontWeight={600}
                            fontSize="sm"
                            letterSpacing="wide"
                            bg={license === c ? "#122a4f" : "#00bf70"}
                            textTransform="uppercase"
                            _hover={license !== c && { bg: "#029c5d" }}
                            onClick={() => this.licenseFilter(c)}
                            cursor="pointer"
                          >
                            {c}
                          </PseudoBox>
                        ))}
                      </Box>
                    </Box>
                    <Box>
                      <Box color="gray.600" mx={2} mb={1} fontWeight={500}>
                        Language
                      </Box>
                      <Box display="flex" flexWrap="wrap">
                        <PseudoBox
                          px={3}
                          py={1}
                          m={1}
                          borderRadius={4}
                          color={"white"}
                          fontSize="sm"
                          fontWeight={600}
                          letterSpacing="wide"
                          bg={language === "" ? "#122a4f" : "orange.500"}
                          textTransform="uppercase"
                          _hover={language !== "" && { bg: "#af5417" }}
                          onClick={() => this.languageFilter("")}
                          cursor="pointer"
                        >
                          All
                        </PseudoBox>
                        {languages.map((c) => (
                          <PseudoBox
                            px={3}
                            py={1}
                            m={1}
                            borderRadius={4}
                            color={"white"}
                            fontWeight={600}
                            letterSpacing="wide"
                            fontSize="sm"
                            bg={language === c ? "#122a4f" : "orange.500"}
                            textTransform="uppercase"
                            _hover={language !== c && { bg: "#af5417" }}
                            onClick={() => this.languageFilter(c)}
                            cursor="pointer"
                          >
                            {c}
                          </PseudoBox>
                        ))}
                      </Box>
                    </Box>
                  </Box>
                </Box>
              </Box>
              <Box display="flex" flexWrap="wrap" width="100%">
                {compLoad.map((comp) => {
                  const match = queryResults.filter(
                    (alt) => alt.mainID === comp.id
                  )
                  if (match.length > 0) {
                    return (
                      <CompGroup
                        comp={comp}
                        commercial={comp.commercial}
                        alts={match}
                      />
                    )
                  }
                })}
              </Box>
            </Box>
          </Box>
        </Box>
      </Box>
    )
  }