Skip to content

Instantly share code, notes, and snippets.

@seandogg
Last active August 11, 2023 04:07
Show Gist options
  • Save seandogg/bfa408ed707a50a55d8805a67ead1d52 to your computer and use it in GitHub Desktop.
Save seandogg/bfa408ed707a50a55d8805a67ead1d52 to your computer and use it in GitHub Desktop.
translate-x-help
import log from 'loglevel';
import PropTypes from 'prop-types';
import { useState, useEffect } from 'react';
import useLocalStorage from 'use-local-storage';
import SvgIcon from '@/components/SvgIcon';
import useSettings from '@/hooks/useSettings';
const CreditsButton = ({
display_vertical = false,
product,
className,
spanClassName,
plusSvgClassName,
creditSvgWidth
}) => {
const { dispatch } = useSettings();
const [creditLabel, setCreditLabel] = useState('');
const [savedStates] = useLocalStorage('jurisdictionKeys', []);
// data is coming down from algolia different than shopify
// also we have series products that need a seperate graph here
// we can extract the credits and label for each of them below.
const extractCredits = (product) => {
if (!product) return [];
log.debug('product is: ', product);
if (product?.variants && product?.variants?.edges) {
if (!product?.variants?.edges?.length) return [];
// get the variant credits from the variant with any downcased title of "live registration" first,
// else fallback to liveRegistrationVariant
const liveRegistrationVariant = product.variants.edges.find((variant) => {
if (variant?.node?.title?.toLowerCase() === 'live registration') {
return (
variant?.node?.metafields?.course?.credits ||
JSON.parse(variant?.node?.credits?.value ?? '{}')
);
}
});
log.debug('liveRegistrationVariant:', liveRegistrationVariant);
if (liveRegistrationVariant) {
return (
liveRegistrationVariant?.node?.metafields?.course?.credits ||
JSON.parse(liveRegistrationVariant?.node?.credits?.value ?? '{}')
);
}
// this can be the fallback
const availableVariantCredits = product.variants.edges.map((variant) => {
log.debug('availableVariantCredits is: ', variant);
return (
variant?.node?.metafields?.course?.credits ||
JSON.parse(variant?.node?.credits?.value ?? '{}')
);
});
if (liveRegistrationVariant) {
log.debug('liveRegistrationVariant:', liveRegistrationVariant);
const uniqueLiveRegistrationCredits = new Set(
liveRegistrationVariant.flat().map((credit) => JSON.stringify(credit))
);
// Return unique live registration credit options
return Array.from(uniqueLiveRegistrationCredits).map((credit) =>
JSON.parse(credit)
);
} else if (availableVariantCredits) {
// Remove duplicate credit options from flattened array
const uniqueVariantCredits = new Set(
availableVariantCredits.flat().map((credit) => JSON.stringify(credit))
);
// Return unique credit options
return Array.from(uniqueVariantCredits).map((credit) =>
JSON.parse(credit)
);
} else if (product?.meta?.course?.credits) {
return product?.meta?.course?.credits ?? [];
} else if (product?.credits) {
return JSON.parse(product?.credits?.value) ?? [];
} else {
return [];
}
} else {
return [];
}
};
const formatCreditLabel = (credits, savedStates) => {
if (!credits) return '';
const builtLabels = credits
.filter((credit) => savedStates.includes(credit['credit-key']))
.map((credit) => `${credit['credit-total']} ${credit['credit-title']}`)
// filter any duplicates out
.filter((credit, index, self) => self.indexOf(credit) === index);
const label =
builtLabels.length > 0
? builtLabels.join(', ')
: `${credits.length} CLE Options Available`;
return label.length > 25 ? `${label.substring(0, 22)}...` : label; // truncate longer labels
};
const setButtonLabels = () => {
if (!product) return;
const credits = extractCredits(product);
const label = formatCreditLabel(credits, savedStates);
setCreditLabel(label);
};
useEffect(() => {
setButtonLabels();
}, [savedStates, product]);
const btnClass = [
'btn--secondary',
'btn--credit',
'cursor-pointer',
'select-none',
'whitespace-nowrap',
'relative',
'z-10',
'text-fine-print',
'font-medium'
];
const buttonClasses = [
...btnClass,
...(Array.isArray(className) ? className : [className])
];
const spanClass = ['select-none', 'align-middle'];
const spanClasses = [
...spanClass,
...(Array.isArray(spanClassName) ? spanClassName : [spanClassName])
];
const plusSvgClass = ['align-middle', 'select-none', 'icon-plus'];
const plusSvgClasses = [
...plusSvgClass,
...(Array.isArray(plusSvgClassName) ? plusSvgClassName : [plusSvgClassName])
];
if (!product || creditLabel === '') return <></>;
return (
<button
type="button"
aria-label={creditLabel}
className={[
...buttonClasses,
...(display_vertical
? ['border-0', 'transition-none']
: ['transition-all', 'xl-max:border-0'])
].join(' ')}
onClick={() => {
dispatch({
type: 'SET_MODAL',
data: {
name: 'credits',
state: true,
product: {
...product,
meta: {
course: {
credits: extractCredits(product)
}
}
}
}
});
}}
>
<SvgIcon
height={creditSvgWidth ? creditSvgWidth : 15}
width={creditSvgWidth ? creditSvgWidth : 15}
className="icon-credits select-none "
name="credits"
/>
<span className={[...spanClasses].join(' ')}>{creditLabel}</span>
<SvgIcon
height={15}
width={15}
className={[...plusSvgClasses].join(' ')}
name="plus"
/>
</button>
);
};
CreditsButton.propTypes = {
product: PropTypes.shape({
variants: PropTypes.shape({
edges: PropTypes.arrayOf(
PropTypes.shape({
node: PropTypes.shape({
credits: PropTypes.shape({
value: PropTypes.string
}),
metafields: PropTypes.shape({
course: PropTypes.shape({
credits: PropTypes.arrayOf(
PropTypes.shape({
'credit-key': PropTypes.string,
'credit-title': PropTypes.string,
'credit-total': PropTypes.string
})
)
})
})
})
})
)
}),
meta: PropTypes.shape({
course: PropTypes.shape({
credits: PropTypes.arrayOf(
PropTypes.shape({
'credit-key': PropTypes.string,
'credit-title': PropTypes.string,
'credit-total': PropTypes.string
})
)
})
}),
credits: PropTypes.shape({
value: PropTypes.string
})
}),
className: PropTypes.oneOfType([
PropTypes.string,
PropTypes.arrayOf(PropTypes.string)
]),
spanClassName: PropTypes.oneOfType([
PropTypes.string,
PropTypes.arrayOf(PropTypes.string)
]),
plusSvgClassName: PropTypes.oneOfType([
PropTypes.string,
PropTypes.arrayOf(PropTypes.string)
]),
creditSvgWidth: PropTypes.number,
display_vertical: PropTypes.bool
};
export default CreditsButton;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment