Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
ac47917
Update next.config.ts
skyblue1232 Mar 23, 2026
d83b47b
Merge pull request #47 from CUK-Compasser/feat/#40/role-auth
skyblue1232 Mar 23, 2026
daf250f
feat/order-status
skyblue1232 Mar 23, 2026
9afa3fa
chore/tab-layout
skyblue1232 Mar 23, 2026
fbfe475
chore/tab-layout
skyblue1232 Mar 23, 2026
a62ba41
Merge pull request #58 from CUK-Compasser/feat/#49/order-status
skyblue1232 Mar 23, 2026
4c44d76
chore/kakao-map
skyblue1232 Mar 23, 2026
686fe7f
feat/my-page
skyblue1232 Mar 23, 2026
7d3c6a7
chore/tab-layout
skyblue1232 Mar 23, 2026
f452b16
feat/mypage-detail
skyblue1232 Mar 23, 2026
dc807d9
feat/mypage/modal
skyblue1232 Mar 23, 2026
81f7452
Merge pull request #59 from CUK-Compasser/feat/#50/my-page
skyblue1232 Mar 23, 2026
c98374b
chore/icons
skyblue1232 Mar 24, 2026
ff3a68b
feat/notice
skyblue1232 Mar 24, 2026
ab79dc4
Merge pull request #60 from CUK-Compasser/feat/#57/notice-page
skyblue1232 Mar 24, 2026
0e21e24
chore/notice-page
skyblue1232 Mar 24, 2026
01afa45
Merge pull request #61 from CUK-Compasser/feat/#57/notice-page
skyblue1232 Mar 24, 2026
0e5b225
chore/design-system
skyblue1232 Mar 24, 2026
b3a4ff9
feat/main-list
skyblue1232 Mar 24, 2026
9b95c6b
feat/kakao-map
skyblue1232 Mar 24, 2026
0ed5dc3
Merge pull request #62 from CUK-Compasser/feat/#48/home-page
skyblue1232 Mar 24, 2026
aabd497
feat/store-register
skyblue1232 Mar 25, 2026
34fc2d2
Merge pull request #64 from CUK-Compasser/feat/#48/home-page
skyblue1232 Mar 25, 2026
9ceee17
chore/icon
skyblue1232 Mar 26, 2026
d694549
feat/signup-register
skyblue1232 Mar 26, 2026
266c4de
chore/owner-home
skyblue1232 Mar 26, 2026
ebdbc74
Merge pull request #66 from CUK-Compasser/feat/#65/owner-store-register
skyblue1232 Mar 26, 2026
667bc88
refactor/store-register
skyblue1232 Mar 26, 2026
02a0ff9
Merge pull request #67 from CUK-Compasser/feat/#65/owner-store-register
skyblue1232 Mar 26, 2026
ec921fa
chore/input
skyblue1232 Mar 26, 2026
306d8ab
feat/manage-time/modal
skyblue1232 Mar 26, 2026
8e838df
feat/random-box/modal
skyblue1232 Mar 26, 2026
ab7776b
feat/signup-register
skyblue1232 Mar 26, 2026
6fc14ce
chore/input
skyblue1232 Mar 26, 2026
5077a55
chore/input-lint
skyblue1232 Mar 26, 2026
79c1b18
Merge pull request #69 from CUK-Compasser/feat/#65/owner-store-register
skyblue1232 Mar 26, 2026
802eb4a
chore/icons
skyblue1232 Mar 27, 2026
2ab955e
feat/owner-home
skyblue1232 Mar 27, 2026
a17e592
Merge pull request #70 from CUK-Compasser/feat/#54/owner-home-page
skyblue1232 Mar 27, 2026
de8c55f
feat/owner-orderList/modal
skyblue1232 Mar 27, 2026
7685797
feat/owner-orderList
skyblue1232 Mar 27, 2026
7572263
chore/tab-order
skyblue1232 Mar 27, 2026
f26a770
Merge pull request #71 from CUK-Compasser/feat/#55/owner-order-page
skyblue1232 Mar 27, 2026
26fdefb
Update README.md
skyblue1232 Mar 27, 2026
980e000
feat/owner-mypage
skyblue1232 Mar 29, 2026
7c37663
feat/owner-store-info
skyblue1232 Mar 29, 2026
f172bb5
feat/owner-store-account
skyblue1232 Mar 29, 2026
df3eda0
Merge pull request #72 from CUK-Compasser/feat/#56/owner-my-page
skyblue1232 Mar 29, 2026
d1fe2dd
feat/owner-home-qr
skyblue1232 Mar 29, 2026
d3fe0b7
Merge pull request #74 from CUK-Compasser/feat/#73/owner-home-qr
skyblue1232 Mar 29, 2026
729a37a
chore/mock-data
skyblue1232 Mar 29, 2026
46b296f
feat/store-detail
skyblue1232 Mar 29, 2026
bd10738
chore/owner-tab-layout
skyblue1232 Mar 29, 2026
705bdd4
Merge pull request #75 from CUK-Compasser/feat/#63/shop-detail
skyblue1232 Mar 29, 2026
04d9b91
chore/mock-data
skyblue1232 Mar 29, 2026
5761d96
chore/page-layout
skyblue1232 Mar 29, 2026
02841a5
feat/purchase-detail
skyblue1232 Mar 29, 2026
0be34e8
feat/purchase-modal
skyblue1232 Mar 29, 2026
643b131
feat/purchase-complete
skyblue1232 Mar 29, 2026
07e7188
Merge pull request #77 from CUK-Compasser/feat/#76/random-box-payment
skyblue1232 Mar 29, 2026
8aa1c55
setting/packages/query-factory
skyblue1232 Mar 31, 2026
a6caef7
Merge pull request #79 from CUK-Compasser/setting/#78/api-query-factory
skyblue1232 Mar 31, 2026
9f80070
chore/api-client
skyblue1232 Mar 31, 2026
776a49a
Merge pull request #80 from CUK-Compasser/setting/#78/api-query-factory
skyblue1232 Mar 31, 2026
fa09d2a
api/login
skyblue1232 Apr 2, 2026
17e4aee
api/signup
skyblue1232 Apr 2, 2026
5e949c4
chore/owner-data
skyblue1232 Apr 2, 2026
08935fc
feat/business-page
skyblue1232 Apr 2, 2026
52b07f8
feat/signup-api
skyblue1232 Apr 2, 2026
e69383b
feat/register-hook
skyblue1232 Apr 2, 2026
b5a3c92
refactor/signup-register
skyblue1232 Apr 2, 2026
dba4df5
chore/account-field
skyblue1232 Apr 2, 2026
94924b8
refactor/store-info
skyblue1232 Apr 2, 2026
108b1bf
Merge pull request #82 from CUK-Compasser/feat/#81/signup-api
skyblue1232 Apr 2, 2026
b653af1
chore/packages
skyblue1232 Apr 4, 2026
5a5a71f
api/main-store
skyblue1232 Apr 4, 2026
a7b3f5b
feat/address-search
skyblue1232 Apr 4, 2026
25f4d4f
feat/store-map/detail
skyblue1232 Apr 4, 2026
cedce21
fix/store-model
skyblue1232 Apr 4, 2026
7df0816
Merge pull request #84 from CUK-Compasser/feat/#83/list-map-apis
skyblue1232 Apr 4, 2026
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
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,12 @@
# FE
# FE
#### 모노레포(도메인 기반) 구조

