diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml
index 45dd2855..4a8d28ac 100644
--- a/.github/workflows/preview.yml
+++ b/.github/workflows/preview.yml
@@ -7,6 +7,7 @@ permissions:
on:
pull_request:
branches: [develop]
+ types: [opened, synchronize, reopened]
jobs:
preview:
@@ -14,6 +15,9 @@ jobs:
steps:
- name: Git Checkout
uses: actions/checkout@v4
+ with:
+ ref: ${{ github.event.pull_request.head.sha }}
+ fetch-depth: 0
- name: Install pnpm
uses: pnpm/action-setup@v4
@@ -36,7 +40,13 @@ jobs:
NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL }}
- name: Build
- run: pnpm -filter=web build
+ run: |
+ echo "GITHUB_EVENT_NAME=${{ github.event_name }}" >> apps/web/.env.production.local
+ echo "GITHUB_EVENT_NUMBER=${{ github.event.pull_request.number }}" >> apps/web/.env.production.local
+ pnpm -filter=web build
+ env:
+ GITHUB_EVENT_NAME: ${{ github.event_name }}
+ GITHUB_EVENT_NUMBER: ${{ github.event.pull_request.number }}
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
diff --git a/apps/mobile/app/(route)/dashboard.tsx b/apps/mobile/app/(route)/dashboard.tsx
index 6e96b635..bf0a8625 100644
--- a/apps/mobile/app/(route)/dashboard.tsx
+++ b/apps/mobile/app/(route)/dashboard.tsx
@@ -3,13 +3,16 @@ import WebView, { WebViewMessageEvent } from "react-native-webview";
import { ROUTES } from "@/constants/routes";
import { useHandleNavigationActions } from "@/hooks/useHandleNavigationActions";
import { getWebViewApiUrl } from "@/utils/getWebViewApiUrl";
+import { parseMessage } from "@/utils/parseMessage";
export default function DashboardScreen() {
const baseUrl = getWebViewApiUrl();
const handleNavigationActions = useHandleNavigationActions();
const requestOnMessage = (e: WebViewMessageEvent) => {
- handleNavigationActions(e);
+ const { type, data } = parseMessage(e);
+
+ handleNavigationActions({ type, data });
};
return ;
diff --git a/apps/mobile/app/(route)/meetings.tsx b/apps/mobile/app/(route)/meetings.tsx
index 1883a399..d6a442fa 100644
--- a/apps/mobile/app/(route)/meetings.tsx
+++ b/apps/mobile/app/(route)/meetings.tsx
@@ -3,13 +3,16 @@ import WebView, { WebViewMessageEvent } from "react-native-webview";
import { ROUTES } from "@/constants/routes";
import { useHandleNavigationActions } from "@/hooks/useHandleNavigationActions";
import { getWebViewApiUrl } from "@/utils/getWebViewApiUrl";
+import { parseMessage } from "@/utils/parseMessage";
export default function MeetingsScreen() {
const baseUrl = getWebViewApiUrl();
const handleNavigationActions = useHandleNavigationActions();
const requestOnMessage = (e: WebViewMessageEvent) => {
- handleNavigationActions(e);
+ const { type, data } = parseMessage(e);
+
+ handleNavigationActions({ type, data });
};
return ;
diff --git a/apps/mobile/app/(route)/seats.tsx b/apps/mobile/app/(route)/seats.tsx
index 08c04fb2..f363efc6 100644
--- a/apps/mobile/app/(route)/seats.tsx
+++ b/apps/mobile/app/(route)/seats.tsx
@@ -3,13 +3,16 @@ import WebView, { WebViewMessageEvent } from "react-native-webview";
import { ROUTES } from "@/constants/routes";
import { useHandleNavigationActions } from "@/hooks/useHandleNavigationActions";
import { getWebViewApiUrl } from "@/utils/getWebViewApiUrl";
+import { parseMessage } from "@/utils/parseMessage";
export default function SeatsScreen() {
const baseUrl = getWebViewApiUrl();
const handleNavigationActions = useHandleNavigationActions();
const requestOnMessage = (e: WebViewMessageEvent) => {
- handleNavigationActions(e);
+ const { type, data } = parseMessage(e);
+
+ handleNavigationActions({ type, data });
};
return ;
diff --git a/apps/mobile/app/(route)/settings.tsx b/apps/mobile/app/(route)/settings.tsx
index 7fe7c530..a368796a 100644
--- a/apps/mobile/app/(route)/settings.tsx
+++ b/apps/mobile/app/(route)/settings.tsx
@@ -3,13 +3,17 @@ import WebView, { WebViewMessageEvent } from "react-native-webview";
import { ROUTES } from "@/constants/routes";
import { useHandleNavigationActions } from "@/hooks/useHandleNavigationActions";
import { getWebViewApiUrl } from "@/utils/getWebViewApiUrl";
+import { parseMessage } from "@/utils/parseMessage";
export default function SettingsScreen() {
const baseUrl = getWebViewApiUrl();
const handleNavigationActions = useHandleNavigationActions();
const requestOnMessage = (e: WebViewMessageEvent) => {
- handleNavigationActions(e);
+ const { type, data } = parseMessage(e);
+
+ handleNavigationActions({ type, data });
};
+
return ;
}
diff --git a/apps/web/app/_components/AuthGuard.tsx b/apps/web/app/_components/AuthGuard.tsx
index 778b58f8..4c579830 100644
--- a/apps/web/app/_components/AuthGuard.tsx
+++ b/apps/web/app/_components/AuthGuard.tsx
@@ -2,7 +2,7 @@
import { useEffect, useState } from "react";
import { PAGE_NAME } from "@ui/src/utils/constants/pageNames";
-import { useRouter } from "next/navigation";
+import { useRouter, usePathname } from "next/navigation";
import { useAuthStore } from "@/app/store/useAuthStore";
import { createWebViewEventListener } from "../../lib/bridge/createWebViewEventListener";
import { parseWebViewAuthMessage } from "../../lib/bridge/parseWebViewAuthMessage";
@@ -11,10 +11,10 @@ import SignInForm from "./SignInForm";
export default function AuthGuard(): JSX.Element | null {
const router = useRouter();
+ const pathname = usePathname();
const [isLoading, setIsLoading] = useState(true);
const { isLoggedIn } = useAuthStore();
const { isIOSWebView, isAndroidWebView } = useDetectWebView();
-
const webViewEventListener = createWebViewEventListener({ isIOSWebView, isAndroidWebView });
useEffect(() => {
@@ -23,14 +23,25 @@ export default function AuthGuard(): JSX.Element | null {
}, []);
useEffect(() => {
- if (isLoggedIn) {
- router.replace(PAGE_NAME.DASHBOARD);
+ if (!isLoggedIn) {
+ setIsLoading(false);
+ return;
+ }
+
+ if (pathname === "/" && typeof window !== "undefined") {
+ const urlParams = new URLSearchParams(window.location.search);
+ const prNumber = urlParams.get("pr");
+
+ if (prNumber) {
+ router.replace(`/dashboard?pr=${prNumber}`);
+ } else {
+ router.replace(PAGE_NAME.DASHBOARD);
+ }
}
setIsLoading(false);
- }, [isLoggedIn, router]);
+ }, [isLoggedIn, router, pathname]);
if (isLoading) return null;
-
return isLoggedIn ? null : ;
}
diff --git a/apps/web/app/dashboard/_components/DashboardSection.tsx b/apps/web/app/dashboard/_components/DashboardSection.tsx
index d5add773..43c1c08e 100644
--- a/apps/web/app/dashboard/_components/DashboardSection.tsx
+++ b/apps/web/app/dashboard/_components/DashboardSection.tsx
@@ -33,6 +33,7 @@ export default function DashboardSection({ data = [] }: DashboardSectionProps):
return (
+
Preview Test
내 회의
{upcomingMeetings.length > 0 ? (
diff --git a/apps/web/components/Gnb/GnbMenu.tsx b/apps/web/components/Gnb/GnbMenu.tsx
index 433d94bc..58c74b79 100644
--- a/apps/web/components/Gnb/GnbMenu.tsx
+++ b/apps/web/components/Gnb/GnbMenu.tsx
@@ -33,8 +33,22 @@ export default function GnbMenu({ isAdmin }: GnbMenuProps): JSX.Element | null {
const { push } = useAppRouter();
const { isWebView } = useDetectWebView();
+ const getPrNumber = (): string | null => {
+ if (typeof window === "undefined") return null;
+
+ const urlParams = new URLSearchParams(window.location.search);
+
+ return urlParams.get("pr");
+ };
+
+ const getUrlWithPR = (path: string): string => {
+ const prNumber = getPrNumber();
+
+ return prNumber ? `${path}?pr=${prNumber}` : path;
+ };
+
const handleButtonClick = (path: string): void => {
- push(path);
+ push(getUrlWithPR(path));
};
return (
@@ -57,7 +71,7 @@ export default function GnbMenu({ isAdmin }: GnbMenuProps): JSX.Element | null {
},
}
: {
- href,
+ href: getUrlWithPR(href),
})}
className={cn("h-full justify-start md:h-40 md:w-full md:px-0 md:py-0", index === 3 && "block md:hidden")}
variant="Text"
@@ -82,7 +96,7 @@ export default function GnbMenu({ isAdmin }: GnbMenuProps): JSX.Element | null {
{ADMIN_ITEMS.map(({ href, name, icon: Icon }) => {
const isActive = pathname === href;
return (
-
+