Skip to content

Commit

Permalink
feature: [피드 조회] 게시글 카드 컴포넌트 (#58)
Browse files Browse the repository at this point in the history
* feat: 피드 article 레이아웃 구현

* refactor: 컴포넌트명 컨밴션에 맞게 변경& Tpye 파스칼케이스로 변경

* feat: 피드 출력 컴포넌트 구현

* feat: 피드 게시물 컴포넌트 분리

* feat: 피드 사진 이미지 스크롤 구현
- react-native-swiper 모듈 추가

* refactor: 컴포넌트 분리
- state변경 시 깜빡거리는 문제 해결

* feat: 피드 클릭시 화면 이동 추가

* refactor: 클릭 에니메이션 수정

* refactor: 스티치 리뷰 적용
- Dot.tsx, ActiveDot.tsx 제거
- 한줄짜리 람다식 간소화 형식으로 변경
- package.json 에서 불필요한 recompose 타입 모듈 제거
- 메소드 네이밍 변경
- 메소드로 분리 할 필요가 있는 로직 메소드로 분리해서 추상화

* refactor: 터틀 리뷰 적용
- Dot.tsx, ActiveDot.tsx 생성
- 불필요한 css 요소 제거
- 매직넘버 상수화

* refactor: 네이밍 수정

* refactor: 네이밍 수정

* refactor: 네이밍 수정
- determineFavorite -> toggleFavorite

* refactor: 패키지 변경
  • Loading branch information
joseph415 authored Jul 28, 2020
1 parent 54fd93c commit f92f09b
Show file tree
Hide file tree
Showing 28 changed files with 7,787 additions and 42 deletions.
Binary file added front/assets/samplePhoto1.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added front/assets/samplePhoto2.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions front/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"react-native-reanimated": "~1.9.0",
"react-native-safe-area-context": "~3.0.7",
"react-native-screens": "~2.9.0",
"react-native-swiper": "^1.6.0",
"react-native-web": "~0.11.7",
"recoil": "^0.0.10"
},
Expand Down
23 changes: 23 additions & 0 deletions front/src/components/ActiveDot.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* @author joseph415
*/

import React from "react";
import { StyleSheet, View } from "react-native";

export default function ActiveDot() {
return <View style={styles.activeDot} />;
}

const styles = StyleSheet.create({
activeDot: {
backgroundColor: "#eeecda",
width: 8,
height: 8,
borderRadius: 4,
marginLeft: 3,
marginRight: 3,
marginTop: 3,
marginBottom: 3,
},
});
4 changes: 4 additions & 0 deletions front/src/components/ArticleAuthor.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* @author lxxjn0
*/

import React from "react";
import { StyleSheet, View } from "react-native";
import AuthorAvatar from "./AuthorAvatar";
Expand Down
4 changes: 4 additions & 0 deletions front/src/components/AuthorAvatar.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* @author lxxjn0
*/

import React from "react";
import { Image, StyleSheet, View } from "react-native";
import { AuthorAvatarType } from "../types/types";
Expand Down
4 changes: 4 additions & 0 deletions front/src/components/AuthorName.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* @author lxxjn0
*/

import React from "react";
import { View, Text, StyleSheet } from "react-native";

Expand Down
4 changes: 4 additions & 0 deletions front/src/components/AuthorScore.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* @author lxxjn0
*/

import React from "react";
import { StyleSheet, Text, View } from "react-native";
import { MaterialCommunityIcons } from "@expo/vector-icons";
Expand Down
4 changes: 4 additions & 0 deletions front/src/components/AuthorTheCheat.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* @author lxxjn0
*/

import React from "react";
import { StyleSheet, Text, TouchableOpacity } from "react-native";
import { MaterialCommunityIcons } from "@expo/vector-icons";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type ArticleAdditional = {
chatCount: number;
};

