@fortawesome/free-solid-svg-icons#faEdit TypeScript Examples

The following examples show how to use @fortawesome/free-solid-svg-icons#faEdit. 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: fontawesome-config.ts    From covidnet_ui with GNU Affero General Public License v3.0 6 votes vote down vote up
// Description: add icons to be used in the app as needed
// Some are solid and some are from regular svg (hollow icons)
library.add(
  faSearch,
  faSearchPlus,
  faHome,
  faSpinner,
  faExclamationTriangle,
  faTrash,
  faTrashAlt,
  faEdit,
  faUser,
  faUserEdit,
  faUserPlus,
  faUserTimes,
  faUserMinus,
  faKey,
  faCheck,
  faCheckCircle,
  faCalendarDay,
  faClock,
  faCalendarAlt,
  farUser,
  faFileAlt
);
Example #2
Source File: TableContent.tsx    From datajoint-labbook with MIT License 6 votes vote down vote up
/**
   * Handle button rednering with disable feature for Insert Update or Delete based on the table type and return the buttons accordingly
   */
  getTableActionButtons() {
    let disableInsert: boolean = false;
    let disableUpdate: boolean = false;
    let disableDelete: boolean = false;

    if (this.props.selectedTableType === TableType.COMPUTED || this.props.selectedTableType === TableType.IMPORTED) {
      disableInsert = true;
      disableUpdate = true;
    }
    else if (this.props.selectedTableType === TableType.PART) {
      disableInsert = true;
      disableUpdate = true;
      disableDelete = true;
    }
    else if (this.checkIfTableHasNonNullableBlobs()) {
      disableUpdate = true;
    }

    return(
      <div className="content-controllers">
        <button onClick={() => this.setCurrentTableActionMenu(TableActionType.FILTER)} className={this.state.currentSelectedTableActionMenu === TableActionType.FILTER && !this.state.hideTableActionMenu ? 'selectedButton' : ''}><FontAwesomeIcon className="menuIcon filter" icon={faFilter} /><span>Filter</span></button>
        <button onClick={() => this.setCurrentTableActionMenu(TableActionType.INSERT)} className={this.state.currentSelectedTableActionMenu === TableActionType.INSERT && !this.state.hideTableActionMenu ? 'selectedButton' : ''} disabled={disableInsert}><FontAwesomeIcon className="menuIcon insert" icon={faPlusCircle} /><span>Insert</span></button>
        <button onClick={() => this.setCurrentTableActionMenu(TableActionType.UPDATE)} className={this.state.currentSelectedTableActionMenu === TableActionType.UPDATE && !this.state.hideTableActionMenu ? 'selectedButton' : ''} disabled={disableUpdate}><FontAwesomeIcon className="menuIcon update" icon={faEdit} /><span>Update</span></button>
        <button onClick={() => this.setCurrentTableActionMenu(TableActionType.DELETE)} className={this.state.currentSelectedTableActionMenu === TableActionType.DELETE && !this.state.hideTableActionMenu ? 'selectedButton' : ''} disabled={disableDelete}><FontAwesomeIcon className="menuIcon delete" icon={faTrashAlt} /><span>Delete</span></button>
      </div>
    )
  }
Example #3
Source File: TabOverview.tsx    From genshin-optimizer with MIT License 6 votes vote down vote up
function StatDisplayCard({ title, content, editContent }) {
  const [edit, setedit] = useState(false)
  return <CardLight>
    <CardContent sx={{ py: 1 }}>
      <Box display="flex" justifyContent="space-between">
        <Typography variant="subtitle1">{title}</Typography>
        <Button size="small" color={edit ? "error" : "info"} onClick={() => setedit(!edit)} >
          <span><FontAwesomeIcon icon={edit ? faSave : faEdit} /> {edit ? EXIT : EDIT}</span>
        </Button>
      </Box>
    </CardContent>
    <Divider />
    <CardContent>
      {edit ? editContent : content}
    </CardContent>
  </CardLight>
}
Example #4
Source File: shared.module.ts    From enterprise-ng-2020-workshop with MIT License 6 votes vote down vote up
constructor(faIconLibrary: FaIconLibrary) {
    faIconLibrary.addIcons(
      faGithub,
      faMediumM,
      faPlus,
      faEdit,
      faTrash,
      faTimes,
      faCaretUp,
      faCaretDown,
      faExclamationTriangle,
      faFilter,
      faTasks,
      faCheck,
      faSquare,
      faLanguage,
      faPaintBrush,
      faLightbulb,
      faWindowMaximize,
      faStream,
      faBook
    );
  }
Example #5
Source File: Menu.tsx    From MagicUI with Apache License 2.0 6 votes vote down vote up
menus = [
  {
    icon: <FontAwesomeIcon icon={faMagic}/>,
    path: Routers.MAIN
  },
  {
    icon: <FontAwesomeIcon icon={faEdit}/>,
    path: Routers.WEBGL_EDITOR
  },
  {
    icon: <FontAwesomeIcon icon={faCode}/>,
    path: Routers.DSL_CODE_EDITOR
  },
  {
    icon: <FontAwesomeIcon icon={faImage}/>,
    path: ""
  }
]
Example #6
Source File: index.tsx    From gatsby-markdown-typescript-personal-website with MIT License 5 votes vote down vote up
/* add any additional icon to the library */
library.add(fab, faLaptopCode, faDrawPolygon, faEdit, faEdit, faBullhorn, faMapMarkerAlt, faPhone, faPaperPlane);
Example #7
Source File: employee-list.component.ts    From employee-crud-api with MIT License 5 votes vote down vote up
icons = {
    faTrash,
    faEdit
  }
