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
1 change: 1 addition & 0 deletions apps/pyconkr-admin/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const queryClient = new QueryClient({

const CommonOptions: Common.Contexts.ContextOptions = {
debug: true,
language: "ko",
baseUrl: ".",
frontendDomain: import.meta.env.VITE_PYCONKR_FRONTEND_DOMAIN,
backendApiDomain: import.meta.env.VITE_PYCONKR_BACKEND_API_DOMAIN,
Expand Down
64 changes: 38 additions & 26 deletions apps/pyconkr/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,48 @@
import * as Common from "@frontend/common";
import React from "react";
import { BrowserRouter, Route, Routes, useLocation } from "react-router-dom";
import * as React from "react";
import { Route, Routes, useLocation } from "react-router-dom";
import * as R from "remeda";

import MainLayout from "./components/layout";
import { Test } from "./components/pages/test";
import { IS_DEBUG_ENV } from "./consts/index.ts";
import { SponsorProvider } from "./contexts/SponsorContext";
import MainLayout from "./components/layout/index.tsx";
import { PageIdParamRenderer, RouteRenderer } from "./components/pages/dynamic_route.tsx";
import { Test } from "./components/pages/test.tsx";
import { IS_DEBUG_ENV } from "./consts";
import { useAppContext } from "./contexts/app_context";
import BackendAPISchemas from "../../../packages/common/src/schemas/backendAPI";

// 스폰서를 표시할 페이지 경로 설정
const SPONSOR_VISIBLE_PATHS = ["/"];
export const App: React.FC = () => {
const backendAPIClient = Common.Hooks.BackendAPI.useBackendClient();
const { data: flatSiteMap } = Common.Hooks.BackendAPI.useFlattenSiteMapQuery(backendAPIClient);
const siteMapNode = Common.Utils.buildNestedSiteMap(flatSiteMap)?.[""];

const AppContent = () => {
const location = useLocation();
const shouldShowSponsor = SPONSOR_VISIBLE_PATHS.includes(location.pathname);
const { setAppContext, language } = useAppContext();

return (
<SponsorProvider initialVisibility={shouldShowSponsor}>
<Routes>
<Route element={<MainLayout />}>
{IS_DEBUG_ENV && <Route path="/debug" element={<Test />} />}
<Route path="/pages/:id" element={<Common.Components.PageIdParamRenderer />} />
<Route path="*" element={<Common.Components.RouteRenderer />} />
</Route>
</Routes>
</SponsorProvider>
);
};
React.useEffect(() => {
(async () => {
const currentRouteCodes = ["", ...location.pathname.split("/").filter((code) => !R.isEmpty(code))];
const currentSiteMapDepth: (BackendAPISchemas.NestedSiteMapSchema | undefined)[] = [siteMapNode];

for (const routeCode of currentRouteCodes.splice(1)) {
currentSiteMapDepth.push(currentSiteMapDepth.at(-1)?.children[routeCode]);
if (R.isNullish(currentSiteMapDepth.at(-1))) {
console.warn(`Route not found in site map: ${routeCode}`);
break;
}
}

setAppContext((ps) => ({ ...ps, siteMapNode, currentSiteMapDepth }));
})();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [location, language, flatSiteMap]);

export const App: React.FC = () => {
return (
<BrowserRouter>
<AppContent />
</BrowserRouter>
<Routes>
<Route element={<MainLayout />}>
{IS_DEBUG_ENV && <Route path="/debug" element={<Test />} />}
<Route path="/pages/:id" element={<PageIdParamRenderer />} />
<Route path="*" element={<RouteRenderer />} />
</Route>
</Routes>
);
};
97 changes: 56 additions & 41 deletions apps/pyconkr/src/components/layout/BreadCrumb/index.tsx
Original file line number Diff line number Diff line change
@@ -1,56 +1,71 @@
import styled from "@emotion/styled";
import { useEffect, useState } from "react";
import { Stack, styled } from "@mui/material";
import * as React from "react";
import { Link } from "react-router-dom";
import * as R from "remeda";

export default function BreadCrumb() {
const [breadcrumbInfo, setBreadcrumbInfo] = useState({
paths: [{ text: "홈", href: "/" }],
title: "파이콘 한국 행동강령(CoC)",
});
import BackendAPISchemas from "../../../../../../packages/common/src/schemas/backendAPI";

useEffect(() => {
const mockPathInfo = {
paths: [
{ text: "홈", href: "/" },
{ text: "파이콘 한국", href: "/about" },
],
title: "파이콘 한국 행동강령(CoC)",
};
setBreadcrumbInfo(mockPathInfo);
}, []);
type BreadCrumbPropType = {
title: string;
parentSiteMaps: (BackendAPISchemas.NestedSiteMapSchema | undefined)[];
};

export const BreadCrumb: React.FC<BreadCrumbPropType> = ({ title, parentSiteMaps }) => {
let route = "/";
return (
<BreadCrumbContainer>
<BreadcrumbPathContainer>
{breadcrumbInfo.paths.map((item, index) => (
<span key={index}>
{index > 0 && <span className="separator">&gt;</span>}
<a href={item.href}>{item.text}</a>
</span>
))}
<BreadcrumbPathContainer direction="row" alignItems="center">
{parentSiteMaps
.slice(1, -1)
.filter((routeInfo) => R.isNonNullish(routeInfo))
.map(({ route_code, name }, index) => {
route += `${route_code}/`;
return (
<span key={index}>
{index > 0 && <span className="separator">&gt;</span>}
<Link to={route} children={name} />
</span>
);
})}
</BreadcrumbPathContainer>
<PageTitle>{breadcrumbInfo.title}</PageTitle>
<PageTitle>{title}</PageTitle>
</BreadCrumbContainer>
);
}
};

const BreadCrumbContainer = styled.div`
width: 100%;
padding: 14px 117px;
background-color: rgba(255, 255, 255, 0.7);
background-image: linear-gradient(rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0.45));
box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: column;
gap: 5px;
`;
const BreadCrumbContainer = styled(Stack)(({ theme }) => ({
position: "fixed",

top: "3.625rem",
width: "100%",
height: "4.5rem",
background: "linear-gradient(rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0.45))",
boxShadow: "0 1px 10px rgba(0, 0, 0, 0.1)",
backdropFilter: "blur(10px)",

gap: "0.25rem",
justifyContent: "center",
alignItems: "flex-start",

zIndex: theme.zIndex.appBar - 1,

paddingRight: "8rem",
paddingLeft: "8rem",

[theme.breakpoints.down("lg")]: {
paddingRight: "2rem",
paddingLeft: "2rem",
},
[theme.breakpoints.down("sm")]: {
paddingRight: "1rem",
paddingLeft: "1rem",
},
}));

const BreadcrumbPathContainer = styled.div`
const BreadcrumbPathContainer = styled(Stack)`
font-size: 9.75px;
font-weight: 300;
color: #000000;
display: flex;
align-items: center;
gap: 0;

a {
color: #000000;
Expand All @@ -67,7 +82,7 @@ const BreadcrumbPathContainer = styled.div`
}
`;

const PageTitle = styled.h1`
const PageTitle = styled("h1")`
font-size: 27px;
font-weight: 600;
color: #000000;
Expand Down
Loading