Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
pinocchio-life-like committed Sep 9, 2024
1 parent bcfc63e commit e1300cd
Show file tree
Hide file tree
Showing 23 changed files with 775 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { XStack, RText } from '@packrat/ui';
import { Clock } from '@tamagui/lucide-icons';
import React, { type FC } from 'react';

interface CreatedAtLabelProps {
date: string;
}
export const CreatedAtLabel: FC<CreatedAtLabelProps> = ({ date }) => {
return (
<XStack
style={{ marginTop: 4, alignItems: 'center', maxWidth: '100%' }}
space={4}
>
<Clock size={16} />
<RText>{date}</RText>
</XStack>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { CreatedAtLabel } from './CreatedAtLabel';
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { AntDesign } from '@expo/vector-icons';
import { RText, XStack } from '@packrat/ui';
import React, { type FC } from 'react';
import { Pressable, type GestureResponderEvent } from 'react-native';

interface FavoriteButtonProps {
isAuthUserFavorite: boolean;
onClick: (e: GestureResponderEvent) => void;
count: number;
}
export const FavoriteButton: FC<FavoriteButtonProps> = ({
onClick,
isAuthUserFavorite,
count,
}) => {
return (
<XStack style={{ alignItems: 'center' }} space="$2">
<Pressable onPress={onClick}>
<AntDesign
name="heart"
size={16}
color={isAuthUserFavorite ? 'red' : undefined}
/>
</Pressable>
<RText style={{ fontSize: 14 }}>{count}</RText>
</XStack>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { FavoriteButton } from './FavoriteButton';
260 changes: 260 additions & 0 deletions packages/app/modules/feed/components/FeedCard/FeedCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
import React, { type FC } from 'react';
import { type FeedItem, type FeedType } from 'app/modules/feed/model';
import { feedItemPackCardConverter } from './utils';
import { PackCard } from 'app/modules/pack';
import { type CardType } from '@packrat/ui';
import { useAddFavorite } from 'app/modules/feed';
import { useAuthUser } from 'app/modules/auth';

const convertersByType = {
pack: feedItemPackCardConverter,
};

const cardComponentsByType = {
pack: PackCard,
};

interface FeedCardProps {
feedType: FeedType;
cardType: CardType;
item: FeedItem;
}

export const FeedCard: FC<FeedCardProps> = ({ item, cardType, feedType }) => {
const { addFavorite } = useAddFavorite();
const user = useAuthUser();
const cardProps =
typeof convertersByType[feedType] === 'function'
? convertersByType[feedType](item, user?.id)
: null;

const handleAddToFavorite = () => {
if (!user) return;
const data = {
packId: item.id,
userId: user.id,
};

addFavorite(data);
};

if (!cardProps) {
return null;
}

const CardComponent = cardComponentsByType[feedType];

return (
<CardComponent
{...cardProps}
cardType={cardType}
toggleFavorite={handleAddToFavorite}
/>
);
};

/*
export function FeedCardOld({
type,
id,
owner,
name,
total_weight,
is_public,
favorited_by,
favorites_count,
owner_id,
destination,
createdAt,
owners,
duration,
itemPacks,
}: FeedCardProps) {
console.log('CardProps:', favorited_by);
const user = useAuthUser();
const { currentTheme } = useTheme();
const { addFavorite } = useAddFavorite();
const [weightUnit] = useItemWeightUnit();
const router = useRouter();
const isFavorite =
type !== 'trip' &&
favorited_by?.some((obj) => obj?.['userId'] === user?.id && user?.id);
const handleAddToFavorite = () => {
if (!user) return;
const data = {
packId: id,
userId: user.id,
};
addFavorite(data);
};
const truncatedName = truncateString(name, 25);
const truncatedDestination = truncateString(destination, 25);
const formattedWeight = convertWeight(total_weight, 'g', weightUnit);
const quantity =
itemPacks?.reduce(
(accumulator, currentValue) => accumulator + currentValue?.item?.quantity,
0,
) ?? 0;
let numberOfNights;
if (duration) numberOfNights = JSON.parse(duration).numberOfNights;
return (
<Layout>
<XStack flexWrap="wrap" space="$4" padding="$4" style={{ width: '100%' }}>
<Card
elevate
size="$4"
backgroundColor={currentTheme.colors.card}
borderWidth={0} // Remove border
padding="$4"
width="100%"
height={300}
>
<ContextMenu.Root>
<ContextMenu.Trigger>
<YStack space="$4">
<Card.Header>
<H2>
<RLink
href={type === 'pack' ? '/pack/' + id : '/trip/' + id}
style={{ textDecoration: 'none' }}
>
<RText
fontSize={18}
color={currentTheme.colors.tertiaryBlue}
>
{truncatedName}
</RText>
</RLink>
</H2>
<XStack space="$2" alignItems="center">
{type === 'pack' && (
<XStack alignItems="center" space="$2">
<MaterialIcons
name="backpack"
size={24}
color={currentTheme.colors.cardIconColor}
/>
<DuplicateIcon link={`/pack/${id}?copy=true`} />
</XStack>
)}
{type === 'trip' && (
<Entypo
name="location-pin"
size={24}
color={currentTheme.colors.cardIconColor}
/>
)}
</XStack>
</Card.Header>
{type === 'pack' && (
<>
<Paragraph theme="alt2">
Total Weight: {formatNumber(formattedWeight)} {weightUnit}
</Paragraph>
<Paragraph theme="alt2">
Total Quantity: {quantity}
</Paragraph>
</>
)}
{type === 'trip' && (
<Paragraph theme="alt2">{truncatedDestination}</Paragraph>
)}
<Card.Footer>
<YStack flex={1} justifyContent="flex-end">
<XStack
justifyContent="space-between"
alignItems="center"
flexDirection="row"
>
<YStack>
<RLink
href={`/profile/${owner_id}`}
style={{ textDecoration: 'none' }}
>
<RText
color={currentTheme.colors.text}
style={{ marginRight: 8 }}
>
View{' '}
{owner?.username ? '@' + owner?.username : 'Owner'}
</RText>
</RLink>
<Paragraph theme="alt2">
{formatDistanceToNow(new Date(createdAt), {
addSuffix: true,
})}
</Paragraph>
</YStack>
{type === 'pack' && (
<XStack alignItems="center" space="$2">
<TouchableOpacity onPress={handleAddToFavorite}>
<AntDesign
name="heart"
size={16}
color={
isFavorite
? 'red'
: currentTheme.colors.cardIconColor
}
/>
</TouchableOpacity>
<RText fontSize="$2" color={currentTheme.colors.text}>
{favorites_count}
</RText>
</XStack>
)}
{type === 'trip' && (
<YStack alignItems="center" space="$2">
<RText
fontSize="$2"
color={currentTheme.colors.tertiaryBlue}
>
Nights
</RText>
<RText
fontSize="$2"
color={currentTheme.colors.tertiaryBlue}
>
{numberOfNights}
</RText>
</YStack>
)}
</XStack>
</YStack>
</Card.Footer>
</YStack>
</ContextMenu.Trigger>
<ContextMenu.Content>
<ContextMenu.Item
textValue={`View ${type}`}
key="view"
onSelect={() => {
router.push(type === 'pack' ? '/pack/' + id : '/trip/' + id);
}}
>
<ContextMenu.ItemTitle>View {type}</ContextMenu.ItemTitle>
</ContextMenu.Item>
<ContextMenu.Item
textValue={`View owner`}
key="owner"
onSelect={() => {
router.push(`/profile/${owner_id}`);
}}
>
<ContextMenu.ItemTitle>View Owner</ContextMenu.ItemTitle>
</ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Root>
</Card>
</XStack>
</Layout>
);
}
*/
1 change: 1 addition & 0 deletions packages/app/modules/feed/components/FeedCard/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { FeedCard } from './FeedCard';
40 changes: 40 additions & 0 deletions packages/app/modules/feed/components/FeedCard/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { type FeedCardProps, type FeedItem } from 'modules/feed/model';
import { formatDistanceToNowStrict } from 'date-fns';
import { type PackDetails } from 'app/modules/pack';
import { truncateString } from 'app/utils/truncateString';

type Converter<Input, Result> = (
input: Input,
currentUserId?: string | number,
) => Result;

export const feedItemPackCardConverter: Converter<
FeedItem,
Omit<FeedCardProps<PackDetails>, 'cardType' | 'toggleFavorite'>
> = (input, currentUserId) => {
return {
id: input.id,
createdAt: formatDistanceToNowStrict(new Date(input.createdAt), {
addSuffix: false,
}),
title: truncateString(input.name, 25),
ownerId:
typeof input.owner_id === 'string'
? input.owner_id
: input.owner_id?.id || '',
details: {
score: input.total_score,
weight: input.total_weight,
quantity:
input?.itemPacks?.reduce(
(accumulator, currentValue) =>
accumulator + currentValue?.item?.quantity,
0,
) ?? 0,
},
isUserFavorite: input?.userFavoritePacks?.some(
(obj) => obj?.userId === currentUserId,
),
favoriteCount: input.favorites_count,
};
};
25 changes: 25 additions & 0 deletions packages/app/modules/feed/hooks/useAddFavorite.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { queryTrpc } from 'app/trpc';

export function useAddFavorite() {
const utils = queryTrpc.useContext();

const mutation = queryTrpc.addToFavorite.useMutation();

// A wrapper function to abstract away the .mutate call
const addFavorite = (newFavorite, userId?: string) => {
mutation.mutate(newFavorite, {
onSuccess: () => {
// Invalidate and refetch. Update to be more specific
utils.getUserFavorites.invalidate();
utils.getPublicPacks.invalidate();
utils.getPacks.invalidate(userId ? { ownerId: userId } : undefined);
},
});
};

// Return the wrapper function and any other data or functions you might need
return {
addFavorite,
...mutation, // This spreads in other properties like isLoading, isError, etc.
};
}
17 changes: 17 additions & 0 deletions packages/app/modules/feed/hooks/useFetchUserFavorites.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { queryTrpc } from 'app/trpc';

export const useFetchUserFavorites = (userId: string) => {
const enabled = !!userId;

const { data, error, isLoading, refetch } =
queryTrpc.getUserFavorites.useQuery(
{ userId },
{
enabled,
refetchOnWindowFocus: false,
keepPreviousData: true,
},
);

return { data, error, isLoading, enabled, refetch };
};
Loading

0 comments on commit e1300cd

Please sign in to comment.