@apollo/client#useLazyQuery JavaScript Examples
The following examples show how to use
@apollo/client#useLazyQuery.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: PrivateRoute.js From saasgear with MIT License | 6 votes |
PrivateRoute = ({ render }) => {
const history = useHistory();
const dispatch = useDispatch();
const [getProfile, { data: userProfile, loading: loadingUserProfile }] = useLazyQuery(
getProfileQuery,
);
const { data } = useSelector((state) => state.user);
useEffect(() => {
if (!data || Object.keys(data).length === 0) {
getProfile();
}
}, []);
useEffect(() => {
if (userProfile && userProfile.profileUser) {
if (userProfile?.profileUser?.invitationToken) {
history.push(`/teams/invitation/${data?.profileUser?.invitationToken}`);
}
dispatch(setProfileUser({ data: userProfile.profileUser, loading: loadingUserProfile }));
}
}, [userProfile]);
return (
<>
{data && data.id && !loadingUserProfile && (
<Route
render={ props => render(props)}
/>
)}
{(!data || !data.id || loadingUserProfile) && (
<div>Loading...</div>
)}
</>
);
}
Example #2
Source File: podcasts.js From grandcast.fm with Apache License 2.0 | 6 votes |
Podcasts = () => {
const [getPodcasts, { data }] = useLazyQuery(PodcastSearchQuery)
const { isSignedIn } = useAuth()
const [searchString, setSearchString] = useState('')
return (
<Container>
{!isSignedIn() && <SignIn />}
{isSignedIn() && (
<div>
<FormControl id="podcastsearch">
<FormLabel>Search podcasts</FormLabel>
<Flex>
<Input onChange={(e) => setSearchString(e.target.value)} />
<Button
ml={4}
onClick={() =>
getPodcasts({ variables: { searchTerm: searchString } })
}
>
Search
</Button>
</Flex>
</FormControl>
<VStack>
{data?.podcastSearch.map((p) => {
return <Podcast podcast={p} />
})}
</VStack>
</div>
)}
</Container>
)
}
Example #3
Source File: favorites.js From climatescape.org with MIT License | 6 votes |
// Fetches all favorites data from the GraphQL API, waiting until Auth0 is done
// loading so that the current user's favorites may be fetched. Returns a hooked
// object that will eventually take the following shape:
// {
// "rec1": { count: 14, id: "uuid-of-users-favorite" },
// "rec2": { count: 2, id: null },
// }
export function useFavorites(defaultData) {
const { loading: authLoading, user } = useAuth0()
const [favorites, setFavorites] = useState(() =>
indexFavoritesData(defaultData)
)
const uuid = user?.[APP_CLAIM]?.uuid
const [getFavorites, { data }] = useLazyQuery(GetFavorites, {
variables: {
loggedIn: !!user,
userId: uuid,
},
})
// Only fetch favorites from the server once we know if a user is logged in
useEffect(() => {
if (!authLoading) getFavorites()
}, [authLoading, getFavorites])
// Index and set favorites any time data changes
useMemo(() => data && setFavorites(indexFavoritesData(data)), [data])
return favorites
}
Example #4
Source File: favorites.js From goodhere with MIT License | 6 votes |
// Fetches all favorites data from the GraphQL API, waiting until Auth0 is done
// loading so that the current user's favorites may be fetched. Returns a hooked
// object that will eventually take the following shape:
// {
// "rec1": { count: 14, id: "uuid-of-users-favorite" },
// "rec2": { count: 2, id: null },
// }
export function useFavorites(defaultData, { isFavoritesPage } = {}) {
const { loading: authLoading, user } = useAuth0()
const [favorites, setFavorites] = useState(indexFavoritesData(defaultData))
const uuid = user?.sub?.replace(/.+\|/, '')
const [getFavorites, { data, loading: favoritesLoading, called }] = useLazyQuery(isFavoritesPage ? GetUserFavorites : GetFavorites, {
variables: {
loggedIn: !!user,
userId: uuid,
},
})
// Only fetch favorites from the server once we know if a user is logged in
useEffect(() => {
if (!authLoading) getFavorites()
}, [authLoading, getFavorites])
// Index and set favorites any time data changes
useEffect(() => {
if (data) {
setFavorites(isFavoritesPage ? normalizeFavorites(data) : indexFavoritesData(data))
}
}, [data, favoritesLoading])
const isLoading = favoritesLoading || authLoading
return [favorites, isLoading]
}
Example #5
Source File: [uid].js From RC4Community with Apache License 2.0 | 5 votes |
Profile = () => {
const router = useRouter()
const { uid } = router.query
const cookies = Cookies.get('user');
const [getCurrentUser, { data, error, loading }] = useLazyQuery(FindUserByUid);
useEffect(() => {
if(!cookies) {
router.push('/')
}
getCurrentUser({
variables: {
uid: uid
}
})
}, [])
if(error) console.log(error)
if(data?.findUserByUid){
const user = data.findUserByUid
return(
<>
<div className="my-3" style={{display:"flex", alignItems:"center", flexDirection:"column"}}>{
user?.photoURL ?
<img src={user.photoURL}
alt={user.displayName}
className="rounded-circle"
height="130px"
width="130px" />
:
<NoUserAvatar name={user?.displayName} size="130" />
}
<h2 className="my-3">{user.displayName}</h2>
</div>
</>
)
}
return <></>
}
Example #6
Source File: comments.js From stacker.news with MIT License | 5 votes |
export default function Comments ({ parentId, comments, ...props }) {
const client = useApolloClient()
useEffect(() => {
const hash = window.location.hash
if (hash) {
document.querySelector(hash).scrollIntoView({ behavior: 'smooth' })
}
}, [])
const [getComments, { loading }] = useLazyQuery(COMMENTS_QUERY, {
fetchPolicy: 'network-only',
onCompleted: data => {
client.writeFragment({
id: `Item:${parentId}`,
fragment: gql`
${COMMENTS}
fragment Comments on Item {
comments {
...CommentsRecursive
}
}
`,
fragmentName: 'Comments',
data: {
comments: data.comments
}
})
}
})
return (
<>
{comments.length ? <CommentsHeader handleSort={sort => getComments({ variables: { id: parentId, sort } })} /> : null}
{loading
? <CommentsSkeleton />
: comments.map(item => (
<Comment depth={1} key={item.id} item={item} {...props} />
))}
</>
)
}
Example #7
Source File: HospitalPage.js From bedav with GNU General Public License v3.0 | 5 votes |
function HospitalPage(props) {
let { hospitalId } = useParams();
const client = useApolloClient();
hospitalId = decodeURIComponent(hospitalId);
useEffect(() => {
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
});
let cachedHospital = client.readFragment({
id: `Hospital:${hospitalId}`,
fragment: HospitalInfoFragment,
});
const [hospital, setHospital] = useState(cachedHospital);
const [getHospital, { data, loading }] = useLazyQuery(PageQuery, {
variables: {
hospitalId: hospitalId,
},
});
if (data && data.hospital && !hospital) {
setHospital(data.hospital);
}
if (hospital) {
document.title = "Bedav - " + hospital.name;
} else if (loading) {
return <Spinner />;
} else if (hospital === null) {
getHospital({
variables: {
hospitalId,
},
});
return <Spinner />;
}
return (
<>
<MainContainer>
<BedInfoSection hospital={hospital} />
<HospitalInfoSection hospital={hospital} />
</MainContainer>
</>
);
}
Example #8
Source File: use-constructor-loader.js From horondi_client_fe with MIT License | 5 votes |
useConstructorLoader = () => {
const [constructorValues, setConstructorValues] = useState({});
const [constructorModel, setConstructorModel] = useState('');
const currentConstructorModel = useRef({});
const allModels = useRef([]);
const [allPrices, setAllPrice] = useState({});
const [valuesLoading, setValuesLoading] = useState(true);
const { data: constructors, error: constructorsError } = useQuery(getAllConstructors, {
variables: {
limit: 0,
skip: 0
}
});
const [
getConstructorByModelHandler,
{ data: constructorByModel, refetch, called, constructorError }
] = useLazyQuery(getConstructorByModel, {
variables: {
id: constructorModel
}
});
useEffect(() => {
if (constructors) {
allModels.current = constructors.getAllConstructors.items.map((item) => item.model);
setConstructorModel(constructors.getAllConstructors.items[0].model._id);
currentConstructorModel.current = constructors.getAllConstructors.items[0];
}
}, [constructors]);
useEffect(() => {
if (constructorByModel) {
const pocket =
constructorByModel.getConstructorByModel.pocketsWithRestrictions[0]
?.currentPocketWithPosition?.pocket;
const values = {
name: constructorByModel.getConstructorByModel.name,
size: constructorByModel.getConstructorByModel.model.sizes[0],
pattern: constructorByModel.getConstructorByModel.patterns[0],
bottom: constructorByModel.getConstructorByModel.bottoms[0],
basic: constructorByModel.getConstructorByModel.basics[0],
model: constructorByModel.getConstructorByModel.model,
basePrice: constructorByModel.getConstructorByModel.basePrice,
pocket
};
setConstructorValues(values);
currentConstructorModel.current = constructorByModel.getConstructorByModel;
currentConstructorModel.current.model && setValuesLoading(false);
}
}, [constructorByModel]);
useEffect(() => {
!called && constructorModel && getConstructorByModelHandler();
called && refetch();
}, [constructorModel]);
return {
constructorValues,
setConstructorValues,
constructorModel,
setConstructorModel,
currentConstructorModel,
allPrices,
setAllPrice,
allModels,
valuesLoading,
constructorsError,
constructorError
};
}
Example #9
Source File: certificate-thanks-page.js From horondi_client_fe with MIT License | 5 votes |
CertificateThanksPage = () => {
const styles = useStyles();
const { i18n } = useTranslation();
const language = i18n.language === 'ua' ? 0 : 1;
const [paidOrderLoading, setLoading] = useState(true);
const [certificatesArr, setCertificates] = useState(null);
const certificatesOrderId = getFromLocalStorage(orderDataToLS.certificatesOrderId);
const [sendCertificateCodesToEmail] = useLazyQuery(sendCertificatesCodesToEmail);
useSubscription(certificatesPaidSubscription, {
variables: { certificatesOrderId },
onSubscriptionData: ({ subscriptionData: { data } }) => {
const {
certificatesPaid: { certificates }
} = data;
sendCertificateCodesToEmail({
variables: {
language,
certificates
}
});
setCertificates(certificates);
setLoading(false);
}
});
if (paidOrderLoading) {
return <Loader data-testid='loader' />;
}
return (
<div className={styles.thanksBackground}>
<div className={styles.thanksContainer}>
{!paidOrderLoading && (
<div className={styles.thanksInfo}>
<CertificateThanksCard
count={certificatesArr.length}
name={certificatesArr[0]?.name}
email={certificatesArr[0]?.email}
value={certificatesArr[0]?.value}
paymentStatus={certificatesArr[0]?.paymentStatus}
dateStart={certificatesArr[0]?.dateStart}
dateEnd={certificatesArr[0]?.dateEnd}
/>
</div>
)}
</div>
</div>
);
}
Example #10
Source File: search-bar.js From horondi_client_fe with MIT License | 5 votes |
SearchBar = ({
searchParams,
setSearchParams,
fromNavBar = true,
searchHandler,
defaultValue
}) => {
const styles = useStyles({ fromNavBar });
const { t } = useTranslation();
const [searchValue, setSearchValue] = useState('');
const debouncedSearchValue = useDebounce(searchValue, 1000);
const [getProductsQuery, { loading }] = useLazyQuery(getFilteredProductsQuery, {
onCompleted: (data) => {
setSearchParams((prevState) => ({
...prevState,
loading,
products: data.getProducts.items
}));
},
variables: { search: searchParams.searchFilter },
fetchPolicy: 'no-cache'
});
const visibilityToggle = (value) => {
setSearchParams((prevState) => ({
...prevState,
searchBarVisibility: value
}));
};
useEffect(() => {
if (debouncedSearchValue) {
setSearchParams(() => ({
products: [],
searchFilter: debouncedSearchValue,
searchBarVisibility: true
}));
getProductsQuery();
} else {
handleOnBlur();
}
}, [debouncedSearchValue]);
const handleSearch = (event) => {
const { value } = event.target;
setSearchValue(value);
};
const mainClass = fromNavBar ? styles.root : styles.notFromNavbar;
const handleOnBlur = () => {
setTimeout(() => visibilityToggle(false), 100);
};
const handleOnFocus = () => {
if (searchValue) {
visibilityToggle(true);
}
};
return (
<div className={mainClass}>
<SearchIcon />
<TextField
placeholder={t('searchBar.search')}
value={defaultValue || searchValue}
onBlur={handleOnBlur}
onFocus={handleOnFocus}
inputProps={{ maxLength: 20 }}
onChange={searchHandler || handleSearch}
/>
</div>
);
}
Example #11
Source File: filled-cart.js From horondi_client_fe with MIT License | 4 votes |
FilledCart = ({ items, cartOperations }) => {
const styles = useStyles();
const { t } = useTranslation();
const history = useHistory();
const { getCurrencySign } = useCurrency();
const [addConstructorProduct] = useMutation(addProductFromConstructor);
const promoCodeInput = useRef(null);
const { pathToCategory, pathToCheckout } = routes;
const [price, setPrice] = useState();
const [promoCodeValue, setPromoCodeValue] = useState('');
const [productFromConstructorLoading, setProductFromConstructorLoading] = useState(false);
const { currency } = useContext(CurrencyContext);
const { cartLoading, user } = useSelector(({ User }) => ({
user: User.userData
}));
const [getPromoCode, { data: promoCode, error }] = useLazyQuery(getPromoCodeByCode, {
variables: {
code: promoCodeValue
}
});
const currencySign = getCurrencySign();
const { getTotalPrice, setCartItem, getTotalPricesWithPromoCode } = cartOperations;
const checkPromoCode = () => {
setPromoCodeValue(promoCodeInput.current.value);
getPromoCode();
promoCodeInput.current.value = '';
};
useEffect(() => {
promoCode ? setPrice(getTotalPricesWithPromoCode(promoCode)) : setPrice(getTotalPrice());
}, [items, currency, getTotalPrice, promoCode, getTotalPricesWithPromoCode]);
if (cartLoading || productFromConstructorLoading) {
return <Loader />;
}
const onGoToCheckout = async () => {
const itemsFromConstructor = items.filter((item) => item.isFromConstructor);
for (const item of itemsFromConstructor) {
const input = {
product: {
name: item.name,
model: item.model?._id,
pattern: item.pattern?._id,
mainMaterial: {
material: item.basic?.features.material._id,
color: item.basic?.features.color._id
},
bottomMaterial: {
material: item.bottom?.features.material._id,
color: item.bottom?.features.color._id
},
sizes: [item.sizeAndPrice.size._id],
basePrice: item.sizeAndPrice.price
},
upload: []
};
setProductFromConstructorLoading(true);
const { data } = await addConstructorProduct({
variables: {
product: input.product,
upload: input.upload
}
});
setCartItem(item.id, {
...item,
productId: data.addProductFromConstructor._id
});
}
history.push(pathToCheckout, { promoCode });
};
return (
<>
<PathBack />
<div className={styles.root} data-cy='filled-cart'>
<div className={styles.orderWrapper}>
<div className={styles.orderTable}>
<OrderTable
items={items}
user={user}
cartOperations={cartOperations}
promoCode={promoCode}
/>
</div>
</div>
<div>
<div className={styles.promoAndTotalWrapper}>
<div className={styles.promoWrapper}>
<div>
<TextField
className={styles.textField}
InputProps={{
className: styles.promoInput
}}
placeholder={t('cart.promoPlaceHolder')}
variant={TEXT_FIELD_VARIANT.OUTLINED}
inputRef={promoCodeInput}
error={!!error}
helperText={error && t('cart.notFound')}
/>
<Button
data-testid='promoButton'
variant='contained'
className={`${styles.promoButton} ${styles.promoInput}`}
onClick={checkPromoCode}
>
{t('cart.applyPromoCode')}
</Button>
</div>
<Link to={pathToCategory}>
<Button className={styles.shoppingButton}>{t('cart.continue')}</Button>
</Link>
</div>
<div className={styles.totalWrapper}>
{promoCode && (
<div className={styles.totalPrice}>
<span>{t('cart.saving')}</span>
<div>
{currencySign}
{getTotalPrice() - getTotalPricesWithPromoCode(promoCode)}
</div>
</div>
)}
<div className={styles.totalPrice}>
<span>{t('cart.totalPrice')}</span>
<div>
{currencySign}
{price}
</div>
</div>
<Button variant='contained' className={styles.ordersButton} onClick={onGoToCheckout}>
{t('cart.checkout')}
</Button>
</div>
</div>
</div>
<SimilarProducts cartList={items} />
</div>
</>
);
}
Example #12
Source File: gift-certificate.js From horondi_client_fe with MIT License | 4 votes |
GiftCertificate = () => {
const { t } = useTranslation();
const styles = useStyles();
const appStyles = useAppStyles();
const [getPaymentCheckoutForCertificate] = useLazyQuery(getPaymentCheckoutForCertificates, {
onCompleted: (data) => {
const { paymentUrl, paymentToken, certificatesOrderId } =
data.getPaymentCheckoutForCertificates;
setToLocalStorage(orderDataToLS.certificatesOrderId, certificatesOrderId);
window.open(`${process.env.REACT_APP_ROOT_PATH}${pathToCertificateThanks}/${paymentToken}`);
window.open(paymentUrl);
}
});
const [generateCertificates] = useMutation(generateCertificate, {
onCompleted: (data) => {
const { certificates, certificatesPrice } = data.generateCertificate;
getPaymentCheckoutForCertificate({
variables: {
data: {
currency: getCurrentCurrency(currency),
amount: String(certificatesPrice),
certificates
}
}
});
}
});
const initialValues = {
email: ''
};
const { userData, currency } = useSelector(({ User, Currency }) => ({
userData: User.userData,
currency: Currency.currency
}));
const CHECKBOXES_STATE = [
{ value: 500, checked: false, count: INITIAL_CERTIFICATE_COUNT },
{ value: 1000, checked: true, count: INITIAL_CERTIFICATE_COUNT },
{ value: 1500, checked: false, count: INITIAL_CERTIFICATE_COUNT }
];
const [checkboxesArr, setCheckboxesArr] = useState(CHECKBOXES_STATE);
const { errors, values, touched, handleChange, handleSubmit, handleBlur, resetForm } = useFormik({
validationSchema,
initialValues,
onSubmit: () => {
const newCertificates = findCheckedCertificates(checkboxesArr);
generateCertificates({
variables: {
newCertificates,
email: values.email
}
});
}
});
useEffect(() => {
if (userData) {
resetForm({
values: {
email: userData.email
}
});
}
}, [userData, resetForm]);
const handleCheckboxChange = (value, checkboxIndex) => {
setCheckboxesArr(
checkboxesArr.map((checkbox, index) =>
index === checkboxIndex ? { ...checkbox, checked: value } : checkbox
)
);
};
const handleCountChange = (count, index) => {
setCheckboxesArr(
checkboxesArr.map((checkbox, key) => (key === index ? { ...checkbox, count } : checkbox))
);
};
const findCheckedCertificates = (certificates) =>
certificates
.filter((certificate) => certificate.checked === true)
.map(({ checked, ...keepAtrs }) => keepAtrs);
const checkboxContent = checkboxesArr.map((checkbox, index) => (
<CertificateCheckbox
handleAllCheckboxesChange={handleCheckboxChange}
handleAllCountChange={handleCountChange}
checked={checkbox.checked}
index={index}
key={checkbox.value}
value={checkbox.value}
/>
));
const certificateText = (index) => t(`certificate.certificateRules.${index}`);
const certificateRulesContent = certificateRules.map((_, index) => (
<React.Fragment key={index}>
{`${index + 1}. ${certificateText(index)}`}
<br />
</React.Fragment>
));
return (
<div className={appStyles.rootApp}>
<div className={appStyles.containerApp}>
<h1 className={styles.pageTitle}>{t('certificate.giftCertificate')}</h1>
<h2 className={styles.chooseCertificate}>{t('certificate.chooseCertificate')}</h2>
<div className={styles.checkboxWrapper}>{checkboxContent}</div>
<div className={styles.lowerWrapper}>
<div>{certificateRulesContent}</div>
<form onSubmit={handleSubmit}>
<div className={styles.formWrapper}>
<TextField
id='email'
data-testid='email'
fullWidth
label={t('checkout.checkoutTextFields.email')}
variant={TEXT_FIELD_VARIANT.OUTLINED}
className={styles.textField}
onBlur={handleBlur}
onChange={handleChange}
value={values.email}
color={MATERIAL_UI_COLOR.PRIMARY}
name='email'
error={touched.email && Boolean(t(errors.email))}
helperText={touched.email && t(errors.email)}
/>
<Button
data-testid='button'
className={styles.purchaseButton}
fullWidth
type='submit'
>
{t('buttons.buyButton')}
</Button>
</div>
</form>
</div>
</div>
</div>
);
}
Example #13
Source File: UserPage.js From stack-underflow with MIT License | 4 votes |
UserPage = () => {
const classes = useUserPageStyles();
const { notify } = useStateContext();
const { username } = useParams();
const [fetchedUser, setFetchedUser] = useState(null);
const [fetchUser, { data, loading }] = useLazyQuery(GET_USER, {
onError: (err) => {
notify(getErrorMsg(err), 'error');
},
});
useEffect(() => {
fetchUser({ variables: { username } });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [username]);
useEffect(() => {
if (data) {
setFetchedUser(data.getUser);
}
}, [data]);
if (loading || !fetchedUser) {
return (
<div style={{ minWidth: '100%', marginTop: '20%' }}>
<LoadingSpinner size={80} />
</div>
);
}
const {
id,
username: userName,
createdAt,
reputation,
totalQuestions,
totalAnswers,
recentQuestions,
recentAnswers,
} = fetchedUser;
return (
<div className={classes.root}>
<div className={classes.userCard}>
<Avatar
src={`https://secure.gravatar.com/avatar/${id}?s=164&d=identicon`}
alt={username}
className={classes.avatar}
component={RouterLink}
to={`/user/${username}`}
/>
<Typography variant="h5" color="secondary" className={classes.cardText}>
{reputation} <Typography variant="caption">REPUTATION</Typography>
</Typography>
</div>
<div className={classes.infoCard}>
<div className={classes.userInfo}>
<div>
<Typography
variant="h4"
color="primary"
className={classes.bigText}
>
{userName}
</Typography>
<Typography
variant="body1"
color="secondary"
className={classes.smallText}
>
member for {formatDateAgo(createdAt)}
</Typography>
</div>
<div className={classes.statsBar}>
<div style={{ marginRight: 10 }}>
<Typography
variant="h4"
color="primary"
className={classes.bigText}
>
{totalAnswers}
</Typography>
<Typography
variant="body1"
color="secondary"
className={classes.smallText}
>
answers
</Typography>
</div>
<div>
<Typography
variant="h4"
color="primary"
className={classes.bigText}
>
{totalQuestions}
</Typography>
<Typography
variant="body1"
color="secondary"
className={classes.smallText}
>
questions
</Typography>
</div>
</div>
</div>
<Divider />
<div className={classes.recentActivity}>
<div style={{ marginBottom: '1em' }}>
<Typography variant="h6" color="primary">
Last Asked Questions
</Typography>
<Divider />
{recentQuestions.length !== 0 ? (
recentQuestions.map((q) => (
<div key={q.id}>
<RecentQuestions question={q} />
<Divider />
</div>
))
) : (
<Typography variant="subtitle1">
No questions asked yet.
</Typography>
)}
</div>
<div>
<Typography variant="h6" color="primary">
Last Answered Questions
</Typography>
<Divider />
{recentAnswers.length !== 0 ? (
recentAnswers.map((q) => (
<div key={q.id}>
<RecentQuestions question={q} />
<Divider />
</div>
))
) : (
<Typography variant="subtitle1">
No questions answered yet.
</Typography>
)}
</div>
</div>
</div>
</div>
);
}
Example #14
Source File: comments-item.js From horondi_client_fe with MIT License | 4 votes |
CommentsItem = ({ userFirstName, commentItem, commentId, productId, refetchComments }) => {
const styles = useStyles();
const { user, text, date, show, rate, replyCommentsCount, verifiedPurchase } = commentItem;
const { userData } = useSelector(({ User }) => ({
userData: User.userData
}));
const { t, i18n } = useTranslation();
const { firstName, email } = user || {
firstName: t('common.userData.firstName'),
email: t('common.userData.email')
};
const [isModalShown, toggleModal] = useState(false);
const [isReplyShown, toggleReply] = useState();
const [isReplyListShown, toggleReplyList] = useState(false);
const [currentLimit, setCurrentLimit] = useState(3);
const dateLanguage = i18n.language === 'ua' ? 'ukr-UA' : 'en-US';
const dateToShow = new Date(date);
const [getReplyCommentsByID, { loading, data: replyCommentsData, error, called }] = useLazyQuery(
getReplyCommentsQuery,
{
variables: {
filter: { commentId, filters: false },
pagination: { skip: handleSkip(replyCommentsCount, currentLimit), limit: currentLimit }
},
fetchPolicy: 'network-only',
nextFetchPolicy: 'cache-first'
}
);
if (error || loading) return errorOrLoadingHandler(error, loading);
const { replyComments } = replyCommentsData
? replyCommentsData.getReplyCommentsByComment.items[0]
: { replyComments: [] };
const commentDate = dateToShow.toLocaleString(dateLanguage, COMMENTS_TIME_OPTIONS);
const reloadCommentsData = async () => {
toggleReplyList(true);
await refetchComments();
getReplyCommentsByID();
};
const handleOpen = () => {
toggleModal(true);
};
const handleClose = () => {
toggleModal(false);
};
const handleReplyOpen = () => {
toggleReply(true);
};
const handleReplyClose = () => {
toggleReply(false);
};
const showReplyList = async () => {
!called && getReplyCommentsByID();
toggleReplyList((prevIsReplyListShown) => !prevIsReplyListShown);
};
const getMoreComments = async () => {
getReplyCommentsByID();
setCurrentLimit((prev) => prev + 10);
};
const replyCommentsList = replyComments.map(({ _id, ...rest }) => (
<ReplyCommentsItem
key={_id}
replyItem={rest}
replyCommentId={_id}
updateReplies={reloadCommentsData}
/>
));
const limitOption = replyCommentsList.length === replyCommentsCount;
const loadMore = limitOption ? null : t('product.comments.loadMore');
return (
<div className={styles.container}>
<div className={styles.comments}>
<div className={styles.comment}>
<div className={styles.userContainer}>
<div className={styles.user}>
<span className={styles.name} data-testid='firstName'>
{firstName}
</span>
</div>
<div className={styles.commentActions}>
{verifiedPurchase ? (
<Tooltip className={styles.checkIcon} title={t('product.tooltips.bought')}>
<>
<VerifiedPurchaseIcon
alt='Verified purchase icon'
className={styles.boughtIcon}
/>
</>
</Tooltip>
) : null}
{handleUserCommentApprove(userData, email, show) ? (
<Tooltip title={t('product.tooltips.feedbackComment')}>
<>
<FeedbackOutlinedIcon className={styles.iconF} />
</>
</Tooltip>
) : null}
</div>
</div>
<div className={styles.date}>{commentDate}</div>
</div>
<div className={styles.rateIcon}>{handleRate(rate)}</div>
<div className={styles.textContent}>
<div
className={handleTextStyle(show, styles.text, `${styles.notAproveText} ${styles.text}`)}
data-testid='commentText'
>
{text}
</div>
<div className={styles.userIcons}>
{handleUserCommentOwner(userData, email) ? (
<div className={styles.icons}>
<Tooltip title={t('product.tooltips.delete')}>
<DeleteIcon className={styles.deleteIcon} onClick={handleOpen} />
</Tooltip>
</div>
) : null}
</div>
</div>
<div className={styles.reply}>
<ReplyOutlinedIcon className={styles.replyIcon} />
<Tooltip title={userData ? '' : t(`product.tooltips.unregisteredReply`)}>
<p className={styles.button} onClick={handleReplyOpen}>
{t('common.reply.submit')}
</p>
</Tooltip>
{replyCommentsCount ? (
<div className={styles.replyCount} onClick={showReplyList}>
<ChatBubbleOutlineOutlinedIcon className={styles.icon} />
<span className={styles.replyText}>
{replyCommentsCount}
{'\u00A0'}
{t('common.reply.answers')}
</span>
</div>
) : null}
</div>
{isReplyShown && userData?._id && (
<ReplyForm
userFirstName={userFirstName}
user={user}
className={styles.replyForm}
cancel={handleReplyClose}
refetchComments={reloadCommentsData}
commentId={commentId}
productId={productId}
/>
)}
{isReplyListShown ? (
<div>
{replyCommentsCount > currentLimit && (
<div className={styles.loadMore}>
{handleArrowIcon(limitOption)}
<span onClick={getMoreComments} className={styles.loadMoreText}>
{loadMore}
</span>
</div>
)}
{loading && (
<div className={styles.loader}>
<Loader width={20} height={20} heightWrap={40} />
</div>
)}
{replyCommentsList}
</div>
) : null}
</div>
<CommentDialog
handleClose={handleClose}
isModalShown={isModalShown}
id={commentId}
userId={handleUserId(userData)}
isDeleteComment
refetchComments={refetchComments}
/>
</div>
);
}
Example #15
Source File: thanks-page.js From horondi_client_fe with MIT License | 4 votes |
ThanksPage = () => {
const router = useLocation();
const { t, i18n } = useTranslation();
const dispatch = useDispatch();
const language = i18n.language === 'ua' ? 0 : 1;
const [paidOrderLoading, setLoading] = useState(true);
const { order, loading, user } = useSelector(({ Order, User }) => ({
order: Order.order,
loading: Order.loading,
user: User.userData
}));
const styles = useStyles();
const paymentMethod = getFromLocalStorage(orderDataToLS.paymentMethod);
const [sendPaidOrderToEmail] = useLazyQuery(sendOrderToEmail);
const paidOrderNumber = router.pathname.slice(router.pathname.length - ORDER_NUMBER_LENGTH);
useSubscription(orderPaidSubscription, {
variables: { orderId: paidOrderNumber },
onSubscriptionData: ({
subscriptionData: {
data: { paidOrder }
}
}) => {
dispatch(setOrder(paidOrder));
setToLocalStorage(orderDataToLS.order, paidOrder);
sendPaidOrderToEmail({
variables: {
language,
paidOrderNumber
}
});
setLoading(false);
}
});
useEffect(() => {
if (paymentMethod === checkoutPayMethod.cash) {
dispatch(getOrder());
}
}, [dispatch, language, user]);
if ((paymentMethod === checkoutPayMethod.card && paidOrderLoading) || loading) {
return <Loader data-testid='loader' />;
}
const getDeliveryAddress = (orderPayload) => {
const deliveryType = orderPayload?.delivery.sentBy;
const courierOffice = orderPayload?.delivery.courierOffice;
const customerAddress = `${orderPayload?.delivery.city}, ${orderPayload?.delivery.street}, ${orderPayload?.delivery.house}`;
if (deliveryType === deliveryTypes.NOVAPOST || deliveryType === deliveryTypes.UKRPOST) {
return courierOffice;
}
if (deliveryType === deliveryTypes.SELFPICKUP) {
return t('thanksPage.thanksCard.selfDelivery');
}
return customerAddress;
};
return (
<div className={styles.thanksBackground}>
<div className={styles.thanksContainer}>
{!order && <Redirect to={pathToMain} /> &&
paymentMethod !== t('checkout.checkoutPayment.card')}
{(!loading || !paidOrderLoading) && (
<>
<div className={styles.thunksInfo}>
<ThanksCard
orderNumber={order?.orderNumber}
customerName={`${order?.recipient.firstName} ${order?.recipient.lastName}`}
phoneNumber={order?.recipient.phoneNumber}
deliveryType={order?.delivery.sentBy}
address={getDeliveryAddress(order)}
/>
</div>
</>
)}
</div>
</div>
);
}
Example #16
Source File: QuestionPage.js From stack-underflow with MIT License | 4 votes |
QuestionPage = () => {
const { clearEdit, notify } = useStateContext();
const { user } = useAuthContext();
const { quesId } = useParams();
const [question, setQuestion] = useState(null);
const classes = useQuesPageStyles();
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('xs'));
const [fetchQuestion, { data, loading }] = useLazyQuery(VIEW_QUESTION, {
onError: (err) => {
notify(getErrorMsg(err), 'error');
},
});
useEffect(() => {
fetchQuestion({ variables: { quesId } });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [quesId]);
useEffect(() => {
if (data) {
setQuestion(data.viewQuestion);
}
}, [data]);
if (loading || !question) {
return (
<div style={{ minWidth: '100%', marginTop: '20%' }}>
<LoadingSpinner size={80} />
</div>
);
}
const { title, views, createdAt, updatedAt } = question;
return (
<div className={classes.root}>
<div className={classes.topBar}>
<div className={classes.titleWrapper}>
<Typography
variant={isMobile ? 'h6' : 'h5'}
color="secondary"
style={{ wordWrap: 'anywhere' }}
>
{title}
</Typography>
{user ? (
<Button
variant="contained"
color="primary"
size={isMobile ? 'small' : 'medium'}
component={RouterLink}
to="/ask"
onClick={() => clearEdit()}
style={{ minWidth: '9em' }}
>
Ask Question
</Button>
) : (
<AuthFormModal buttonType="ask" />
)}
</div>
<div className={classes.quesInfo}>
<Typography variant="caption" style={{ marginRight: 10 }}>
Asked <strong>{formatDateAgo(createdAt)} ago</strong>
</Typography>
{createdAt !== updatedAt && (
<Typography variant="caption" style={{ marginRight: 10 }}>
Edited <strong>{formatDateAgo(updatedAt)} ago</strong>
</Typography>
)}
<Typography variant="caption">
Viewed <strong>{views} times</strong>
</Typography>
</div>
</div>
<Divider />
<Grid container direction="row" wrap="nowrap" justify="space-between">
<QuesPageContent question={question} />
<RightSidePanel />
</Grid>
</div>
);
}
Example #17
Source File: index.js From openeew-dashboard with Apache License 2.0 | 4 votes |
Sensors = ({ history }) => {
const { addToast } = useContext(AppContext)
const [execQuery, { data, loading }] = useLazyQuery(GET_SENSORS, {
errorPolicy: 'all',
// TODO
onError() {
addToast({
kind: 'warning',
caption:
'There were errors generated by the sensor query that may affect the display of relevant data. If this is a recurring warning, consider opening an issue.',
title: 'Sensor Data Loaded with Error(s)',
})
},
})
const [pageSize, setPageSize] = useState(5)
const [page, setPage] = useState(1)
const [sensors, setSensors] = useState([])
const [currentlyVisibleSensors, setCurrentlyVisibleSensors] = useState([])
const [shouldShowSideMenu, setShouldShowSideMenu] = useState(false)
const [shouldShowRemoveMenu, setShouldShowRemoveMenu] = useState(false)
const [displayedSensor, setDisplayedSensor] = useState({})
const [removeSensorLoading, setRemoveSensorLoading] = useState(false)
const [currentHoveredSensor, setCurrentHoveredSensor] = useState()
const [sendRemoveSensor] = useMutation(SEND_SENSOR_REMOVE)
useEffect(() => {
execQuery()
}, [execQuery])
useEffect(() => {
if (data && data.sensors) {
setSensors(processSensorData(data.sensors))
}
}, [data])
useEffect(() => {
setCurrentlyVisibleSensors(
sensors.slice((page - 1) * pageSize, page * pageSize)
)
}, [page, pageSize, sensors])
const onSensorHover = (index) => {
setCurrentHoveredSensor(index)
}
const onModify = (sensor) => {
setShouldShowSideMenu(true)
setDisplayedSensor(sensor)
}
const onRemove = (sensor) => {
setShouldShowRemoveMenu(true)
setDisplayedSensor(sensor)
}
const removeSensor = () => {
setRemoveSensorLoading(true)
sendRemoveSensor({ variables: { sensorId: displayedSensor.id } })
.then(() => {
setRemoveSensorLoading(false)
setShouldShowRemoveMenu(false)
setSensors(() => {
return sensors.filter((sensor) => sensor.id !== displayedSensor.id)
})
})
.catch((e) => {
return handleGraphQLError(e)
})
}
const onPaginationChange = (paginationInfo) => {
setPage(paginationInfo.page)
setPageSize(paginationInfo.pageSize)
}
const setFilter = (e) => {
if (e.selectedItem.id === 'my-sensors') {
setSensors(sensors.filter((sensor) => sensor.isUserOwner))
} else {
setSensors(processSensorData(data.sensors))
}
}
return (
<div className="sensors-page">
<p className="title" tabIndex={0}>
Sensors
</p>
<Dropdown
id="sensor-group-dropdown"
className="sensor-group-dropdown"
label={sensorGroupDropdownItems[0].text}
itemToString={(item) => (item ? item.text : '')}
items={sensorGroupDropdownItems}
onChange={setFilter}
/>
<div className="sensors-map__container">
<SensorsMap
sensors={sensors}
setDisplayedSensor={setDisplayedSensor}
setShouldShowSideMenu={setShouldShowSideMenu}
onSensorHover={onSensorHover}
currentHoveredSensor={currentHoveredSensor}
/>
</div>
<div className="sensors-table__container">
<SensorsTable
loading={loading}
history={history}
sensors={sensors}
onSensorHover={onSensorHover}
currentHoveredSensor={currentHoveredSensor}
onPaginationChange={onPaginationChange}
page={page}
pageSize={pageSize}
currentlyVisibleSensors={currentlyVisibleSensors}
setSensors={setSensors}
shouldShowSideMenu={shouldShowSideMenu}
shouldShowRemoveMenu={shouldShowRemoveMenu}
removeSensorLoading={removeSensorLoading}
displayedSensor={displayedSensor}
setDisplayedSensor={setDisplayedSensor}
setShouldShowSideMenu={setShouldShowSideMenu}
setShouldShowRemoveMenu={setShouldShowRemoveMenu}
removeSensor={removeSensor}
onModify={onModify}
onRemove={onRemove}
/>
</div>
</div>
)
}
Example #18
Source File: QuesListPage.js From stack-underflow with MIT License | 4 votes |
QuesListPage = ({ tagFilterActive, searchFilterActive }) => {
const { tagName, query } = useParams();
const { clearEdit, notify } = useStateContext();
const { user } = useAuthContext();
const [quesData, setQuesData] = useState(null);
const [sortBy, setSortBy] = useState('HOT');
const [page, setPage] = useState(1);
const classes = useQuesListStyles();
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('xs'));
const [fetchQuestions, { data, loading }] = useLazyQuery(GET_QUESTIONS, {
fetchPolicy: 'network-only',
onError: (err) => {
notify(getErrorMsg(err), 'error');
},
});
const getQues = (sortBy, page, limit, filterByTag, filterBySearch) => {
fetchQuestions({
variables: { sortBy, page, limit, filterByTag, filterBySearch },
});
};
useEffect(() => {
getQues(sortBy, 1, 12, tagName, query);
setPage(1);
window.scrollTo(0, 0);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [sortBy, tagName, query]);
useEffect(() => {
if (data && page === 1) {
setQuesData(data.getQuestions);
}
if (data && page !== 1) {
setQuesData((prevState) => ({
...data.getQuestions,
questions: prevState.questions.concat(
filterDuplicates(prevState.questions, data.getQuestions.questions)
),
}));
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [data]);
const handleLoadPosts = () => {
getQues(sortBy, page + 1, 12, tagName, query);
setPage(page + 1);
};
return (
<div className={classes.root}>
<div className={classes.topBar}>
<Typography
variant={isMobile ? 'h6' : 'h5'}
color="secondary"
style={{ wordWrap: 'anywhere' }}
>
{tagFilterActive
? `Questions tagged [${tagName}]`
: searchFilterActive
? `Search results for "${query}"`
: 'All Questions'}
</Typography>
{user ? (
<Button
variant="contained"
color="primary"
size={isMobile ? 'small' : 'medium'}
component={RouterLink}
to="/ask"
onClick={() => clearEdit()}
style={{ minWidth: '9em' }}
>
Ask Question
</Button>
) : (
<AuthFormModal buttonType="ask" />
)}
</div>
<SortQuesBar isMobile={isMobile} sortBy={sortBy} setSortBy={setSortBy} />
<Divider />
{loading && page === 1 && (
<div style={{ minWidth: '100%', marginTop: '1em' }}>
<LoadingSpinner size={60} />
</div>
)}
{quesData &&
(quesData.questions.length !== 0 ? (
quesData.questions.map((q) => <QuesCard key={q.id} question={q} />)
) : (
<Typography
color="secondary"
variant="h6"
className={classes.noQuesText}
>
{tagFilterActive
? `There are no questions tagged "${tagName}".`
: searchFilterActive
? `No matches found for your search "${query}".`
: 'No questions found.'}
</Typography>
))}
{quesData && quesData.next && (
<LoadMoreButton
loading={page !== 1 && loading}
handleLoadPosts={handleLoadPosts}
/>
)}
</div>
);
}
Example #19
Source File: BankTransferFlow.js From ucurtmetre with GNU General Public License v3.0 | 4 votes |
function BankTransferFlow() {
const location = useLocation();
const [currentBank, setCurrentBank] = React.useState(-1);
const blAuth = localStorage.getItem('blAuth');
const [
collectDonation,
{ data: donationData, error: donationError, loading: donationLoading },
] = useMutation(COLLECT_DONATION, { onError: err => err });
const [getOauthUrl, { data }] = useLazyQuery(GET_OAUTH_URL, {
variables: {
campaignId: 'donate-all',
returnUrl: 'https://destek.ucurtmaprojesi.com/auth/callback',
},
});
const [
getBanks,
{ error: bankError, data: bankData, loading: bankLoading },
] = useLazyQuery(GET_BANKS, {
context: {
headers: {
oauth2: blAuth,
},
},
});
useEffect(() => {
if (blAuth) {
getBanks();
} else {
getOauthUrl();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
if (bankError) {
localStorage.removeItem('blAuth');
getOauthUrl();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [bankError]);
return (
<div className="bank-transfer-flow">
{location.state?.state?.redirectError && (
<Alert
icon={<AlertCircle />}
variant="danger"
message="BiLira ile bağlantı kurulurken bir hata oluştu. Lütfen daha sonra tekrar deneyin."
/>
)}
<Alert
message={
<>
<p>
Yapacağınız destekleri güvenli ve hızlı bir şekilde öğrencimize
ulaştırabilmek için{' '}
<a
href="https://www.bilira.co/"
target="_blank"
rel="noopener noreferrer"
>
BiLira
</a>{' '}
ile çalışıyoruz.
</p>
{!blAuth && (
<p>
Aşağıdaki butonu kullanarak hızlıca hesap oluşturabilir, varolan
hesabınızla transferi yapacağınız banka hesabına kolayca
ulaşabilirsiniz.
</p>
)}
</>
}
icon={<AlertCircle />}
/>
{bankLoading && (
<div>
<Skeleton count={4} />
</div>
)}
{data && !blAuth && (
<a
className="login-with-bilira"
href={data.biliraOAuthUrl.authorizationUri}
>
BiLira ile giriş yap
</a>
)}
{bankData && !donationData && (
<>
<SelectBank
bankData={bankData}
onSelect={bankId => setCurrentBank(bankId)}
selectedBank={currentBank}
/>
{currentBank !== -1 && (
<Formik
initialValues={{
email: '',
amount: '',
consentToReceiveNews: false,
consentToUserAgreement: false,
}}
validationSchema={bankTransferValidation}
onSubmit={async (values, { setSubmitting }) => {
setSubmitting(true);
collectDonation({
variables: {
campaignCode: 'campaign-all',
bankId: parseInt(currentBank, 10),
email: values.email,
amount: parseFloat(values.amount),
},
context: {
headers: {
oauth2: blAuth,
},
},
});
}}
>
{({ isSubmitting, dirty, isValid }) => (
<Form data-private>
<div>
<Input
label="Email"
name="email"
type="email"
placeholder="Lütfen email adresinizi girin."
/>
<Input
label="Miktar"
name="amount"
type="number"
placeholder="Lütfen göndermek istediğiniz destek miktarını giriniz."
/>
</div>
<Agreements
kvkkName="consentToReceiveNews"
agreementName="consentToUserAgreement"
/>
<button
className="button secondary-button submit"
type="submit"
disabled={
isSubmitting || !dirty || !isValid || donationLoading
}
width="full"
>
Destekle
</button>
</Form>
)}
</Formik>
)}
</>
)}
{(donationData || donationError) && (
<BankDetailViewer error={donationError} data={donationData} />
)}
</div>
);
}
Example #20
Source File: job-form.js From stacker.news with MIT License | 4 votes |
// need to recent list items
export default function JobForm ({ item, sub }) {
const storageKeyPrefix = item ? undefined : `${sub.name}-job`
const router = useRouter()
const [monthly, setMonthly] = useState(satsMin2Mo(item?.maxBid || sub.baseCost))
const [getAuctionPosition, { data }] = useLazyQuery(gql`
query AuctionPosition($id: ID, $bid: Int!) {
auctionPosition(sub: "${sub.name}", id: $id, bid: $bid)
}`,
{ fetchPolicy: 'network-only' })
const [upsertJob] = useMutation(gql`
mutation upsertJob($id: ID, $title: String!, $company: String!, $location: String,
$remote: Boolean, $text: String!, $url: String!, $maxBid: Int!, $status: String) {
upsertJob(sub: "${sub.name}", id: $id, title: $title, company: $company,
location: $location, remote: $remote, text: $text,
url: $url, maxBid: $maxBid, status: $status) {
id
}
}`
)
const JobSchema = Yup.object({
title: Yup.string().required('required').trim(),
company: Yup.string().required('required').trim(),
text: Yup.string().required('required').trim(),
url: Yup.string()
.or([Yup.string().email(), Yup.string().url()], 'invalid url or email')
.required('Required'),
maxBid: Yup.number('must be number')
.integer('must be whole').min(sub.baseCost, `must be at least ${sub.baseCost}`)
.required('required'),
location: Yup.string().test(
'no-remote',
"don't write remote, just check the box",
v => !v?.match(/\bremote\b/gi))
.when('remote', {
is: (value) => !value,
then: Yup.string().required('required').trim()
})
})
const position = data?.auctionPosition
useEffect(() => {
const initialMaxBid = Number(item?.maxBid || localStorage.getItem(storageKeyPrefix + '-maxBid')) || sub.baseCost
getAuctionPosition({ variables: { id: item?.id, bid: initialMaxBid } })
setMonthly(satsMin2Mo(initialMaxBid))
}, [])
return (
<>
<Form
className='py-5'
initial={{
title: item?.title || '',
company: item?.company || '',
location: item?.location || '',
remote: item?.remote || false,
text: item?.text || '',
url: item?.url || '',
maxBid: item?.maxBid || sub.baseCost,
stop: false,
start: false
}}
schema={JobSchema}
storageKeyPrefix={storageKeyPrefix}
onSubmit={(async ({ maxBid, stop, start, ...values }) => {
let status
if (start) {
status = 'ACTIVE'
} else if (stop) {
status = 'STOPPED'
}
const { error } = await upsertJob({
variables: {
id: item?.id,
sub: sub.name,
maxBid: Number(maxBid),
status,
...values
}
})
if (error) {
throw new Error({ message: error.toString() })
}
if (item) {
await router.push(`/items/${item.id}`)
} else {
await router.push(`/~${sub.name}/recent`)
}
})}
>
<Input
label='job title'
name='title'
required
autoFocus
/>
<Input
label='company'
name='company'
required
/>
<BForm.Row className='mr-0'>
<Col>
<Input
label='location'
name='location'
/>
</Col>
<Checkbox
label={<div className='font-weight-bold'>remote</div>} name='remote' hiddenLabel
groupClassName={styles.inlineCheckGroup}
/>
</BForm.Row>
<MarkdownInput
label='description'
name='text'
as={TextareaAutosize}
minRows={6}
required
/>
<Input
label={<>how to apply <small className='text-muted ml-2'>url or email address</small></>}
name='url'
required
/>
<Input
label={
<div className='d-flex align-items-center'>bid
<Info>
<ol className='font-weight-bold'>
<li>The higher your bid the higher your job will rank</li>
<li>The minimum bid is {sub.baseCost} sats/min</li>
<li>You can increase or decrease your bid, and edit or stop your job at anytime</li>
<li>Your job will be hidden if your wallet runs out of sats and can be unhidden by filling your wallet again</li>
</ol>
</Info>
</div>
}
name='maxBid'
onChange={async (formik, e) => {
if (e.target.value >= sub.baseCost && e.target.value <= 100000000) {
setMonthly(satsMin2Mo(e.target.value))
getAuctionPosition({ variables: { id: item?.id, bid: Number(e.target.value) } })
} else {
setMonthly(satsMin2Mo(sub.baseCost))
}
}}
append={<InputGroup.Text className='text-monospace'>sats/min</InputGroup.Text>}
hint={<PriceHint monthly={monthly} />}
/>
<><div className='font-weight-bold text-muted'>This bid puts your job in position: {position}</div></>
{item && <StatusControl item={item} />}
<SubmitButton variant='secondary' className='mt-3'>{item ? 'save' : 'post'}</SubmitButton>
</Form>
</>
)
}
Example #21
Source File: link-form.js From stacker.news with MIT License | 4 votes |
export function LinkForm ({ item, editThreshold }) {
const router = useRouter()
const client = useApolloClient()
const [getPageTitle, { data }] = useLazyQuery(gql`
query PageTitle($url: String!) {
pageTitle(url: $url)
}`, {
fetchPolicy: 'network-only'
})
const [getDupes, { data: dupesData }] = useLazyQuery(gql`
${ITEM_FIELDS}
query Dupes($url: String!) {
dupes(url: $url) {
...ItemFields
}
}`, {
fetchPolicy: 'network-only'
})
const [upsertLink] = useMutation(
gql`
mutation upsertLink($id: ID, $title: String!, $url: String!, $boost: Int, $forward: String) {
upsertLink(id: $id, title: $title, url: $url, boost: $boost, forward: $forward) {
id
}
}`
)
const LinkSchema = Yup.object({
title: Yup.string().required('required').trim(),
url: Yup.string().matches(URL, 'invalid url').required('required'),
...AdvPostSchema(client)
})
return (
<Form
initial={{
title: item?.title || '',
url: item?.url || '',
...AdvPostInitial
}}
schema={LinkSchema}
onSubmit={async ({ boost, ...values }) => {
const { error } = await upsertLink({
variables: { id: item?.id, boost: Number(boost), ...values }
})
if (error) {
throw new Error({ message: error.toString() })
}
if (item) {
await router.push(`/items/${item.id}`)
} else {
await router.push('/recent')
}
}}
storageKeyPrefix={item ? undefined : 'link'}
>
<Input
label='title'
name='title'
overrideValue={data?.pageTitle}
required
/>
<Input
label='url'
name='url'
required
autoFocus
hint={editThreshold
? <div className='text-muted font-weight-bold'><Countdown date={editThreshold} /></div>
: null}
onChange={async (formik, e) => {
if ((/^ *$/).test(formik?.values.title)) {
getPageTitle({
variables: { url: e.target.value }
})
}
getDupes({
variables: { url: e.target.value }
})
}}
/>
{!item && <AdvPostForm />}
<ActionTooltip>
<SubmitButton variant='secondary' className='mt-3'>{item ? 'save' : 'post'}</SubmitButton>
</ActionTooltip>
{dupesData?.dupes?.length > 0 &&
<div className='mt-3'>
<AccordianItem
show
headerColor='#c03221'
header={<div style={{ fontWeight: 'bold', fontSize: '92%' }}>dupes</div>}
body={
<div>
{dupesData.dupes.map((item, i) => (
<Item item={item} key={item.id} />
))}
</div>
}
/>
</div>}
</Form>
)
}