Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
56e14d4
fix: Fast Friend API 필드 수정
Soohyuniii Apr 3, 2025
78b0650
Merge pull request #128 from Soohyuniii/fix/fast-friend-api-field
Soohyuniii Apr 6, 2025
2159df3
feat: 내 정보 화면 리스트 개발
Soohyuniii Apr 7, 2025
d5e14e9
feat: chat room UI 개발
Soohyuniii Apr 7, 2025
b58a146
Merge pull request #145 from Soohyuniii/feat/내정보화면의-리스트화면-개발
Soohyuniii Apr 7, 2025
026380f
fix: rename ChatAction
Soohyuniii Apr 8, 2025
973dfa7
Merge branch 'dev' of https://github.com/MBTips/FE-MBTips into feat/채…
Soohyuniii Apr 8, 2025
3440b17
Merge pull request #149 from Soohyuniii/feat/채팅-UI-개발
Soohyuniii Apr 8, 2025
41ce066
feat: cicd 설정
Soohyuniii Apr 8, 2025
0af889c
Merge pull request #153 from Soohyuniii/feature/cicd-설정-수정내용-반영
Soohyuniii Apr 8, 2025
6e75a4d
배포 운영환경 설정
Apr 8, 2025
f0f2904
빌드명령어 수정
Apr 8, 2025
850eb16
ci 파일생성
Apr 8, 2025
507c5fd
Merge branch 'dev' into feat/cicd
yhj0214 Apr 8, 2025
0c931a6
Merge pull request #155 from MBTips/feat/cicd
Soohyuniii Apr 8, 2025
80a02fe
fix: GA4 설정 변경
Soohyuniii Apr 8, 2025
ea00a47
Merge branch 'dev' of https://github.com/MBTips/FE-MBTips into fix/GA…
Soohyuniii Apr 8, 2025
fbbe71b
Merge pull request #156 from Soohyuniii/fix/GA4-설정-변경
Soohyuniii Apr 8, 2025
b59da9c
Merge branch 'main' of https://github.com/MBTips/FE-MBTips into dev
Soohyuniii Apr 8, 2025
d083552
test: name test
Soohyuniii Apr 8, 2025
af7abea
fix: remove test
Soohyuniii Apr 8, 2025
1a2d7f8
Merge pull request #158 from Soohyuniii/dev
Soohyuniii Apr 8, 2025
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
35 changes: 4 additions & 31 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ name: 빌드 자동화
on:
push:
branches:
- main
- feat/cicd
- dev

jobs:
build:
Expand All @@ -14,39 +13,13 @@ jobs:
- name: Checkout code
uses: actions/checkout@v2

- name: Set up Node.js (언어 환경)
- name: Set up Node.js (또는 다른 언어 환경)
uses: actions/setup-node@v2
with:
node-version: "20"

- name: Create .env.production file
run: |
echo "MODE=production" > .env.production
echo "VITE_GA_MEASUREMENT_ID=${{ secrets.VITE_GA_MEASUREMENT_ID }}" >> .env.production

- name: Install dependencies
run: npm ci
run: npm install

- name: Run build
env:
NODE_ENV: production
run: npm run build -- --mode production

- name: Docker build & push
run: |
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
docker build -t ${{ secrets.DOCKER_USERNAME }}/embitips_front .
docker push ${{ secrets.DOCKER_USERNAME }}/embitips_front

- name: Deploy to GCP
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOST_PROD }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.PRIVATE_KEY }}
script: |
sudo docker stop embitips_front || true
sudo docker rm embitips_front || true
sudo docker pull ${{ secrets.DOCKER_USERNAME }}/embitips_front
sudo docker run -d -p 3000:3000 --name embitips_front ${{ secrets.DOCKER_USERNAME }}/embitips_front
sudo docker image prune -f
run: npm run build
52 changes: 52 additions & 0 deletions .github/workflows/cicd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: 빌드 자동화

on:
push:
branches:
- main
- feat/cicd

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Set up Node.js (언어 환경)
uses: actions/setup-node@v2
with:
node-version: "20"

- name: Install dependencies
run: |
npm install
npm install tailwindcss@latest postcss@latest autoprefixer@latest
npm install --save-dev @types/node

- name: Create .env file # env 파일 생성 단계 추가
run: |
echo "VITE_GA_MEASUREMENT_ID=${{ secrets.VITE_GA_MEASUREMENT_ID }}" > .env

- name: Run build
run: npm run build # 프로젝트에 맞는 빌드 명령어

