Skip to content

Instantly share code, notes, and snippets.

@chanphiromsok
Last active May 25, 2022 01:35
Show Gist options
  • Save chanphiromsok/fb9c6497c13cd0abf9782d64a6099af4 to your computer and use it in GitHub Desktop.
Save chanphiromsok/fb9c6497c13cd0abf9782d64a6099af4 to your computer and use it in GitHub Desktop.
superapps
function getBanner(banners: any[]) {
let objectArr = Object.create(null) as {
[key in string]: StoreBanner[]
};
banners?.forEach((banner) => {
const key = _.camelCase(banner.position)
if (!objectArr[key]) {
objectArr[key] = []
}
objectArr[key].push(banner);
})
return objectArr;
}
import { View, Text, Platform, ActivityIndicator } from 'react-native'
import React, { ComponentProps, memo, useEffect, useRef } from 'react'
import FastImage, { ImageStyle } from "react-native-fast-image";
import { createImageProgress } from 'react-native-image-progress'
import { useCallback, useState } from 'react'
import Animated ,{Easing, interpolate}from "react-native-reanimated"
import { useFocusEffect } from "@react-navigation/native";
const getNewKey = () => Math.random().toString()
export const useCacheBust = (
url: string,
): { bust: () => void; url: string; query: string } => {
const [key, setKey] = useState(getNewKey())
const bust = useCallback(() => {
setKey(getNewKey())
}, [])
const query = `?bust=${key}`
return {
url: `${url}${query}`,
query,
bust,
}
}
const AnimatedFastImage = Animated.createAnimatedComponent(FastImage);
type Props = {
source: ComponentProps<typeof FastImage>['source']
}
const IMAGE_URL =
'https://cdn-images-1.medium.com/max/1600/1*-CY5bU4OqiJRox7G00sftw.gif'
const ImageGrid = ({ source }: Props) => {
const { url, query } = useCacheBust(IMAGE_URL);
const ref = useRef(new Animated.Value(0)).current;
const onLoadEnd = () => {
Animated.timing(ref, {
toValue: 1,
duration: 500,
easing: Easing.linear,
}).start()
}
return (
<View style={{flex:1,backgroundColor:"gray"}}>
<AnimatedFastImage
key={query}
useNativeDriver
source={{
uri: url,
priority: FastImage.priority.high
}}
style={{
flex: 1,
opacity: interpolate(ref, {
inputRange: [0, 1],
outputRange: [0, 1],
extrapolate: Animated.Extrapolate.CLAMP,
})
}}
shouldRasterizeIOS={Platform.OS === "ios" ? true : false}
onLoadEnd={onLoadEnd}
/>
</View>
)
}
export default memo(ImageGrid)
import React, { RefObject, useCallback, useEffect, useRef, useState } from 'react';
import { ScrollView, Text } from "react-native";
import { View } from "react-native-animatable";
import EStyleSheet from "react-native-extended-stylesheet";
import { FlatList } from "react-native-gesture-handler";
import Center from "../../components/container/Center";
import Container from "../../components/container/Container";
import TextI18n from "../../components/text/TextI18n";
import TextProximaSoft from "../../components/text/TextProximaSoft";
import ModalAmountCard from "./components/ModalAmountCard";
const ModalAmountScreen = () => {
const [amounts, setAmount] = useState([1, 1.25, 2, 5, 10, 20]);
const selectedAmount = useRef(0)
const setOpacityTo = useCallback((value, index) => {
dataRefs.forEach((ref, i) => {
ref?.current?.setNativeProps({
style: i === index ? { backgroundColor: "red" } : { backgroundColor: "blue" }
})
})
}, []);
const dataRefs = [] as any[]
amounts.forEach(_ => {
dataRefs.push(React.createRef());
});
return (
<Container flex={1}>
<Center>
<TextProximaSoft >
<TextI18n code="amount" style={{ fontSize: 16, fontWeight: "bold" }} />
</TextProximaSoft>
</Center>
<ScrollView style={{ paddingHorizontal: 15 }}>
{amounts.map((amount, index) => {
return <ModalAmountCard ref={dataRefs[index]} amount={amount} onPressAmount={(amount) => {
selectedAmount.current = amount
setOpacityTo({ opacity: 0 }, index);
}} />
})}
</ScrollView>
</Container>
)
}
export default ModalAmountScreen
import React, { ComponentProps, useMemo, useRef } from 'react'
import { StoreItemResponseData, StoreListResponseData } from "../../../../commons/http/types/StoreApiType";
import { useInfiniteStoreItemListing } from "../../../../commons/queries/useStoreApis";
import Product from "../../components/Product";
import ProductItemGrid from "../../components/ProductItem_Grid";
import { Dimensions, NativeScrollEvent, NativeSyntheticEvent, StyleSheet, Text, View } from "react-native";
import { CloudGroup } from "../../../../commons/http/types/CloudTypes";
import { DataProvider, RecyclerListView, LayoutProvider } from "recyclerlistview"
import _ from 'lodash'
const { width, height } = Dimensions.get('window')
type P = ComponentProps<typeof Product>
type Props = {
selectedCategoryId: number
store: StoreListResponseData;
serviceId: number;
analyticBanner: P["analyticBanner"]
analyticSpotlight: P["analyticSpotlight"]
cloud?: CloudGroup
promotions?: {
items: StoreItemResponseData[];
title: string;
}
width: number;
categoryWidth: number
onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void | undefined
};
const RTC = ({
selectedCategoryId,
store,
serviceId,
analyticBanner,
analyticSpotlight,
cloud,
promotions,
categoryWidth,
width,
onScroll }: Props) => {
const { data, fetchNextPage, hasNextPage, isFetched, isFetchingNextPage } = useInfiniteStoreItemListing(serviceId, {
companyId: store?.store_id,
categoryId: selectedCategoryId,
perPage: 20,
});
const rowRenderer = (type: any, item: any) => {
return <Product
store={store}
serviceId={serviceId}
item={item}
type="grid"
hideSpecialInstruction
analyticBanner={analyticBanner}
analyticSpotlight={analyticSpotlight}
renderItem={(props) => (
<ProductItemGrid
{...props}
width={width - categoryWidth - 2}
spacing={15}
/>
)
}
/>
};
const _layoutProvider = useRef(new LayoutProvider(
i => 1,
(_, dim) => {
dim.width = width / 2;
dim.height = height / 2;
},
))
if (!data?.pages.length) return null;
return (
<View style={styles.container} >
{data?.pages && <RecyclerListView
onEndReachedThreshold={1}
layoutProvider={_layoutProvider.current}
dataProvider={dataProviderMaker(data?.pages?.map((page) => page?.data?.data).flat())}
rowRenderer={rowRenderer} />}
</View>
)
}
const dataProviderMaker = (data: any[]) => {
console.log("DATA", JSON.stringify(data, null, 2));
return new DataProvider((r1, r2) => !_.isEqual(r1, r2)).cloneWithRows([...data])
}
export default RTC;
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#FFF',
minHeight: 1,
minWidth: 1,
},
body: {
marginLeft: 10,
marginRight: 10,
maxWidth: width - (80 + 10 + 20),
},
image: {
height: 80,
width: 80,
},
name: {
fontSize: 20,
fontWeight: 'bold',
},
description: {
fontSize: 14,
opacity: 0.5,
},
listItem: {
flexDirection: 'row',
margin: 10,
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment