add membership type selection option

This commit is contained in:
leander committed 2024-08-07 13:57:48 +02:00
1 parent 15e34b2893
commit 2f03297d0b
4 files changed
+79 -9

No files matched your search

+19
View File
@@ -34,6 +34,7 @@
"react-native-render-html": "^6.3.4",
"react-native-safe-area-context": "4.10.5",
"react-native-screens": "^3.31.1",
"react-native-simple-radio-button": "^2.7.4",
"react-native-svg": "^15.2.0",
"react-native-ui-lib": "^7.26.2",
"react-redux": "^8.1.2",
@@ -49,6 +50,7 @@
"@types/jest": "^29.5.12",
"@types/react": "18.2",
"@types/react-native-confetti": "^0.1.4",
"@types/react-native-simple-radio-button": "^2.7.7",
"eslint": "^8.57.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^18.0.0",
@@ -7011,6 +7013,17 @@
"@types/react": "*"
}
},
"node_modules/@types/react-native-simple-radio-button": {
"version": "2.7.7",
"resolved": "https://registry.npmjs.org/@types/react-native-simple-radio-button/-/react-native-simple-radio-button-2.7.7.tgz",
"integrity": "sha512-cDDpMb+MyYDrZmQX/phRdpbW4SJynTv165MWkwjqa39jbuSkMAxuvBdiTCTBTiugikPRvQRFBG1wPRF/+0Lprw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/react": "*",
"react-native": "*"
}
},
"node_modules/@types/semver": {
"version": "7.5.8",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz",
@@ -16205,6 +16218,12 @@
"react-native": "*"
}
},
"node_modules/react-native-simple-radio-button": {
"version": "2.7.4",
"resolved": "https://registry.npmjs.org/react-native-simple-radio-button/-/react-native-simple-radio-button-2.7.4.tgz",
"integrity": "sha512-QOZNmJUn0ViBGU+at7wAG/uGzd5PfXi0kMHr9lfTCLXknW/f9f2fOVjxjdHvOCdf/zA/eMJBjGjtusSDzQf1+w==",
"license": "MIT"
},
"node_modules/react-native-svg": {
"version": "15.2.0",
"resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.2.0.tgz",
+2
View File
@@ -39,6 +39,7 @@
"react-native-render-html": "^6.3.4",
"react-native-safe-area-context": "4.10.5",
"react-native-screens": "^3.31.1",
"react-native-simple-radio-button": "^2.7.4",
"react-native-svg": "^15.2.0",
"react-native-ui-lib": "^7.26.2",
"react-redux": "^8.1.2",
@@ -54,6 +55,7 @@
"@types/jest": "^29.5.12",
"@types/react": "18.2",
"@types/react-native-confetti": "^0.1.4",
"@types/react-native-simple-radio-button": "^2.7.7",
"eslint": "^8.57.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^18.0.0",
+45 -6
View File
@@ -12,6 +12,7 @@ import {
GestureResponderEvent,
} from 'react-native';
import Confetti from 'react-native-confetti';
import RadioForm from 'react-native-simple-radio-button';
import { Button, Incubator } from 'react-native-ui-lib';
import theme from 'src/theme';
@@ -76,6 +77,7 @@ interface PurchaseButtonProps {
isLoadingMembershipType: boolean;
membershipPrice: number;
onPurchasePress: () => void;
setMembershipTypeSlug: (value: string) => void;
}
const PurchaseButton = ({
@@ -84,13 +86,36 @@ const PurchaseButton = ({
isLoadingMembershipType,
onPurchasePress,
membershipPrice,
setMembershipTypeSlug,
}: PurchaseButtonProps) => {
if (user.is_member) {
return null;
}
const options = [
{ label: 'Student', value: 'student' },
{ label: 'Ordinær', value: 'standard' },
{ label: 'Støtte', value: 'support' },
];
const onSelect = (value: string) => {
setMembershipTypeSlug(value);
};
return (
<View>
<RadioForm
radio_props={options}
initial={1}
formHorizontal={true}
labelHorizontal={false}
buttonColor={theme.colors.neufOrange}
// @ts-expect-error No overload matches this call. We ignore since we need to style the button
selectedButtonColor={theme.colors.neufOrange}
animation={false}
onPress={onSelect}
style={styles.radioForm}
/>
{paymentLoading && <ActivityIndicator color={theme.colors.neufOrange} />}
<Button
onPress={onPurchasePress}
@@ -149,11 +174,18 @@ interface ProofProps {
const Proof = ({ onLogoutPress, fetchUser, isFetchingUserData, onDeletePress }: ProofProps) => {
const CONFETTI_TIMEOUT = 15000;
const confettiRef = useRef<Confetti>(null);
const { paymentLoading, isLoadingMembershipType, onPurchasePress, membershipPrice, toast, setToast, user } = useProof(
{
fetchUser,
},
);
const {
paymentLoading,
isLoadingMembershipType,
onPurchasePress,
membershipPrice,
toast,
setToast,
user,
setMembershipTypeSlug,
} = useProof({
fetchUser,
});
useEffect(() => {
const currentRef = confettiRef.current;
@@ -196,6 +228,7 @@ const Proof = ({ onLogoutPress, fetchUser, isFetchingUserData, onDeletePress }:
isLoadingMembershipType={isLoadingMembershipType}
membershipPrice={membershipPrice}
onPurchasePress={onPurchasePress}
setMembershipTypeSlug={setMembershipTypeSlug}
/>
<MembershipValidTo user={user} />
</View>
@@ -273,7 +306,7 @@ const styles = StyleSheet.create({
fontSize: 18,
},
purchaseButton: {
marginTop: 16,
marginTop: 8,
},
logoutButton: {
alignSelf: 'center',
@@ -308,4 +341,10 @@ const styles = StyleSheet.create({
width: Dimensions.get('window').width * 0.8, // 80% of screen width
alignSelf: 'center',
},
radioForm: {
alignSelf: 'center',
textAlign: 'center',
marginTop: 20,
gap: 12,
},
});
+13 -3
View File
@@ -9,7 +9,7 @@ import { ToastProps } from 'src/types/toast';
const PROOF_QUERY = gql`
{
membershipTypes(isDefault: true) {
membershipTypes {
slug
price
}
@@ -26,7 +26,8 @@ const useProof = ({ fetchUser }: UseProofProps) => {
const { data, loading } = useQuery(PROOF_QUERY);
const { initPaymentSheet, presentPaymentSheet } = useStripe();
const [paymentLoading, setPaymentLoading] = useState(false);
const membershipTypeSlug = data?.membershipTypes?.[0]?.slug ?? 'standard';
const [membershipTypeSlug, setMembershipTypeSlug] = useState('standard');
const [membershipPrice, setMembershipPrice] = useState(25000); // WARNING: Hardcoded due to state not being loaded initially. Should probably be fixed.
const [toast, setToast] = useState<ToastProps | null>(null);
const openPaymentSheet = async () => {
@@ -77,7 +78,15 @@ const useProof = ({ fetchUser }: UseProofProps) => {
}
}, [fetchUser, user?.last_membership]);
const membershipPrice = data?.membershipTypes?.[0]?.price;
useEffect(() => {
// eslint-disable-next-line no-restricted-syntax
for (const membershipType of data?.membershipTypes ?? []) {
if (membershipType.slug === membershipTypeSlug) {
setMembershipPrice(membershipType.price);
}
}
}, [membershipTypeSlug, data?.membershipTypes]);
return {
isLoadingMembershipType: loading,
membershipPrice: membershipPrice ? membershipPrice / 100 : 0,
@@ -86,6 +95,7 @@ const useProof = ({ fetchUser }: UseProofProps) => {
toast,
setToast,
user,
setMembershipTypeSlug,
};
};