export interface ArticleCardProps {
export interface CategoryArticleCardProps {
title: string;
price: number;
createdAt: string;
Expand All @@ -26,14 +26,14 @@ export interface ArticleCardProps {
thumbnail: ImageProps;
}

export default function ArticleCard({
export default function CategoryArticleCard({
title,
price,
createdAt,
detail,
additional,
thumbnail,
}: ArticleCardProps) {
}: CategoryArticleCardProps) {
return (
<View style={styles.container}>
<View style={styles.imageContainer}>
Expand Down
4 changes: 2 additions & 2 deletions front/src/components/CategoryNavigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import { createStackNavigator } from "@react-navigation/stack";
import CategoryHomeScreen from "../screens/CategoryHomeScreen";
import CategoryDetailScreen from "../screens/CategoryDetailScreen";
import SearchScreen from "../screens/SearchScreen";
import { categoryParamList } from "../types/types";
import { CategoryParamList } from "../types/types";

const Stack = createStackNavigator<categoryParamList>();
const Stack = createStackNavigator<CategoryParamList>();

export default function CategoryNavigation() {
return (
Expand Down
14 changes: 0 additions & 14 deletions front/src/components/DemoArticle.tsx

This file was deleted.

23 changes: 23 additions & 0 deletions front/src/components/Dot.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* @author joseph415
*/

import React from "react";
import { StyleSheet, View } from "react-native";

export default function Dot() {
return <View style={styles.dot} />;
}

const styles = StyleSheet.create({
dot: {
backgroundColor: "rgba(0,0,0,.2)",
width: 5,
height: 5,
borderRadius: 4,
marginLeft: 3,
marginRight: 3,
marginTop: 3,
marginBottom: 3,
},
});
76 changes: 76 additions & 0 deletions front/src/components/Favorite.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/**
* @author joesph415
*/

import React, { useRef, useState } from "react";
import { Animated, StyleSheet, Text, View } from "react-native";
import { AntDesign } from "@expo/vector-icons";
import { FeedArticle } from "../types/types";

export default function Favorite({ feedArticle }: FeedArticle) {
const [isFavorite, setIsFavorite] = useState(false);
const [favorite, setFavorite] = useState(feedArticle.favorite);
const AnimateIcon = Animated.createAnimatedComponent(AntDesign);

const springValue = useRef(new Animated.Value(1)).current;

const fulfillHeartAnimate = () => {
springValue.setValue(0.33);
Animated.timing(springValue, {
toValue: 1,
duration: 150,
useNativeDriver: true,
}).start();
};

const toggleFavorite = () => {
const unmarkFavorite = () => {
setIsFavorite(false);
setFavorite(favorite - 1);
};

const markFavorite = () => {
setIsFavorite(true);
setFavorite(favorite + 1);
};

if (isFavorite) {
unmarkFavorite();
} else {
markFavorite();
}
fulfillHeartAnimate();
};

return (
<View style={styles.detailsHeartContainer}>
<AnimateIcon
name={isFavorite ? "heart" : "hearto"}
size={23}
color={isFavorite ? "red" : "black"}
onPress={toggleFavorite}
style={{
transform: [{ scale: springValue }],
}}
/>
<Text
onPress={() => {
// do nothing
}}
style={styles.text}
>
{" "}
x {favorite}
</Text>
</View>
);
}

const styles = StyleSheet.create({
detailsHeartContainer: {
flexDirection: "row",
flex: 1,
alignItems: "center",
},
text: { fontWeight: "bold" },
});
135 changes: 135 additions & 0 deletions front/src/components/FeedArticleCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/**
* @author joseph415
*/

import React, { useRef } from "react";
import {
Animated,
StyleSheet,
Text,
TouchableWithoutFeedback,
View,
} from "react-native";
import {
FeedArticle,
FeedNavigationProp,
PhotoInfo,
Tag,
} from "../types/types";
import FeedArticleTag from "./FeedArticleTag";
import Favorite from "./Favorite";
import FeedSliderImage from "./FeedSliderImage";
import { useNavigation } from "@react-navigation/native";
import { insertComma } from "../replacePriceWithComma";

const ANIMATE_START_VALUE = 0.93;

interface FeedArticleCardProps {
id: number;
price: string;
tagBoxes: Tag[];
favorite: number;
photos: PhotoInfo[];
}

export default function FeedArticleCard({ feedArticle }: FeedArticle) {
const navigation = useNavigation<FeedNavigationProp>();

const AnimateTouchableWithoutFeedback = Animated.createAnimatedComponent(
TouchableWithoutFeedback,
);

const clickValue = useRef(new Animated.Value(1)).current;

const clickArticleAnimate = () => {
clickValue.setValue(ANIMATE_START_VALUE);

Animated.timing(clickValue, {
toValue: 1,
duration: 150,
useNativeDriver: true,
}).start();
};

return (
<AnimateTouchableWithoutFeedback
onPress={() => {
clickArticleAnimate();
navigation.navigate("FeedArticle");
}}
style={{ transform: [{ scale: clickValue }] }}
>
<View style={styles.articleContainer}>
<View style={styles.photoContainer}>
<FeedSliderImage feedArticle={feedArticle} />
</View>
<View style={styles.articleSemiDetailsContainer}>
<View style={styles.detailsContainer}>
<Favorite feedArticle={feedArticle} />
<View style={styles.detailsPriceContainer}>
<Text style={styles.text}>
{insertComma(feedArticle.price)}
</Text>
</View>
</View>
<View style={styles.tagContainer}>
{feedArticle.tagBoxes.map((tagItem) => (
<FeedArticleTag key={tagItem.id} tagBox={tagItem} />
))}
</View>
</View>
</View>
</AnimateTouchableWithoutFeedback>
);
}

const styles = StyleSheet.create({
articleContainer: {
marginHorizontal: 4,
backgroundColor: "#FFF",
paddingVertical: 15,
borderRadius: 8,
aspectRatio: 4 / 3,
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 1,
},
shadowOpacity: 0.22,
shadowRadius: 2.22,

elevation: 6,
},
photoContainer: {
paddingHorizontal: 8,
flex: 3,
},
pagination: {
bottom: 15,
},
articleSemiDetailsContainer: {
flex: 1.3,
},
detailsContainer: {
flexDirection: "row",
flex: 1,
paddingHorizontal: 8,
},
detailsHeartContainer: {
flexDirection: "row",
flex: 1,
alignItems: "center",
},
text: { fontWeight: "bold" },
detailsPriceContainer: {
flex: 1,
justifyContent: "center",
alignItems: "flex-end",
},
tagContainer: {
flex: 1,
flexDirection: "row",
alignItems: "center",
paddingHorizontal: 8,
},
});
31 changes: 31 additions & 0 deletions front/src/components/FeedArticleTag.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* @author joseph415
*/

import React from "react";
import { StyleSheet, Text, View } from "react-native";
import { TagItemProps } from "../types/types";

export default function FeedArticleTag({ tagBox }: TagItemProps) {
return (
<View style={styles.tagItem}>
<View style={styles.tagItemTextWrapper}>
<Text>{tagBox.tag}</Text>
</View>
</View>
);
}

const styles = StyleSheet.create({
tagItem: {
flexDirection: "row",
alignItems: "center",
height: "80%",
marginRight: 5,
borderRadius: 10,
backgroundColor: "#eeecda",
},
tagItemTextWrapper: {
paddingHorizontal: 3,
},
});
Loading

0 comments on commit f92f09b

Please sign in to comment.