Example #8
Source File: constants.ts    From MagicUI with Apache License 2.0 5 votes vote down vote up
ComponentFoldConfig = [
  {
    type: TYPES.SHAPE,
    children: [
      {
        name: COMPONENT_TYPES.SHAPE.RECT,
        icon: faSquare
      },
      {
        name: COMPONENT_TYPES.SHAPE.CIRCLE,
        icon: faCircle
      }
    ]
  },
  {
    type: TYPES.WIDGET,
    children: [
      {
        name: COMPONENT_TYPES.WIDGET.PC_WIDGET,
        icon: faWindowMaximize
      },
      {
        name: COMPONENT_TYPES.WIDGET.MOBILE_WIDGET,
        icon: faMobile
      }
    ]
  },
  {
    type: '',
    children: []
  },
  {
    type: TYPES.BUTTON,
    children: [
      {
        name: COMPONENT_TYPES.BUTTON.CUSTOM_BUTTON,
        icon: faCube
      }
    ]
  },
  {
    type: TYPES.INPUT,
    children: [
      {
        name: COMPONENT_TYPES.INPUT.CUSTOM_INPUT,
        icon: faEdit
      }
    ]
  },
  {
    type: TYPES.TEXT,
    children: [
      {
        name: COMPONENT_TYPES.TEXT.LABEL,
        icon: faPen
      },
      {
        name: COMPONENT_TYPES.TEXT.CUSTOM_TEXT,
        icon: faTag
      }
    ]
  },
  {
    type: TYPES.IMAGE,
    children: [
      {
        name: COMPONENT_TYPES.IMAGE.CUSTOM_IMAGE,
        icon: faImage
      }
    ]
  }
]
Example #9
Source File: index.tsx    From MagicUI with Apache License 2.0 5 votes vote down vote up
edit = <FontAwesomeIcon icon={faEdit}/>
Example #10
Source File: ClientSettings.tsx    From TutorBase with MIT License 4 votes vote down vote up
ClientSettings = () => {
    let clientData = useSelector(selectClientData);
    let dispatch = useDispatch();

    let [nameModalOpen, setNameModalOpen] = useState<boolean>(false);
    let [imgModalOpen, setImgModalOpen] = useState<boolean>(false);
    
    let [tempName, setTempName] = useState<Name>({
        first_name: "", 
        last_name: ""
    });
    let [clientName, setClientName] = useState<Name>({
        first_name: "",
        last_name: ""
    }); 
    let [croppedImg, setCroppedImg] = useState<string>("");
    let [clientImg, setClientImg] = useState<string>("");

    const saveNameChange = async () => {
        let name: Name = {first_name: tempName.first_name, last_name: tempName.last_name};
        await api.SetClientName(name, clientData.clientId);
        setClientName(name);
        dispatch(clientDataActions.setFirstName(tempName.first_name));
        dispatch(clientDataActions.setLastName(tempName.last_name));
        setNameModalOpen(false);
    }

    const handleImageSave = async (img: string) => {
        await api.SetClientProfileImage(img, clientData.clientId);
        setClientImg(img);
        dispatch(clientDataActions.setProfileImage(img));
    }

    const saveImgChange = async () => {
        if(croppedImg.toString() !== "") {
            CompressAndSaveImg(croppedImg, clientData.first_name + clientData.last_name + "-photo", handleImageSave);
        } else {
            handleImageSave(croppedImg);
        }

        setImgModalOpen(false);
    }

    const cancelNameChange = () => {
        setNameModalOpen(false); 
        setTempName(clientName);
    }

    const cancelImgChange = () => {
        setCroppedImg("");
        setImgModalOpen(false);
    }

    useEffect(() => {
        const getUser = async () => {
            return (await api.GetUserById(clientData.clientId)).data;
        }
        getUser().then(value => {
            setTempName({first_name: value[0].first_name, last_name: value[0].last_name});
            setClientName({first_name: value[0].first_name, last_name: value[0].last_name});
            setClientImg(value[0].profile_img);
            dispatch(clientDataActions.setFirstName(value[0].first_name));
            dispatch(clientDataActions.setLastName(value[0].last_name));
            dispatch(clientDataActions.setProfileImage(value[0].profile_img));
        });
        
    }, [clientData.clientId, dispatch]);

    return (
        <Container className="settings" fluid>
            <Row className="title" style={{ marginTop: '25px'}}>
            <div className="profile-text">Settings</div>
            </Row>

            <hr></hr>

             <Row>
                <ListGroup>

                    <ListGroupItem className="img-item">
                        <img src={clientImg === ""  ? defaultUser : clientImg} width="200px"/>
                        <a href="#" className="modal-link" onClick={() => setImgModalOpen(true)}>
                            <span className="heading-item"><FontAwesomeIcon icon={faEdit} className="font-adj"/></span>
                        </a>
                        <Modal isOpen={imgModalOpen} fade={false} toggle={() => {setImgModalOpen(!imgModalOpen)}} className="img-modal">
                            <ModalHeader toggle={() => {cancelImgChange()}}>Edit Profile Photo</ModalHeader>
                            <ModalBody>
                                Change your profile photo here.
                                <hr/>
                                <Avatar
                                    width={250}
                                    height={250}
                                    cropColor="#E66064"
                                    closeIconColor="#E66064"
                                    onCrop={(img) => setCroppedImg(img)}
                                    onClose={() => {setCroppedImg("")}}
                                    onBeforeFileLoad={() => {}}
                                    src={clientImg === "" ? defaultUser : clientImg}
                                />
                            </ModalBody>
                            <ModalFooter>
                                <Button className="btn-red" onClick={() => {saveImgChange()}}>Save</Button>
                                <Button color="secondary" onClick={() => {cancelImgChange()}}>Cancel</Button>
                            </ModalFooter>
                        </Modal>
                    </ListGroupItem>

                    <ListGroupItem className="name-item">
                        <span className="heading-item">{clientName.first_name} {clientName.last_name}</span>
                        <a href="#" className="modal-link" onClick={() => {setNameModalOpen(true)}}>
                            <span className="heading-item"><FontAwesomeIcon icon={faEdit} className="font-adj"/></span>
                        </a>
                        <Modal isOpen={nameModalOpen} fade={false} toggle={() => {setNameModalOpen(!nameModalOpen)}} className="name-modal">
                            <ModalHeader toggle={() => {cancelNameChange()}}>Edit Name</ModalHeader>
                            <ModalBody>
                                Change your name here.
                                <hr/>
                                <InputGroup>
                                    First Name:<Input id="first-name" value={tempName.first_name} onChange={(value) => setTempName({first_name: value.target.value, last_name: tempName.last_name})} />
                                </InputGroup>
                                <InputGroup>
                                    Last Name:<Input id="last-name" value={tempName.last_name} onChange={(value) => setTempName({first_name: tempName.first_name, last_name: value.target.value})} />
                                </InputGroup>
                            </ModalBody>
                            <ModalFooter>
                                <Button className="btn-red" onClick={() => {saveNameChange()}}>Save</Button>
                                <Button color="secondary" onClick={() => {cancelNameChange()}}>Cancel</Button>
                            </ModalFooter>
                        </Modal>
                    </ListGroupItem>

                 </ListGroup>
             </Row>
        </Container>
    );
}
Example #11
Source File: ResolverSkylink.tsx    From argo-react with MIT License 4 votes vote down vote up
ResolverSkylink = () => {
  const { projectLoading, selectedProject, orgLoading } =
    useContext<IStateModel>(StateContext);

  const [showCreatePopup, setShowCreatePopup] = useState<boolean>(false);
  const [showUpdatePopup, setShowUpdatePopup] = useState<boolean>(false);
  const [showRemovePopup, setShowRemovePopup] = useState<boolean>(false);
  const [isCopied, setIsCopied] = useState<boolean>(false);
  const [resolverSkylinkLoading, setResolverSkylinkLoading] =
    useState<boolean>(false);
  const [resolverSkylinks, setResolverSkylinks] = useState<IResolverSkylink[]>([]);
  const [selectedResolver, setSelectedResolver] = useState<IResolverSkylink>();
  const componentIsMounted = useRef<boolean>(true);

  useEffect(() => {
    if (selectedProject && !projectLoading) {
      if (componentIsMounted.current) {
        const resolverSkylinks: IResolverSkylink[] =
          selectedProject.resolverSkylinks;
        setResolverSkylinks(resolverSkylinks);
        setResolverSkylinkLoading(false);
      }
    } else {
      if (projectLoading) {
        setResolverSkylinkLoading(true);
      } else {
        setResolverSkylinkLoading(false);
      }
    }
  }, [selectedProject, projectLoading]);

  return (
    <div className="ResolverSkylink">
      <ProjectTopCard />
      <div className="skylinks-container">
        <div className="skylinks-details">
          <div className="skylinks-header">
            <span>Resolver Skylinks</span>
            <button
              type="button"
              className="primary-button"
              disabled={projectLoading || orgLoading}
              onClick={(e) => setShowCreatePopup(true)}
            >
              Generate Resolver Skylinks
            </button>
            <Popup
              trigger={<></>}
              position="center center"
              open={showCreatePopup}
              className="popup-container"
              modal
            >
              <GenerateResolverSkylink
                type="create"
                close={() => setShowCreatePopup(false)}
              />
            </Popup>
            <Popup
              trigger={<></>}
              position="center center"
              open={showUpdatePopup}
              className="popup-container"
              modal
            >
              <GenerateResolverSkylink
                type="update"
                resolver={selectedResolver}
                close={() => setShowUpdatePopup(false)}
              />
            </Popup>
            <Popup
              trigger={<></>}
              position="center center"
              open={showRemovePopup}
              className="popup-container"
              modal
            >
              <GenerateResolverSkylink
                type="remove"
                resolver={selectedResolver}
                close={() => setShowRemovePopup(false)}
              />
            </Popup>
          </div>
          <div className="skylinks-body">
            <div className="table">
              <div className="thead">
                <div className="tr">
                  <div className="th">Name</div>
                  <div className="th">Resolver Skylink</div>
                  <div className="th">Target Skylink</div>
                  <div className="th">Last Updated</div>
                  <div className="th"></div>
                </div>
              </div>
              {!resolverSkylinkLoading ? (
                <div className="tbody">
                  {resolverSkylinks.length > 0 ? (
                    resolverSkylinks.map(
                      (resolverSkylink: IResolverSkylink, index: number) => (
                        <div className="tr" key={index}>
                          <div className="tr-first">
                            <div className="td">
                              <div className="skylinks-td-container">
                                <div className="skylinks-title">
                                  {resolverSkylink.name}
                                </div>
                              </div>
                            </div>
                            <div className="td">
                              <div className="skylinks-td-container">
                                <a
                                  className="skylinks-links"
                                  href={`https://siasky.net/${resolverSkylink.resolverSkylink}`}
                                  target="_blank"
                                  rel="noopener noreferrer"
                                >
                                  sia://{resolverSkylink.resolverSkylink}
                                </a>
                              </div>
                            </div>
                            <div className="td">
                              <div className="skylinks-td-container">
                                <a
                                  className="skylinks-links"
                                  href={`https://siasky.net/${resolverSkylink.resolverSkylink}`}
                                  target="_blank"
                                  rel="noopener noreferrer"
                                >
                                  sia://{resolverSkylink.targetSkylink}
                                </a>
                              </div>
                            </div>
                            <div className="td">
                              <div className="skylinks-td-container">
                                <div className="skylinks-text">
                                  {moment(resolverSkylink.updatedAt).format(
                                    "DD-MM-YYYY hh:mm A",
                                  )}
                                </div>
                              </div>
                            </div>
                            <div className="td">
                              <div className="skylinks-td-container">
                                <div
                                  className={`trash-icon-container ${
                                    projectLoading || orgLoading
                                      ? "icon-disabled"
                                      : ""
                                  }`}
                                  onClick={(e) => {
                                    setSelectedResolver(resolverSkylink);
                                    setShowUpdatePopup(true);
                                  }}
                                >
                                  <FontAwesomeIcon
                                    icon={faEdit}
                                    className="trash-icon"
                                  ></FontAwesomeIcon>
                                </div>

                                <div
                                  className={`trash-icon-container ${
                                    projectLoading || orgLoading
                                      ? "icon-disabled"
                                      : ""
                                  }`}
                                  onClick={(e) => {
                                    setSelectedResolver(resolverSkylink);
                                    setShowRemovePopup(true);
                                  }}
                                >
                                  <FontAwesomeIcon
                                    icon={faTrash}
                                    className="trash-icon"
                                  ></FontAwesomeIcon>
                                </div>
                              </div>
                            </div>
                          </div>
                          <div className="tr-second">
                            <div
                              className="badge-container"
                              onClick={() =>
                                window.open(
                                  `https://homescreen.hns.siasky.net/#/skylink/${resolverSkylink.resolverSkylink}`,
                                  "_blank",
                                )
                              }
                            >
                              <img
                                src="https://img.shields.io/badge/Skynet-Add%20To%20Homescreen-00c65e?style=for-the-badge&labelColor=0d0d0d&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAbCAYAAAAdx42aAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAeGVYSWZNTQAqAAAACAAFARIAAwAAAAEAAQAAARoABQAAAAEAAABKARsABQAAAAEAAABSASgAAwAAAAEAAgAAh2kABAAAAAEAAABaAAAAAAAAAEgAAAABAAAASAAAAAEAAqACAAQAAAABAAAAIKADAAQAAAABAAAAGwAAAADGhQ7VAAAACXBIWXMAAAsTAAALEwEAmpwYAAACZmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNi4wLjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+NTM8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+NjQ8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+Cnr0gvYAAAe5SURBVEgNlVYJbFzVFT3vL/Nt4yXOyiLahF24EMBrszqhNA1EpZWwK0qxZ2xk0apEpaJFNGkzRCC1VYlUJyoisj22EyrFlqBqaGgqiE0QxPaMSyi1E9JS0pRCwGRx7Njz5289702+lWArSZ8zkz/vv3vvufeee+8T+H9WT7WBVb2uEknVXw9XrENEWw6Bm5Hxr4bnz4IuxmHqHwHBu3D81xGYr6Cq5VMlE9ToEN3e+SbF+T8u+hwKD8SuhQjigKhFrp5Pw0CGOv0gAP9xX0CjWksHDA2wvc+51YqM+DWWtJ7E+U7I0xc1Gr4M4hpE3Ed//YPQtW3IMWZjNB1Q2oFpRJBDYz6Nu/zQJqMASD8nM9zgc5ElMOkeg+83oKLjdXQxErXZSFwaQHj4YOPj9GwLJh0a8tPINXMUviA4oEJtiEMQ+klGJwLH/RI0vZJpWAvLmIMztouIbihgtvcQlnT+PoxEFoD0RUDG78IVhivZ0Mhwt1AR403fCiIm0m4/Q76BHu3j3nRZqSn1vavgG+uZgifID4NR8glEYyRWUm6/jIRAqslE2Xa6xRV6K5/DsA/W3U6yDcILDBp0kR8x+LwVd7Wtl8doWmB7k4HiUz5qSgJ0DwnMKxGoHuKbc4RLNi6F8F8iiPmKH0I7gv9+Xob7/zgmsD82DznBQljeMBbvOKsMK82bqEAESEX3wtC/jnHHRlHEgu1uRVl71ngYIXV+hq8gEOiuNZnvDAaidzAFPSRlIQotjcR9ik78MpuCA9GFCLz76OFRLN35pylVAw21mGPtwvGzDolm0ts3UZZYwfcC8bj8yJRceg3VRFBCEIP1teTGLoIgWcW/6PTtmgrhV9uP4vSsFu7eTI8T6G8oU1p97Q2cSD8Pk9S2DJBcP1H7PXH9so1LAWlcRqu0o4uVsluVqCauQ8ZcwfIihDjL7N6tNpZ2biGIVkTwG7z7SAtOjzqoSPwAgbYEZzMbsff6pAKwKu4q4JInX1xyT/Lii2tkXpaoQmxjFYHNiqXrr7zwYE+cnY7KJaD7jz1PDnwHrtfMnP9C6ZOE9dKLyDwHlTs+nLLxdk0uNFZG1Ytnpvakjk0kJEhM2UPClWrKg595B3nGTeTBngsByEPZSpACAQZja5jubnLDIYN/isqOVqWnr24V336FzD6Mqp2vqbPJhuvgubfxnAthfIAl7YfV2fBLpqDgJqEq7q+xbvaRBzDhvjcdQFZAYKB+tepa8vdAbDfm563DyMQ7BLQB5W2vYs9DhZhtNDHY5eyOvTjhdmINq+jtugpKrCPARcg1jpBw+5Be1K8im9UNHKhrRlHOYzjr/Gc6gLDnpxq6oAUlmPDWYlnnMSSjD1O+g4ICo5k/09OnUdXeh75HFsDyfw5NW8Gg7YPjbEEZz8vyzvPr2Kq/hUAUM4ocTu4eHJ14CVfnbsZs6wmMOZ9OJ1HvSBZUxv2Yxm6Fpb2HwWgU5e07kPZvYTfsxdycb7CmDzAyu9iXC3Fn2w8Zzm8yOtfAMI8gFduPPHEnyjqew+LW5UhnHoXGP1NvxQ0FJ6HjUYxleDzInQ4A1dlAaeIjjPNQxs9HXiSBVP19WN55BK98eA9GJjdJirAx1VLZQRr8HTR/DItbamAHlaqBFUX2EuBxDrANnB+HCeRBfPJJEUn9JIF8QA5wWupD0wGMsIXKZRp/Z8uVdhwOGzkB7lb760ikisRmpmA1vTjEPOexT3wfuv4+gTwN3RhGadtKgvwafT6OK/OfQYH1GYF048r5y8grVlXiDtiZSkxMPDADB0gr2Rteq5uDIobfC66iR3LE/hunxhfjnu7RqflxuKEAY8E2vqtTtS3vABmflxH8CuWJbQpwdoRvxtzcG9jOOaKdvzH2L+L0+AtS13QAUiocSslYG1twjKTLzoG0sxHlHc8qAKUcPlPDRhG0me11lmqzBREg7R1C4MfpcZcCkow9TiI+ieKcBeoCM+mO8vzamQGEkzApS0rrYwpkWjSOUpvEqUYp2d/F/j5c4qpmI4H0P7yIfZ6AjWqmxuFtyOQzb0TuW5Ql8PZe9NTkoyB/E9PXhOLcQpxxvj0zAAk5LMdktAV5ZiNO2TYrwmJyPuPbNahoP6giVcNfg8Xa1EgfjP6MZfesVEHjLgksx7jk0h/geRsZkSH2mBL4uAZVHX+5CIBzXHjzu8W4Iqef6m7ktYogdItvTpOUj5GMO5Uh+RXOBdl2+6JVvKw2M9Tl9JadUWi4ghPNkawWz5GE2aEmB/6UgpkeQi6kordRUIaygDm2YQgrG16vl95uh+30Yp99AnFOvea1Fta/arONrybIXRw4c7MXVsjbtIlii/xwS3BXYljOnIsDkKDCATUQLWded9P4AvaHDA0LemUyGlLhKY7rf9AYicXce/5CVs+1NCzUJwg8Es5gY5NV8FuUJn7ElKhquzSA80G81fhltt0EvV/F/Eqms66YYCEiasbzuqfyLfuG4/OLd0BpOJ9VYXsTVPUUw98sVXJJ20R4uSskpTwvL6mB/2M2oFvP3f1p0KM6Bl36pTHn8gIjAaUdXvOCl8mHZ7Bs5/tZrsSl/7KyFAr5/+UtRbRzwnuY63kLZHe8lyAq6PFCNqM5LFabrfZjah7mXg8MYzdKW/+pDMxwh/wf4xZoOPPcKX0AAAAASUVORK5CYII="
                                alt="homescreen badge"
                              />
                            </div>
                            <div
                              className="copy-badge-container"
                              onClick={() => {
                                setIsCopied(true);
                                setTimeout(() => {
                                  setIsCopied(false);
                                }, 2000);
                                navigator.clipboard.writeText(
                                  `[![Add to Homescreen](https://img.shields.io/badge/Skynet-Add%20To%20Homescreen-00c65e?style=for-the-badge&labelColor=0d0d0d&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAbCAYAAAAdx42aAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAeGVYSWZNTQAqAAAACAAFARIAAwAAAAEAAQAAARoABQAAAAEAAABKARsABQAAAAEAAABSASgAAwAAAAEAAgAAh2kABAAAAAEAAABaAAAAAAAAAEgAAAABAAAASAAAAAEAAqACAAQAAAABAAAAIKADAAQAAAABAAAAGwAAAADGhQ7VAAAACXBIWXMAAAsTAAALEwEAmpwYAAACZmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNi4wLjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+NTM8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+NjQ8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+Cnr0gvYAAAe5SURBVEgNlVYJbFzVFT3vL/Nt4yXOyiLahF24EMBrszqhNA1EpZWwK0qxZ2xk0apEpaJFNGkzRCC1VYlUJyoisj22EyrFlqBqaGgqiE0QxPaMSyi1E9JS0pRCwGRx7Njz5289702+lWArSZ8zkz/vv3vvufeee+8T+H9WT7WBVb2uEknVXw9XrENEWw6Bm5Hxr4bnz4IuxmHqHwHBu3D81xGYr6Cq5VMlE9ToEN3e+SbF+T8u+hwKD8SuhQjigKhFrp5Pw0CGOv0gAP9xX0CjWksHDA2wvc+51YqM+DWWtJ7E+U7I0xc1Gr4M4hpE3Ed//YPQtW3IMWZjNB1Q2oFpRJBDYz6Nu/zQJqMASD8nM9zgc5ElMOkeg+83oKLjdXQxErXZSFwaQHj4YOPj9GwLJh0a8tPINXMUviA4oEJtiEMQ+klGJwLH/RI0vZJpWAvLmIMztouIbihgtvcQlnT+PoxEFoD0RUDG78IVhivZ0Mhwt1AR403fCiIm0m4/Q76BHu3j3nRZqSn1vavgG+uZgifID4NR8glEYyRWUm6/jIRAqslE2Xa6xRV6K5/DsA/W3U6yDcILDBp0kR8x+LwVd7Wtl8doWmB7k4HiUz5qSgJ0DwnMKxGoHuKbc4RLNi6F8F8iiPmKH0I7gv9+Xob7/zgmsD82DznBQljeMBbvOKsMK82bqEAESEX3wtC/jnHHRlHEgu1uRVl71ngYIXV+hq8gEOiuNZnvDAaidzAFPSRlIQotjcR9ik78MpuCA9GFCLz76OFRLN35pylVAw21mGPtwvGzDolm0ts3UZZYwfcC8bj8yJRceg3VRFBCEIP1teTGLoIgWcW/6PTtmgrhV9uP4vSsFu7eTI8T6G8oU1p97Q2cSD8Pk9S2DJBcP1H7PXH9so1LAWlcRqu0o4uVsluVqCauQ8ZcwfIihDjL7N6tNpZ2biGIVkTwG7z7SAtOjzqoSPwAgbYEZzMbsff6pAKwKu4q4JInX1xyT/Lii2tkXpaoQmxjFYHNiqXrr7zwYE+cnY7KJaD7jz1PDnwHrtfMnP9C6ZOE9dKLyDwHlTs+nLLxdk0uNFZG1Ytnpvakjk0kJEhM2UPClWrKg595B3nGTeTBngsByEPZSpACAQZja5jubnLDIYN/isqOVqWnr24V336FzD6Mqp2vqbPJhuvgubfxnAthfIAl7YfV2fBLpqDgJqEq7q+xbvaRBzDhvjcdQFZAYKB+tepa8vdAbDfm563DyMQ7BLQB5W2vYs9DhZhtNDHY5eyOvTjhdmINq+jtugpKrCPARcg1jpBw+5Be1K8im9UNHKhrRlHOYzjr/Gc6gLDnpxq6oAUlmPDWYlnnMSSjD1O+g4ICo5k/09OnUdXeh75HFsDyfw5NW8Gg7YPjbEEZz8vyzvPr2Kq/hUAUM4ocTu4eHJ14CVfnbsZs6wmMOZ9OJ1HvSBZUxv2Yxm6Fpb2HwWgU5e07kPZvYTfsxdycb7CmDzAyu9iXC3Fn2w8Zzm8yOtfAMI8gFduPPHEnyjqew+LW5UhnHoXGP1NvxQ0FJ6HjUYxleDzInQ4A1dlAaeIjjPNQxs9HXiSBVP19WN55BK98eA9GJjdJirAx1VLZQRr8HTR/DItbamAHlaqBFUX2EuBxDrANnB+HCeRBfPJJEUn9JIF8QA5wWupD0wGMsIXKZRp/Z8uVdhwOGzkB7lb760ikisRmpmA1vTjEPOexT3wfuv4+gTwN3RhGadtKgvwafT6OK/OfQYH1GYF048r5y8grVlXiDtiZSkxMPDADB0gr2Rteq5uDIobfC66iR3LE/hunxhfjnu7RqflxuKEAY8E2vqtTtS3vABmflxH8CuWJbQpwdoRvxtzcG9jOOaKdvzH2L+L0+AtS13QAUiocSslYG1twjKTLzoG0sxHlHc8qAKUcPlPDRhG0me11lmqzBREg7R1C4MfpcZcCkow9TiI+ieKcBeoCM+mO8vzamQGEkzApS0rrYwpkWjSOUpvEqUYp2d/F/j5c4qpmI4H0P7yIfZ6AjWqmxuFtyOQzb0TuW5Ql8PZe9NTkoyB/E9PXhOLcQpxxvj0zAAk5LMdktAV5ZiNO2TYrwmJyPuPbNahoP6giVcNfg8Xa1EgfjP6MZfesVEHjLgksx7jk0h/geRsZkSH2mBL4uAZVHX+5CIBzXHjzu8W4Iqef6m7ktYogdItvTpOUj5GMO5Uh+RXOBdl2+6JVvKw2M9Tl9JadUWi4ghPNkawWz5GE2aEmB/6UgpkeQi6kordRUIaygDm2YQgrG16vl95uh+30Yp99AnFOvea1Fta/arONrybIXRw4c7MXVsjbtIlii/xwS3BXYljOnIsDkKDCATUQLWded9P4AvaHDA0LemUyGlLhKY7rf9AYicXce/5CVs+1NCzUJwg8Es5gY5NV8FuUJn7ElKhquzSA80G81fhltt0EvV/F/Eqms66YYCEiasbzuqfyLfuG4/OLd0BpOJ9VYXsTVPUUw98sVXJJ20R4uSskpTwvL6mB/2M2oFvP3f1p0KM6Bl36pTHn8gIjAaUdXvOCl8mHZ7Bs5/tZrsSl/7KyFAr5/+UtRbRzwnuY63kLZHe8lyAq6PFCNqM5LFabrfZjah7mXg8MYzdKW/+pDMxwh/wf4xZoOPPcKX0AAAAASUVORK5CYII=)](https://homescreen.hns.siasky.net/#/skylink/${resolverSkylink.resolverSkylink})`,
                                );
                              }}
                            >
                              <div className="copy-badge-text">
                                {isCopied ? "Copied" : "Copy"} Homescreen Badge Code
                              </div>
                              <div className="clipboard-icon-container">
                                <FontAwesomeIcon
                                  icon={faClipboard}
                                  className="clipboard-icon"
                                ></FontAwesomeIcon>
                              </div>
                            </div>
                          </div>
                        </div>
                      ),
                    )
                  ) : (
                    <div className="tr" key={1}>
                      <div className="tr-first no-item">
                        No resolver skylinks to show
                      </div>
                    </div>
                  )}
                </div>
              ) : (
                <div className="tbody">
                  <div className="tr">
                    <div className="tr-first">
                      <div className="td">
                        <div className="skylinks-td-container">
                          <div className="skylinks-title">
                            <Skeleton width={100} duration={2} />
                          </div>
                        </div>
                      </div>
                      <div className="td">
                        <div className="skylinks-td-container">
                          <div className="skylinks-title">
                            <Skeleton width={100} duration={2} />
                          </div>
                        </div>
                      </div>
                      <div className="td">
                        <div className="skylinks-td-container">
                          <div className="skylinks-title">
                            <Skeleton width={100} duration={2} />
                          </div>
                        </div>
                      </div>
                      <div className="td">
                        <div className="skylinks-td-container">
                          <div className="skylinks-text">
                            <Skeleton width={80} duration={2} />
                          </div>
                        </div>
                      </div>
                      <div className="td">
                        <div className="skylinks-td-container">
                          <div className="skylinks-text">
                            <Skeleton width={80} duration={2} />
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                  <div className="tr">
                    <div className="tr-first">
                      <div className="td">
                        <div className="skylinks-td-container">
                          <div className="skylinks-title">
                            <Skeleton width={100} duration={2} />
                          </div>
                        </div>
                      </div>
                      <div className="td">
                        <div className="skylinks-td-container">
                          <div className="skylinks-title">
                            <Skeleton width={100} duration={2} />
                          </div>
                        </div>
                      </div>
                      <div className="td">
                        <div className="skylinks-td-container">
                          <div className="skylinks-title">
                            <Skeleton width={100} duration={2} />
                          </div>
                        </div>
                      </div>
                      <div className="td">
                        <div className="skylinks-td-container">
                          <div className="skylinks-text">
                            <Skeleton width={80} duration={2} />
                          </div>
                        </div>
                      </div>
                      <div className="td">
                        <div className="skylinks-td-container">
                          <div className="skylinks-text">
                            <Skeleton width={80} duration={2} />
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              )}
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}
Example #12
Source File: Shop.tsx    From apps with MIT License 4 votes vote down vote up
ShopTab = ({ region, shops, filters, onChange, itemCache, questCache }: IProps) => {
    let [forceEnablePlanner, setForceEnablePlanner] = useState<boolean | undefined>(undefined);
    let [itemFilters, setItemFilters] = useState(new Set<number>());

    const allItems = new Map(shops.map((shop) => [shop.cost.item.id, shop.cost.item]));

    let shopEnabled = forceEnablePlanner === undefined ? Manager.shopPlannerEnabled() : forceEnablePlanner;
    let counted = shops
        .filter((shop) => (shopEnabled ? filters.has(shop.id) : true))
        .map(
            (shop) =>
                [shop.cost.item, (shopEnabled ? filters.get(shop.id)! : shop.limitNum) * shop.cost.amount] as const
        );

    let items = new Map(counted.map((tuple) => [tuple[0].id, tuple[0]]));

    let amounts = new Map<number, number>();
    for (let [item, amount] of counted)
        if (amounts.has(item.id)) amounts.set(item.id, (amounts.get(item.id) ?? 0) + amount);
        else amounts.set(item.id, amount);

    // reset filter if nothing is chosen
    if (!amounts.size && itemFilters.size) setItemFilters(new Set());

    const excludeItemIds = (itemIds: number[]) => {
        return new Map(
            shops
                .filter((shop) => shop.payType !== Shop.PayType.FREE)
                .filter((shop) => shop.limitNum !== 0)
                .filter((shop) => !itemIds.includes(shop.targetIds[0]) || shop.purchaseType !== Shop.PurchaseType.ITEM)
                .map((shop) => [shop.id, shop.limitNum])
        );
    };

    return (
        <>
            <Alert variant="success" style={{ margin: "1em 0", display: "flex" }}>
                <div style={{ flexGrow: 1 }}>
                    {shopEnabled
                        ? amounts.size > 0
                            ? "Total amount for chosen items: "
                            : "No item was chosen. Choose at least one to get calculations."
                        : "Total currency amount needed to clear the shop: "}
                    {[...amounts]
                        .filter(([_, amount]) => amount > 0)
                        .map(([itemId, amount]) => (
                            <span style={{ whiteSpace: "nowrap", paddingRight: "1ch" }} key={itemId}>
                                <IconLink region={region} item={items.get(itemId)!} />
                                <b>×{amount.toLocaleString()}</b>
                            </span>
                        ))}
                </div>
                <div style={{ flexBasis: "auto", paddingLeft: "10px" }}>
                    <Button
                        variant={shopEnabled ? "dark" : "success"}
                        onClick={() => setForceEnablePlanner(!forceEnablePlanner)}
                    >
                        <FontAwesomeIcon icon={faEdit} title={shopEnabled ? "Disable planner" : "Enable planner"} />
                    </Button>
                </div>
            </Alert>
            {shopEnabled && (
                <>
                    <ButtonGroup>
                        <Button disabled variant="outline-dark">
                            Quick toggle
                        </Button>
                        <Button variant="outline-success" onClick={() => onChange?.(excludeItemIds([]))}>
                            All
                        </Button>
                        <Button variant="outline-success" onClick={() => onChange?.(new Map())}>
                            None
                        </Button>
                        <Dropdown as={ButtonGroup}>
                            <Dropdown.Toggle variant="outline-success">Exclude</Dropdown.Toggle>
                            <Dropdown.Menu>
                                <Dropdown.Item
                                    as={Button}
                                    onClick={() =>
                                        onChange?.(excludeItemIds([...gemIds, ...magicGemIds, ...secretGemIds]))
                                    }
                                >
                                    Gems
                                </Dropdown.Item>
                                <Dropdown.Item
                                    as={Button}
                                    onClick={() => onChange?.(excludeItemIds([...monumentIds, ...pieceIds]))}
                                >
                                    Monuments & Pieces
                                </Dropdown.Item>
                                <Dropdown.Item as={Button} onClick={() => onChange?.(excludeItemIds(monumentIds))}>
                                    Monuments
                                </Dropdown.Item>
                                <Dropdown.Item as={Button} onClick={() => onChange?.(excludeItemIds(pieceIds))}>
                                    Pieces
                                </Dropdown.Item>
                            </Dropdown.Menu>
                        </Dropdown>
                    </ButtonGroup>
                    <div>&nbsp;</div>
                </>
            )}
            <Table hover responsive className="shopTable">
                <thead>
                    <tr>
                        <th style={{ textAlign: "left" }}>Detail</th>
                        <th style={{ whiteSpace: "nowrap" }}>
                            Currency&nbsp;
                            <Dropdown as={ButtonGroup}>
                                <Dropdown.Toggle size="sm">
                                    <FontAwesomeIcon style={{ display: "inline" }} icon={faFilter} />
                                </Dropdown.Toggle>
                                <Dropdown.Menu>
                                    {/* Actually a checkbox is the best here */}
                                    <Dropdown.Item
                                        as={Button}
                                        onClick={() => {
                                            setItemFilters(new Set());
                                        }}
                                    >
                                        Reset
                                    </Dropdown.Item>
                                    {[...allItems].map(([itemId, item]) => (
                                        <Dropdown.Item
                                            key={item.id}
                                            as={Button}
                                            onClick={() => {
                                                setItemFilters(new Set([itemId]));
                                            }}
                                        >
                                            <ItemIcon region={region} item={item} height={40} />
                                            {item.name}
                                        </Dropdown.Item>
                                    ))}
                                </Dropdown.Menu>
                            </Dropdown>
                        </th>
                        <th>Cost</th>
                        <th>Item</th>
                        <th>Set</th>
                        <th>Limit</th>
                        {shopEnabled && <th>Target</th>}
                    </tr>
                </thead>
                <tbody>
                    {shops
                        .filter((shop) =>
                            itemFilters.size && amounts.size ? itemFilters.has(shop.cost.item.id) : true
                        )
                        .sort((a, b) => a.priority - b.priority)
                        .map((shop) => {
                            let limitNumIndicator = shopEnabled ? (
                                <Button
                                    variant="light"
                                    onClick={() => {
                                        filters.set(shop.id, shop.limitNum);
                                        onChange?.(filters);
                                    }}
                                >
                                    {shop.limitNum.toLocaleString()}
                                </Button>
                            ) : (
                                <>{shop.limitNum.toLocaleString()}</>
                            );

                            return (
                                <tr key={shop.id}>
                                    <td style={{ minWidth: "10em" }}>
                                        <b>{shop.name}</b>
                                        <div style={{ fontSize: "0.75rem" }} className="newline">
                                            {colorString(shop.detail)}
                                            <ScriptLink region={region} shop={shop} />
                                            <br />
                                            <div>
                                                {shop.releaseConditions.length ? (
                                                    <ul className="condition-list">
                                                        {shop.releaseConditions.map((cond, index) => (
                                                            <li key={index} style={{ fontSize: "0.75rem" }}>
                                                                {cond.closedMessage && `${cond.closedMessage} — `}
                                                                <CondTargetNumDescriptor
                                                                    region={region}
                                                                    cond={cond.condType}
                                                                    targets={cond.condValues}
                                                                    num={cond.condNum}
                                                                    quests={questCache}
                                                                    items={itemCache}
                                                                />
                                                            </li>
                                                        ))}
                                                    </ul>
                                                ) : (
                                                    ""
                                                )}
                                            </div>
                                        </div>
                                    </td>
                                    <td style={{ textAlign: "center" }}>
                                        {shop.payType !== Shop.PayType.FREE ? (
                                            <IconLink region={region} item={shop.cost.item} />
                                        ) : null}
                                    </td>
                                    <td style={{ textAlign: "center" }}>
                                        {shop.payType !== Shop.PayType.FREE ? shop.cost.amount.toLocaleString() : null}
                                    </td>
                                    <td>
                                        <ShopPurchaseDescriptor region={region} shop={shop} itemMap={itemCache} />
                                    </td>
                                    <td style={{ textAlign: "center" }}>{shop.setNum.toLocaleString()}</td>
                                    <td style={{ textAlign: "center" }}>
                                        {shop.limitNum === 0 ? <>Unlimited</> : limitNumIndicator}
                                    </td>
                                    {shopEnabled && (
                                        <>
                                            <td style={{ textAlign: "center", maxWidth: "5em" }}>
                                                <InputGroup size="sm">
                                                    <Form.Control
                                                        type="number"
                                                        value={filters.get(shop.id) ?? 0}
                                                        min={0}
                                                        max={shop.limitNum || undefined}
                                                        onChange={(event) => {
                                                            let value = +event.target.value;
                                                            if (value) filters.set(shop.id, value);
                                                            else filters.delete(shop.id);
                                                            onChange?.(filters);
                                                        }}
                                                    />
                                                </InputGroup>
                                            </td>
                                        </>
                                    )}
                                </tr>
                            );
                        })}
                </tbody>
            </Table>
        </>
    );
}
Example #13
Source File: ArtifactCard.tsx    From genshin-optimizer with MIT License 4 votes vote down vote up
export default function ArtifactCard({ artifactId, artifactObj, onClick, onDelete, mainStatAssumptionLevel = 0, effFilter = allSubstatFilter, probabilityFilter, disableEditSetSlot = false, editor = false, canExclude = false, canEquip = false, extraButtons }: Data): JSX.Element | null {
  const { t } = useTranslation(["artifact", "ui"]);
  const { database } = useContext(DatabaseContext)
  const databaseArtifact = useArtifact(artifactId)
  const sheet = usePromise(ArtifactSheet.get((artifactObj ?? databaseArtifact)?.setKey), [artifactObj, databaseArtifact])
  const equipOnChar = (charKey: CharacterKey | "") => database.setArtLocation(artifactId!, charKey)
  const editable = !artifactObj
  const [showEditor, setshowEditor] = useState(false)
  const onHideEditor = useCallback(() => setshowEditor(false), [setshowEditor])
  const onShowEditor = useCallback(() => editable && setshowEditor(true), [editable, setshowEditor])

  const wrapperFunc = useCallback(children => <CardActionArea onClick={() => artifactId && onClick?.(artifactId)} sx={{ flexGrow: 1, display: "flex", flexDirection: "column" }} >{children}</CardActionArea>, [onClick, artifactId],)
  const falseWrapperFunc = useCallback(children => <Box sx={{ flexGrow: 1, display: "flex", flexDirection: "column" }} >{children}</Box>, [])

  const art = artifactObj ?? databaseArtifact
  if (!art) return null

  const { id, lock, slotKey, rarity, level, mainStatKey, substats, exclude, location = "" } = art
  const mainStatLevel = Math.max(Math.min(mainStatAssumptionLevel, rarity * 4), level)
  const mainStatUnit = KeyMap.unit(mainStatKey)
  const levelVariant = "roll" + (Math.floor(Math.max(level, 0) / 4) + 1)
  const { currentEfficiency, maxEfficiency } = Artifact.getArtifactEfficiency(art, effFilter)
  const artifactValid = maxEfficiency !== 0
  const slotName = sheet?.getSlotName(slotKey) || "Unknown Piece Name"
  const slotDesc = sheet?.getSlotDesc(slotKey)
  const slotDescTooltip = slotDesc && <InfoTooltip title={<Box>
    <Typography variant='h6'>{slotName}</Typography>
    <Typography>{slotDesc}</Typography>
  </Box>} />
  const setEffects = sheet?.setEffects
  const setDescTooltip = sheet && setEffects && <InfoTooltip title={
    <span>
      {Object.keys(setEffects).map(setNumKey => <span key={setNumKey}>
        <Typography variant="h6"><SqBadge color="success">{t(`artifact:setEffectNum`, { setNum: setNumKey })}</SqBadge></Typography>
        <Typography>{sheet.setEffectDesc(setNumKey as any)}</Typography>
      </span>)}
    </span>
  } />
  return <Suspense fallback={<Skeleton variant="rectangular" sx={{ width: "100%", height: "100%", minHeight: 350 }} />}>
    {editor && <Suspense fallback={false}>
      <ArtifactEditor
        artifactIdToEdit={showEditor ? artifactId : ""}
        cancelEdit={onHideEditor}
        disableEditSetSlot={disableEditSetSlot}
      />
    </Suspense>}
    <CardLight sx={{ height: "100%", display: "flex", flexDirection: "column" }}>
      <ConditionalWrapper condition={!!onClick} wrapper={wrapperFunc} falseWrapper={falseWrapperFunc}>
        <Box className={`grad-${rarity}star`} sx={{ position: "relative", width: "100%" }}>
          {!onClick && <IconButton color="primary" disabled={!editable} onClick={() => database.updateArt({ lock: !lock }, id)} sx={{ position: "absolute", right: 0, bottom: 0, zIndex: 2 }}>
            {lock ? <Lock /> : <LockOpen />}
          </IconButton>}
          <Box sx={{ pt: 2, px: 2, position: "relative", zIndex: 1 }}>
            {/* header */}
            <Box component="div" sx={{ display: "flex", alignItems: "center", gap: 1, mb: 1 }}>
              <Chip size="small" label={<strong>{` +${level}`}</strong>} color={levelVariant as any} />
              <Typography component="span" noWrap sx={{ backgroundColor: "rgba(100,100,100,0.35)", borderRadius: "1em", px: 1 }}><strong>{slotName}</strong></Typography>
              <Box flexGrow={1} sx={{ textAlign: "right" }}>
                {slotDescTooltip}
              </Box>
            </Box>
            <Typography color="text.secondary" variant="body2">
              <SlotNameWithIcon slotKey={slotKey} />
            </Typography>
            <Typography variant="h6" color={`${KeyMap.getVariant(mainStatKey)}.main`}>
              <span>{StatIcon[mainStatKey]} {KeyMap.get(mainStatKey)}</span>
            </Typography>
            <Typography variant="h5">
              <strong>
                <ColorText color={mainStatLevel !== level ? "warning" : undefined}>{cacheValueString(Artifact.mainStatValue(mainStatKey, rarity, mainStatLevel) ?? 0, KeyMap.unit(mainStatKey))}{mainStatUnit}</ColorText>
              </strong>
            </Typography>
            <Stars stars={rarity} colored />
            {/* {process.env.NODE_ENV === "development" && <Typography color="common.black">{id || `""`} </Typography>} */}
          </Box>
          <Box sx={{ height: "100%", position: "absolute", right: 0, top: 0 }}>
            <Box
              component="img"
              src={sheet?.slotIcons[slotKey] ?? ""}
              width="auto"
              height="100%"
              sx={{ float: "right" }}
            />
          </Box>
        </Box>
        <CardContent sx={{ flexGrow: 1, display: "flex", flexDirection: "column", pt: 1, pb: 0, width: "100%" }}>
          {substats.map((stat: ICachedSubstat) => <SubstatDisplay key={stat.key} stat={stat} effFilter={effFilter} rarity={rarity} />)}
          <Box sx={{ display: "flex", my: 1 }}>
            <Typography color="text.secondary" component="span" variant="caption" sx={{ flexGrow: 1 }}>{t`artifact:editor.curSubEff`}</Typography>
            <PercentBadge value={currentEfficiency} max={900} valid={artifactValid} />
          </Box>
          {currentEfficiency !== maxEfficiency && <Box sx={{ display: "flex", mb: 1 }}>
            <Typography color="text.secondary" component="span" variant="caption" sx={{ flexGrow: 1 }}>{t`artifact:editor.maxSubEff`}</Typography>
            <PercentBadge value={maxEfficiency} max={900} valid={artifactValid} />
          </Box>}
          <Box flexGrow={1} />
          {probabilityFilter && <strong>Probability: {(probability(art, probabilityFilter) * 100).toFixed(2)}%</strong>}
          <Typography color="success.main">{sheet?.name ?? "Artifact Set"} {setDescTooltip}</Typography>
        </CardContent>
      </ConditionalWrapper>
      <Box sx={{ p: 1, display: "flex", gap: 1, justifyContent: "space-between", alignItems: "center" }}>
        {editable && canEquip
          ? <CharacterAutocomplete sx={{ flexGrow: 1 }} size="small" showDefault
            defaultIcon={<BusinessCenter />} defaultText={t("ui:inventory")}
            value={location} onChange={equipOnChar} />
          : <LocationName location={location} />}
        {editable && <ButtonGroup sx={{ height: "100%" }}>
          {editor && <Tooltip title={<Typography>{t`artifact:edit`}</Typography>} placement="top" arrow>
            <Button color="info" size="small" onClick={onShowEditor} >
              <FontAwesomeIcon icon={faEdit} className="fa-fw" />
            </Button>
          </Tooltip>}
          {canExclude && <Tooltip title={<Typography>{t`artifact:excludeArtifactTip`}</Typography>} placement="top" arrow>
            <Button onClick={() => database.updateArt({ exclude: !exclude }, id)} color={exclude ? "error" : "success"} size="small" >
              <FontAwesomeIcon icon={exclude ? faBan : faChartLine} className="fa-fw" />
            </Button>
          </Tooltip>}
          {!!onDelete && <Button color="error" size="small" onClick={() => onDelete(id)} disabled={lock}>
            <FontAwesomeIcon icon={faTrashAlt} className="fa-fw" />
          </Button>}
          {extraButtons}
        </ButtonGroup>}
      </Box>
    </CardLight >
  </Suspense>
}
Example #14
Source File: WeaponCard.tsx    From genshin-optimizer with MIT License 4 votes vote down vote up
export default function WeaponCard({ weaponId, onClick, onEdit, onDelete, canEquip = false, extraButtons }: WeaponCardProps) {
  const { t } = useTranslation(["page_weapon", "ui"]);
  const { database } = useContext(DatabaseContext)
  const databaseWeapon = useWeapon(weaponId)
  const weapon = databaseWeapon
  const weaponSheet = usePromise(weapon?.key ? WeaponSheet.get(weapon.key) : undefined, [weapon?.key])

  const filter = useCallback(
    (cs: CharacterSheet) => cs.weaponTypeKey === weaponSheet?.weaponType,
    [weaponSheet],
  )

  const wrapperFunc = useCallback(children => <CardActionArea onClick={() => onClick?.(weaponId)} >{children}</CardActionArea>, [onClick, weaponId],)
  const falseWrapperFunc = useCallback(children => <Box >{children}</Box>, [])

  const equipOnChar = useCallback((charKey: CharacterKey | "") => database.setWeaponLocation(weaponId, charKey), [database, weaponId],)

  const UIData = useMemo(() => weaponSheet && weapon && computeUIData([weaponSheet.data, dataObjForWeapon(weapon)]), [weaponSheet, weapon])

  if (!weapon || !weaponSheet || !UIData) return null;
  const { level, ascension, refinement, id, location = "", lock } = weapon
  const weaponTypeKey = UIData.get(input.weapon.type).value!
  const stats = [input.weapon.main, input.weapon.sub, input.weapon.sub2].map(x => UIData.get(x))
  const img = ascension < 2 ? weaponSheet?.img : weaponSheet?.imgAwaken

  return <Suspense fallback={<Skeleton variant="rectangular" sx={{ width: "100%", height: "100%", minHeight: 300 }} />}>
    <CardLight sx={{ height: "100%", display: "flex", flexDirection: "column", justifyContent: "space-between" }}>
      <ConditionalWrapper condition={!!onClick} wrapper={wrapperFunc} falseWrapper={falseWrapperFunc}>
        <Box className={`grad-${weaponSheet.rarity}star`} sx={{ position: "relative", pt: 2, px: 2, }}>
          {!onClick && <IconButton color="primary" onClick={() => database.updateWeapon({ lock: !lock }, id)} sx={{ position: "absolute", right: 0, bottom: 0, zIndex: 2 }}>
            {lock ? <Lock /> : <LockOpen />}
          </IconButton>}
          <Box sx={{ position: "relative", zIndex: 1 }}>
            <Box component="div" sx={{ display: "flex", alignItems: "center", gap: 1, mb: 1 }}>
              <ImgIcon sx={{ fontSize: "1.5em" }} src={Assets.weaponTypes?.[weaponTypeKey]} />
              <Typography noWrap sx={{ textAlign: "center", backgroundColor: "rgba(100,100,100,0.35)", borderRadius: "1em", px: 1 }}><strong>{weaponSheet.name}</strong></Typography>
            </Box>
            <Typography component="span" variant="h5">Lv. {level}</Typography>
            <Typography component="span" variant="h5" color="text.secondary">/{ascensionMaxLevel[ascension]}</Typography>
            <Typography variant="h6">Refinement <strong>{refinement}</strong></Typography>
            <Typography><Stars stars={weaponSheet.rarity} colored /></Typography>
          </Box>
          <Box sx={{ height: "100%", position: "absolute", right: 0, top: 0 }}>
            <Box
              component="img"
              src={img ?? ""}
              width="auto"
              height="100%"
              sx={{ float: "right" }}
            />
          </Box>
        </Box>
        <CardContent>
          {stats.map(node => {
            if (!node.info.key) return null
            const displayVal = valueString(node.value, node.unit, !node.unit ? 0 : undefined)
            return <Box key={node.info.key} sx={{ display: "flex" }}>
              <Typography flexGrow={1}>{StatIcon[node.info.key!]} {KeyMap.get(node.info.key)}</Typography>
              <Typography>{displayVal}</Typography>
            </Box>
          })}
        </CardContent>
      </ConditionalWrapper>
      <Box sx={{ p: 1, display: "flex", gap: 1, justifyContent: "space-between", alignItems: "center" }}>
        {canEquip
          ? <CharacterAutocomplete size="small" sx={{ flexGrow: 1 }}
            showDefault defaultIcon={<BusinessCenter />} defaultText={t("inventory")}
            value={location} onChange={equipOnChar} filter={filter} />
          : <LocationName location={location} />}
        <ButtonGroup>
          {!!onEdit && <Tooltip title={<Typography>{t`page_weapon:edit`}</Typography>} placement="top" arrow>
            <Button color="info" onClick={() => onEdit(id)} >
              <FontAwesomeIcon icon={faEdit} className="fa-fw" />
            </Button>
          </Tooltip>}
          {!!onDelete && <Button color="error" onClick={() => onDelete(id)} disabled={!!location || lock} >
            <FontAwesomeIcon icon={faTrashAlt} className="fa-fw" />
          </Button>}
          {extraButtons}
        </ButtonGroup>
      </Box>
    </CardLight>
  </Suspense>
}
Example #15
Source File: ComponentsPanel.tsx    From MagicUI with Apache License 2.0 4 votes vote down vote up
function WebGLPageList(props: any) {
  const [hideContent, setHideContent] = useState(true);
  const [pages, setPages] = useState([] as PageType[]);
  const [loading, setLoading] = useState(false);
  const [name, setName] = useState('');
  const [disabled, setDisabled] = useState(true);

  const webGLPage = useSelector((state: IStoreState) => state.webGLPage);
  const user = useSelector((state: IStoreState) => state.user);
  const dispatch = useDispatch();

  useEffect(() => setName(webGLPage.name), [webGLPage.name]);

  const handleClick = () => {
    if (hideContent) {
      if (!user.email) return;
      setPages([]);
      setLoading(true);
      fetchAllPages(user.email).then(v => {
        if (!v.err) {
          const pages = v.pages as PageType[];
          setPages(pages);
          setLoading(false);
        }
      }).catch(e => {

      });
    }
    setHideContent(hideContent => !hideContent);
  };
  const canEdit = (e: React.MouseEvent) => {
    e.stopPropagation();
    setDisabled(false);
  }
  const handleModifyPageName = (e: React.MouseEvent) => {
    e.stopPropagation();
    modifyPageName(user.email, webGLPage.id, name).then(v => {
      console.log(v);
      if (!v.err) {
        setDisabled(true);
        return;
      }
      setDisabled(true);
    })
  }

  const elem = pages.length > 0 ? pages.map((v, i) => {
    const click = () => {
      fetchOnePage(user.email, v.pageId).then(res => {
        if (!res.err) {
          dispatch(selectWebGLPage(
            v.pageId,
            v.name,
            res.page.page,
            v.id
          ));
        }
      });
      handleClick();
    };
    return (<ResultItem name={v.name} key={i} onClick={click}/>);
  }).slice(0, 5) : (
    <div className={style.no_data}>
      <FontAwesomeIcon icon={faThermometerEmpty}/> No Data!
    </div>
  );
  const loadingElem = (
    <div className={style.loading}>
      <FontAwesomeIcon icon={faCircleNotch} spin/> loading...
    </div>
  );

  return (
    <div className={style.ui_page_store}>
      <div className={style.current_ui_page} onClick={handleClick}>
        <input type="text"
               className={cls(!disabled && style.active)}
               onClick={disabled ? () => {} : e => e.stopPropagation()}
               value={name}
               onChange={e => setName(e.target.value)}
               disabled={disabled}/>
        <span onClick={disabled ? canEdit : handleModifyPageName}>
          <FontAwesomeIcon icon={disabled ? faEdit : faCheck} color={disabled ? '#999999' : 'red'}/>
        </span>
      </div>
      <div className={cls(style.ui_page_search_panel, !hideContent && style.show)}>
        <div className={style.search}>
          <input type="text" placeholder="search page..."/>
          <button>
            <FontAwesomeIcon icon={faSearch}/>
          </button>
        </div>
        <ul className={style.ui_page_result}>
          {loading ? loadingElem : elem}
        </ul>
      </div>
    </div>
  );
}