Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/(tabs)/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default function TabLayout() {
}, []);

return (
<SafeAreaView edges={["top"]} style={{ flex: 1 }}>
<SafeAreaView edges={["top"]} style={{ flex: 1 }} className="bg-main-color2">
<Tabs screenOptions={screenOptions}>
<Tabs.Screen
name="home"
Expand Down
4 changes: 3 additions & 1 deletion pages/archive/ArchivePage.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { FeedHeader } from "@/shared/ui/header";
import React from "react";
import { View, Text } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";

export default function ArchivePage() {
return (
<SafeAreaView className="flex-1 bg-white">
<SafeAreaView className="flex-1 bg-background-color" edges={["left", "right", "bottom"]}>
<FeedHeader />
<View className="items-center mb-10">
<Text className="">아카이브</Text>
</View>
Expand Down
2 changes: 1 addition & 1 deletion pages/awards/AwardsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { SafeAreaView } from "react-native-safe-area-context";

export default function AwardsPage() {
return (
<SafeAreaView className="flex-1 bg-white">
<SafeAreaView className="flex-1 bg-background-color" edges={["left", "right", "bottom"]}>
<View className="items-center mb-10">
<Text className="">어워드</Text>
</View>
Expand Down
6 changes: 3 additions & 3 deletions pages/home/HomePage.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from "react";
import { Text, TouchableOpacity } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import { useRouter } from "expo-router";
import { useAuth } from "../../features/auth/model/AuthContext";
import { HomeHeader } from "@/shared/ui/header";

export default function HomePage() {
const { logout } = useAuth();
Expand All @@ -14,8 +14,8 @@ export default function HomePage() {
};

return (
<SafeAreaView className="flex-1 bg-white">
{/* 로그아웃 버튼 */}
<SafeAreaView className="flex-1 bg-white" edges={["left", "right", "bottom"]}>
<HomeHeader />
<TouchableOpacity className="bg-red-400 p-4 items-center" onPress={handleLogout}>
<Text className="text-white">로그아웃 버튼</Text>
</TouchableOpacity>
Expand Down
5 changes: 3 additions & 2 deletions pages/profile/ProfilePage.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import React from "react";
import { View, Text } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import { useAuth } from "../../features/auth/model/AuthContext";
import { SearchHeader } from "@/shared/ui/header";

export default function ProfilePage() {
const { userInfo } = useAuth();

return (
<SafeAreaView className="flex-1 bg-white">
<SafeAreaView className="flex-1 bg-background-color" edges={["left", "right", "bottom"]}>
<SearchHeader />
<View className="items-center mb-10">
<Text>{userInfo?.nickname || "사용자 닉네임"}</Text>
<Text>{userInfo?.email || "이메일 없음"}</Text>
Expand Down
5 changes: 3 additions & 2 deletions pages/upload/UploadPage.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React from "react";
import { View, Text } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import { UploadHeader } from "@/shared/ui/header";

export default function UploadPage() {
return (
<SafeAreaView className="flex-1 bg-white">
<SafeAreaView className="flex-1 bg-background-color" edges={["left", "right", "bottom"]}>
<UploadHeader />
<View className="items-center mb-10">
<Text className="">업로드</Text>
</View>
Expand Down
8 changes: 8 additions & 0 deletions shared/assets/icons/attend.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions shared/assets/icons/back.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions shared/assets/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ export { default as archiving_active } from "./archiving_active.svg";
export { default as uploading_active } from "./uploading_active.svg";
export { default as ranking_active } from "./ranking_active.svg";
export { default as my_active } from "./my_active.svg";
export { default as back } from "./back.svg";
export { default as more } from "./more.svg";
export { default as attend } from "./attend.svg";
export { default as logo } from "./logo.svg";
3 changes: 3 additions & 0 deletions shared/assets/icons/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions shared/assets/icons/more.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 2 additions & 3 deletions shared/assets/icons/search.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions shared/ui/header/CommonHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { View } from "react-native";

export interface HeaderProps {
left?: React.ReactNode;
center?: React.ReactNode;
right?: React.ReactNode;
}

export default function CommonHeader({ left, center, right }: HeaderProps) {
return (
<View className="bg-main-color2 rounded-b-[16px] w-full">
<View className="flex-row items-center justify-between px-6 h-[56px]">
{/* 왼쪽 아이템 */}
<View className="items-center justify-center">{left ?? <View className="w-6 h-6" />}</View>

{/* 가운데 아이템 */}
<View className="flex-1 items-center justify-center mt-2">{center}</View>

{/* 오른쪽 아이템 */}
<View className="items-center justify-center">{right ?? <View className="w-6 h-6" />}</View>
</View>
</View>
);
}
5 changes: 5 additions & 0 deletions shared/ui/header/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export { default as CommonHeader } from "./CommonHeader";
export { default as HomeHeader } from "./variants/HomeHeader";
export { default as FeedHeader } from "./variants/FeedHeader";
export { default as UploadHeader } from "./variants/UploadHeader";
export { default as SearchHeader } from "./variants/SearchHeader";
16 changes: 16 additions & 0 deletions shared/ui/header/items/AttendButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Pressable, Text } from "react-native";
import { Icon } from "@/shared/ui/icon";

interface AttendButtonProps {
onPress?: () => void;
}

// Todo: api연결해서 몇 일 연속 출석인지 표시
export default function AttendButton({ onPress }: AttendButtonProps) {
return (
<Pressable onPress={onPress} className="mr-4 flex-row items-center">
<Icon name="attend" width={24} height={24} />
<Text className="text-main-color1 text-sm ml-2">34</Text>
</Pressable>
);
}
13 changes: 13 additions & 0 deletions shared/ui/header/items/BackButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Pressable } from "react-native";
import { useRouter } from "expo-router";
import { Icon } from "@/shared/ui/icon";

export default function BackButton() {
const router = useRouter();

return (
<Pressable onPress={() => router.back()} hitSlop={8}>
<Icon name="back" width={24} height={24} />
</Pressable>
);
}
5 changes: 5 additions & 0 deletions shared/ui/header/items/Logo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Icon } from "@/shared/ui/icon";

export default function Logo() {
return <Icon name="logo" width={34} height={34} />;
}
14 changes: 14 additions & 0 deletions shared/ui/header/items/MoreButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Pressable } from "react-native";
import { Icon } from "@/shared/ui/icon";

interface MoreButtonProps {
onPress?: () => void;
}

export default function MoreButton({ onPress }: MoreButtonProps) {
return (
<Pressable onPress={onPress} hitSlop={8}>
<Icon name="more" width={24} height={24} />
</Pressable>
);
}
14 changes: 14 additions & 0 deletions shared/ui/header/items/SearchButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Pressable } from "react-native";
import { Icon } from "@/shared/ui/icon";

interface SearchButtonProps {
onPress?: () => void;
}

export default function SearchButton({ onPress }: SearchButtonProps) {
return (
<Pressable onPress={onPress} hitSlop={8}>
<Icon name="search" width={24} height={24} />
</Pressable>
);
}
15 changes: 15 additions & 0 deletions shared/ui/header/items/TodayKeyword.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Text, View } from "react-native";

interface TodayKeywordProps {
dateString?: string;
title: string;
}

export default function TodayKeyword({ title, dateString }: TodayKeywordProps) {
return (
<View className="flex-1 items-center">
{dateString && <Text className="text-[8px] text-main-color1">{dateString}</Text>}
<Text className="text-[24px] font-semibold text-main-color1">{title}</Text>
</View>
);
}
14 changes: 14 additions & 0 deletions shared/ui/header/variants/FeedHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import CommonHeader from "../CommonHeader";
import BackButton from "../items/BackButton";
import TodayKeyword from "../items/TodayKeyword";
import MoreButton from "../items/MoreButton";

export default function FeedHeader() {
return (
<CommonHeader
left={<BackButton />}
center={<TodayKeyword title="피드 테스트" dateString="2025.08.06" />}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

하드코딩된 테스트 데이터를 동적 데이터로 교체해주세요.

현재 "피드 테스트"와 "2025.08.06" 값이 하드코딩되어 있습니다. 실제 데이터나 props를 통해 전달받도록 개선이 필요합니다.

-export default function FeedHeader() {
+export default function FeedHeader({ title, dateString }: { title?: string; dateString?: string }) {
   return (
     <CommonHeader
       left={<BackButton />}
-      center={<TodayKeyword title="피드 테스트" dateString="2025.08.06" />}
+      center={<TodayKeyword title={title || "피드"} dateString={dateString} />}
       right={<MoreButton />}
     />
   );
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
center={<TodayKeyword title="피드 테스트" dateString="2025.08.06" />}
export default function FeedHeader({
title,
dateString,
}: {
title?: string
dateString?: string
}) {
return (
<CommonHeader
left={<BackButton />}
center={<TodayKeyword title={title || "피드"} dateString={dateString} />}
right={<MoreButton />}
/>
)
}
🤖 Prompt for AI Agents
In shared/ui/header/variants/FeedHeader.tsx at line 10, the TodayKeyword
component uses hardcoded values "피드 테스트" and "2025.08.06". Replace these static
strings with dynamic data by passing appropriate props or state values to
FeedHeader, then forwarding them to TodayKeyword to make the component
data-driven.

right={<MoreButton />}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

MoreButton에 onPress 핸들러가 누락되었습니다.

MoreButton 컴포넌트는 onPress prop을 필요로 하는데 현재 전달되지 않고 있습니다.

-      right={<MoreButton />}
+      right={<MoreButton onPress={() => {/* TODO: 더보기 기능 구현 */}} />}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
right={<MoreButton />}
right={<MoreButton onPress={() => {/* TODO: 더보기 기능 구현 */}} />}
🤖 Prompt for AI Agents
In shared/ui/header/variants/FeedHeader.tsx at line 11, the MoreButton component
is missing the required onPress handler prop. Add an onPress prop to the
MoreButton component with an appropriate handler function to handle the press
event.

/>
);
}
20 changes: 20 additions & 0 deletions shared/ui/header/variants/HomeHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import CommonHeader from "../CommonHeader";
import Logo from "../items/Logo";
import SearchButton from "../items/SearchButton";
import AttendButton from "../items/AttendButton";
import { View } from "react-native";

export default function HomeHeader() {
return (
<CommonHeader
left={<Logo />}
center={null}
right={
<View className="flex-row items-center">
<AttendButton />
<SearchButton />
</View>
}
/>
);
}
15 changes: 15 additions & 0 deletions shared/ui/header/variants/SearchHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import CommonHeader from "../CommonHeader";
import BackButton from "../items/BackButton";
import SearchButton from "../items/SearchButton";
import TodayKeyword from "../items/TodayKeyword";

export default function SearchHeader() {
return (
<CommonHeader
left={<BackButton />}
//Todo: 검색 페이지 디자인에 따라 UI 수정 + api 연결
center={<TodayKeyword title="검색 테스트" />}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

하드코딩된 테스트 데이터를 개선해주세요.

"검색 테스트"가 하드코딩되어 있습니다. props를 통해 동적으로 전달받거나 적절한 기본값을 사용하는 것이 좋겠습니다.

-export default function SearchHeader() {
+export default function SearchHeader({ title }: { title?: string }) {
   return (
     <CommonHeader
       left={<BackButton />}
       //Todo: 검색 페이지 디자인에 따라 UI 수정 + api 연결
-      center={<TodayKeyword title="검색 테스트" />}
+      center={<TodayKeyword title={title || "검색"} />}
       right={<SearchButton />}
     />
   );
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
center={<TodayKeyword title="검색 테스트" />}
export default function SearchHeader({ title }: { title?: string }) {
return (
<CommonHeader
left={<BackButton />}
//Todo: 검색 페이지 디자인에 따라 UI 수정 + api 연결
center={<TodayKeyword title={title || "검색"} />}
right={<SearchButton />}
/>
);
}
🤖 Prompt for AI Agents
In shared/ui/header/variants/SearchHeader.tsx at line 11, the string "검색 테스트" is
hardcoded as a title prop for TodayKeyword. Modify the component to accept this
title as a prop so it can be passed dynamically, and provide a sensible default
value if no prop is given to avoid hardcoding.

right={<SearchButton />}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

SearchButton에 onPress 핸들러가 누락되었습니다.

SearchButton 컴포넌트는 onPress prop을 필요로 합니다.

-      right={<SearchButton />}
+      right={<SearchButton onPress={() => {/* TODO: 검색 기능 구현 */}} />}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
right={<SearchButton />}
right={<SearchButton onPress={() => { /* TODO: 검색 기능 구현 */ }} />}
🤖 Prompt for AI Agents
In shared/ui/header/variants/SearchHeader.tsx at line 12, the SearchButton
component is missing the required onPress handler prop. Add an onPress prop to
the SearchButton component, passing a function that handles the press event
appropriately.

/>
);
}
12 changes: 12 additions & 0 deletions shared/ui/header/variants/UploadHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import CommonHeader from "../CommonHeader";
import BackButton from "../items/BackButton";
import TodayKeyword from "../items/TodayKeyword";

export default function UploadHeader() {
return (
<CommonHeader
left={<BackButton />}
center={<TodayKeyword title="고양이" dateString="2025.08.06" />}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

하드코딩된 값들을 동적으로 변경해야 합니다.

TodayKeyword의 title="고양이"와 dateString="2025.08.06"이 하드코딩되어 있습니다. 이는 테스트 값으로 보이며, 실제 업로드 컨텍스트나 현재 날짜를 기반으로 동적으로 설정되어야 합니다.

다음과 같이 수정을 고려해보세요:

-export default function UploadHeader() {
+interface UploadHeaderProps {
+  title: string;
+  dateString?: string;
+}
+
+export default function UploadHeader({ title, dateString }: UploadHeaderProps) {
   return (
     <CommonHeader
       left={<BackButton />}
-      center={<TodayKeyword title="고양이" dateString="2025.08.06" />}
+      center={<TodayKeyword title={title} dateString={dateString} />}
     />
   );
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
center={<TodayKeyword title="고양이" dateString="2025.08.06" />}
interface UploadHeaderProps {
title: string;
dateString?: string;
}
export default function UploadHeader({ title, dateString }: UploadHeaderProps) {
return (
<CommonHeader
left={<BackButton />}
center={<TodayKeyword title={title} dateString={dateString} />}
/>
);
}
🤖 Prompt for AI Agents
In shared/ui/header/variants/UploadHeader.tsx at line 9, the TodayKeyword
component uses hardcoded values for title and dateString. Replace these static
values with dynamic props or state values that reflect the actual upload context
or current date. For example, pass the title and dateString as props to
UploadHeader or compute the current date string dynamically to ensure the
component displays relevant and up-to-date information.

/>
);
}
9 changes: 7 additions & 2 deletions tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,13 @@ module.exports = {
"./shared/**/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {},
extend: {
colors: {
"main-color1": "#195B35",
"main-color2": "#FFFDF5",
"background-color": "#232323",
},
},
},
plugins: [],
};