- name: Docker build & push
run: |
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
docker build -t ${{ secrets.DOCKER_USERNAME }}/embitips_front .
docker push ${{ secrets.DOCKER_USERNAME }}/embitips_front

- name: Deploy to GCP
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOST_PROD }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.PRIVATE_KEY }}
script: |
sudo docker stop embitips_front || true
sudo docker rm embitips_front || true
sudo docker pull ${{ secrets.DOCKER_USERNAME }}/embitips_front
sudo docker run -d -p 3000:3000 --name embitips_front ${{ secrets.DOCKER_USERNAME }}/embitips_front
sudo docker image prune -f
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"build": "vite build --mode production",
"lint": "eslint .",
"preview": "vite preview",
"start": "vite --port 3000"
"start": "vite --port 3000 --mode production"
},
"dependencies": {
"@tailwindcss/vite": "^4.0.3",
Expand Down
40 changes: 30 additions & 10 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import ChatTips from "@/pages/ChatTips";
import ChatTemporature from "@/pages/ChatTemporature";
import Content from "@/pages/Content";
import Login from "@/pages/Login";
import MyInfo from "@/pages/MyInfo";
import KaKaoLogin from "@/pages/KaKaoLogin";
import MbtiTestIntro from "@/pages/MbtiTestIntro";
import MbtiTestQuestions from "@/pages/MbtiTestQuestions";
Expand All @@ -22,24 +23,42 @@ import { initGA, trackPageView } from "@/libs/analytics";

const PageTracker = () => {
const location = useLocation();
const { pathname, state } = location;

const trackedPaths = [
{ path: "/", label: "home" },
{ path: "/login", label: "login" },
{ path: "/contents" }
{ path: "/", page: "홈", element: "" },
{ path: "/login", page: "로그인/회원가입", element: "로그인" },
{ path: "/contents", page: "일반콘텐츠", element: "" },
{ path: "/my-info", page: "내 정보", element: "" },
{ path: "/chat", page: "채팅방", element: "" },
{ path: "/select-info", page: "빠른 대화 설정", element: "" },
{ path: "/select-info", page: "친구 저장", element: "대화 시작하기" }
];

useEffect(() => {
const { pathname } = location;
const trackedContentPaths = ["/contents/1", "/contents/2"];

trackedPaths.forEach(({ path, label }) => {
if (path === "/contents" && pathname.startsWith(path)) {
trackPageView(label || pathname);
} else if (pathname === path) {
trackPageView(label || pathname);
trackedPaths.forEach(({ path, page, element }) => {
// 콘텐츠 상세 페이지 (일반 콘텐츠만 추적)
if (trackedContentPaths.includes(pathname)) {
if (path === "/contents") {
trackPageView(path, { page, element });
}
}
// select-info 페이지에서 state로 분기
else if (pathname === "/select-info" && path === pathname) {
if (state === "fastFriend" && page === "빠른 대화 설정") {
trackPageView(path, { page, element });
} else if (state === "virtualFriend" && page === "친구 저장") {
trackPageView(path, { page, element });
}
}
// 나머지 일반 path
else if (pathname === path && path !== "/select-info") {
trackPageView(path, { page, element });
}
});
}, [location.pathname]);
}, [location.pathname, location.state]);

return null;
};
Expand All @@ -63,6 +82,7 @@ const App = () => {
<Route path="/chat-temporature" element={<ChatTemporature />} />
<Route path="/contents/:id" element={<Content />} />
<Route path="/login" element={<Login />} />
<Route path="/my-info" element={<MyInfo />} />
<Route path="/kakao-login" element={<KaKaoLogin />} />
<Route path="/mbti-test" element={<MbtiTestIntro />} />
<Route path="/mbti-test/:n" element={<MbtiTestQuestions />} />
Expand Down
28 changes: 0 additions & 28 deletions src/components/ChatAction.tsx

This file was deleted.

38 changes: 38 additions & 0 deletions src/components/ChatActionBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { ChangeEvent, KeyboardEvent } from "react";
import ToggleChatTipsButton from "@/components/button/ToggleChatTipsButton";
import MessageInput from "@/components/input/MessageInput";

interface ChatActionProps {
isOpen: boolean;
setIsOpen: (open: boolean) => void;
value: string;
onChange: (e: ChangeEvent<HTMLInputElement>) => void;
onKeyUp: (e: KeyboardEvent<HTMLInputElement>) => void;
onSend: () => void;
}

const ChatActionBar = ({
isOpen,
setIsOpen,
value,
onChange,
onKeyUp,
onSend
}: ChatActionProps) => {
return (
<div className="flex h-[68px] w-full items-center justify-center border-t border-gray-100 bg-white">
<ToggleChatTipsButton isOpen={isOpen} setIsOpen={setIsOpen} />
<MessageInput value={value} onChange={onChange} onKeyUp={onKeyUp} />
<img
className={`ml-4 ${value ? "cursor-pointer" : "cursor-not-allowed"}`}
onClick={onSend}
src={value ? "/icon/submit_action.svg" : "/icon/submit_disabled.svg"}
alt="메시지 제출"
width={40}
height={40}
/>
</div>
);
};

export default ChatActionBar;
4 changes: 2 additions & 2 deletions src/components/ChatMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ const ChatMessage = ({ message, myMessage }: ChatMessageProps) => {
: "rounded-tl-none border border-gray-100";

return (
<div className="flex w-full justify-center items-center mb-2">
<div className="mb-[6px]">
<div
className={`max-w-xs px-2.5 py-3 rounded-[12px] ${borderStyle} ${backgroundColor} ${textColor}`}
className={`max-w-xs rounded-[12px] px-2.5 py-3 ${borderStyle} ${backgroundColor} ${textColor}`}
style={{
fontWeight: 500,
fontSize: "16px",
Expand Down
8 changes: 4 additions & 4 deletions src/components/IntroGuide.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
const IntroGuide = () => {
return (
<div className="bg-white p-5 border border-primary-light rounded-xl">
<p className="font-light text-lg whitespace-pre-line">
<div className="rounded-xl border border-primary-light bg-white p-5 text-black">
<p className="text-md font-light whitespace-pre-line">
{`MBTI 대화에 참여하셨군요!
대화 상황에 대해 구체적으로
말씀해주시면,더 좋은 답변을 드릴 수 있어요 :)`}
</p>
<strong className="block mt-2 font-medium text-lg">
<p className="mt-2 block text-md font-medium">
언제, 어디서, 어떤 상황인지 자유롭게 알려주세요
</strong>
</p>
</div>
);
};
Expand Down
11 changes: 7 additions & 4 deletions src/components/input/MessageInput.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import { ChangeEvent } from "react";
import { ChangeEvent, KeyboardEvent } from "react";

interface MessageInputProps {
value: string;
onChange: (e: ChangeEvent<HTMLInputElement>) => void;
onKeyUp: (e: KeyboardEvent<HTMLInputElement>) => void;
}

const MessageInput = ({ value, onChange }: MessageInputProps) => {
const MessageInput = ({ value, onChange, onKeyUp }: MessageInputProps) => {
return (
<input
className="bg-gray-50 ml-2.5 px-4 py-2.5 rounded-[40px] w-[257px] h-[44px] font-medium text-2lg text-gray-900 placeholder:text-gray-600"
placeholder="메시지를 입력해주세요."
type="text"
className="ml-2.5 flex h-[44px] w-[242px] justify-center rounded-[40px] bg-gray-50 py-2.5 pl-4 text-lg leading-[24px] font-medium text-gray-900 placeholder:text-gray-600 md:w-[257px] lg:w-[382px]"
placeholder="메시지를 입력해주세요"
value={value}
onChange={onChange}
onKeyUp={onKeyUp}
/>
);
};
Expand Down
25 changes: 11 additions & 14 deletions src/libs/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,28 @@ const GA_MEASUREMENT_ID = import.meta.env.VITE_GA_MEASUREMENT_ID || "";

const isProduction = import.meta.env.MODE === "production";

const initGA = () => {
console.log("import.meta.env.MODE", import.meta.env.MODE);
export const initGA = () => {
console.log("isProduction", isProduction);
console.log("ID", GA_MEASUREMENT_ID);
if (isProduction && GA_MEASUREMENT_ID) {
console.log("initGA");
ReactGA.initialize(GA_MEASUREMENT_ID);
}
};

const trackPageView = (path: string) => {
console.log("trackPageView 1");
export const trackPageView = (url: string, params?: Record<string, string>) => {
if (isProduction && GA_MEASUREMENT_ID) {
console.log("trackPageView 2");
ReactGA.send({ hitType: "pageview", page: path });
console.log("trackPageView");
ReactGA.gtag("event", "page_view", {
page_path: url,
...params
});
}
};

const trackEvent = (category: string, action: string, label?: string) => {
export const trackEvent = (name: string, params?: Record<string, string>) => {
if (isProduction && GA_MEASUREMENT_ID) {
ReactGA.event({
category,
action,
label
});
console.log("trackEvent");
ReactGA.event(name, params);
}
};

export { initGA, trackPageView, trackEvent };
Loading