Compasser 프로젝트 프론트엔드 아키텍쳐입니다.
- Design System 구축 및 패키지화

<img width="101" height="68" alt="image" src="https://github.com/user-attachments/assets/8a68362c-0562-4a90-b21d-17f1a41ec896" />

- 카페별 랜덤박스 결제, QR 기반 적립

<img width="3840" height="2160" alt="image" src="https://github.com/user-attachments/assets/5ec8d619-29bb-44d0-8763-fd209ea6fbbd" />

1 change: 1 addition & 0 deletions apps/customer/next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ const nextConfig: NextConfig = {
};

export default nextConfig;

1 change: 1 addition & 0 deletions apps/customer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"type-check": "tsc --noEmit"
},
"dependencies": {
"@compasser/api": "workspace:^",
"@compasser/design-system": "workspace:*",
"@tanstack/react-query": "^5.90.21",
"next": "16.1.6",
Expand Down
18 changes: 18 additions & 0 deletions apps/customer/public/icons/pin-bakery.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions apps/customer/public/icons/pin-cafe.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions apps/customer/public/icons/pin-restaurant.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 11 additions & 10 deletions apps/customer/src/app/(tabs)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,13 @@ export default function TabsLayout({ children }: TabsLayoutProps) {
const router = useRouter();
const pathname = usePathname();

const activeKey =
pathname === "/main"
? "home"
: pathname === "/order"
? "order"
: pathname === "/mypage"
? "my"
: "home";
const activeKey = pathname.startsWith("/mypage")
? "my"
: pathname.startsWith("/order")
? "order"
: pathname.startsWith("/main")
? "home"
: "home";

const handleTabChange = (key: string) => {
if (key === "home") {
Expand All @@ -44,8 +43,10 @@ export default function TabsLayout({ children }: TabsLayoutProps) {
};

return (
<div className="relative mx-auto min-h-screen w-full max-w-[42.5rem] bg-white">
<div className="pb-[8.4rem]">{children}</div>
<div className="flex h-dvh w-full flex-col overflow-hidden bg-white">
<div className="ds-scrollbar-hidden flex-1 overflow-y-auto">
{children}
</div>

<BottomTabBar
items={tabItems}
Expand Down
72 changes: 72 additions & 0 deletions apps/customer/src/app/(tabs)/main/_apis/searchAddressByKakao.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
"use client";

import type { AddressSearchItem } from "../_types/address-search";

export function searchAddressByKakao(
keyword: string,
size = 10
): Promise<AddressSearchItem[]> {
return new Promise((resolve, reject) => {
const trimmedKeyword = keyword.trim();

if (!trimmedKeyword) {
resolve([]);
return;
}

if (
typeof window === "undefined" ||
!window.kakao ||
!window.kakao.maps ||
!window.kakao.maps.services
) {
reject(new Error("Kakao services library is not loaded."));
return;
}

const geocoder = new window.kakao.maps.services.Geocoder();

geocoder.addressSearch(
trimmedKeyword,
(result: KakaoAddressSearchResult[], status: string) => {
const { kakao } = window;

if (status === kakao.maps.services.Status.ZERO_RESULT) {
resolve([]);
return;
}

if (status !== kakao.maps.services.Status.OK) {
reject(new Error("주소 검색 중 오류가 발생했습니다."));
return;
}

const mapped = result.slice(0, size).map(
(item: KakaoAddressSearchResult, index: number) => {
const lotNumberAddress =
item.address?.address_name || item.address_name || "";

const roadAddress =
item.road_address?.address_name || item.address_name || "";

return {
id: `${item.x}-${item.y}-${index}`,
label: roadAddress || lotNumberAddress,
lotNumberAddress,
roadAddress,
longitude: Number(item.x),
latitude: Number(item.y),
};
}
);

resolve(mapped);
},
{
page: 1,
size,
analyze_type: window.kakao.maps.services.AnalyzeType.SIMILAR,
}
);
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
"use client";

import { useEffect, useRef, useState } from "react";
import { BottomSheet, Input, Icon } from "@compasser/design-system";
import type { AddressSearchItem } from "../_types/address-search";
import { searchAddressByKakao } from "../_apis/searchAddressByKakao";

interface AddressSearchBottomSheetProps {
open: boolean;
onClose: () => void;
onSelectAddress: (item: AddressSearchItem) => void;
}

export default function AddressSearchBottomSheet({
open,
onClose,
onSelectAddress,
}: AddressSearchBottomSheetProps) {
const [keyword, setKeyword] = useState("");
const [results, setResults] = useState<AddressSearchItem[]>([]);
const [isSearching, setIsSearching] = useState(false);

const debounceRef = useRef<number | null>(null);

useEffect(() => {
if (!open) {
setKeyword("");
setResults([]);
setIsSearching(false);
}
}, [open]);

useEffect(() => {
if (!open) {
return;
}

const trimmedKeyword = keyword.trim();

if (!trimmedKeyword) {
setResults([]);
setIsSearching(false);
return;
}

if (debounceRef.current) {
window.clearTimeout(debounceRef.current);
}

debounceRef.current = window.setTimeout(async () => {
try {
setIsSearching(true);
const searched = await searchAddressByKakao(trimmedKeyword, 10);
setResults(searched);
} catch (error) {
console.error(error);
setResults([]);
} finally {
setIsSearching(false);
}
}, 250);

return () => {
if (debounceRef.current) {
window.clearTimeout(debounceRef.current);
}
};
}, [keyword, open]);

const handleQuickSelect = () => {
onSelectAddress({
id: "catholic-univ",
label: "가톨릭대 주변 탐색",
lotNumberAddress: "경기도 부천시 원미구 역곡동 일대",
roadAddress: "가톨릭대학교 성심교정 주변",
longitude: 126.8016,
latitude: 37.4875,
});
};

const handleSelectItem = (item: AddressSearchItem) => {
onSelectAddress(item);
};

return (
<BottomSheet
open={open}
onClose={onClose}
variant="default"
overlay
closeOnOverlayClick
showHandle
className="w-full"
contentClassName="px-[1.6rem] pt-[0.8rem] pb-[2rem]"
>
<Input
inputStyle="address"
value={keyword}
onChange={(event) => setKeyword(event.target.value)}
placeholder="위치 입력"
/>

<button
type="button"
onClick={handleQuickSelect}
className="ml-[0.6rem] mt-[1rem] inline-flex items-center rounded-[999px] border border-secondary-variant px-[0.8rem] py-[0.2rem]"
>
<Icon
name="Pin"
width={20}
height={20}
className="mr-[0.4rem]"
/>
<span className="body2-r text-default">가톨릭대 주변 탐색</span>
</button>

{results.length > 0 && (
<div className="mt-[1.2rem] max-h-[32rem] overflow-y-auto">
{results.map((item) => (
<button
key={item.id}
type="button"
onClick={() => handleSelectItem(item)}
className="block w-full border-b border-gray-100 px-[0.6rem] pt-[0.6rem] pb-[0.8rem] text-left"
>
<p className="body2-r text-default">{item.lotNumberAddress}</p>
<p className="caption1-r text-gray-500">{item.roadAddress}</p>
</button>
))}
</div>
)}

{keyword.trim() && isSearching && (
<p className="mt-[1.2rem] px-[0.6rem] text-center caption1-r text-gray-500">
검색 중...
</p>
)}

{keyword.trim() && !isSearching && results.length === 0 && (
<p className="mt-[1.2rem] px-[0.6rem] text-center caption1-r text-gray-500">
검색 결과가 없습니다.
</p>
)}
</BottomSheet>
);
}
Loading
Loading