Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
[![React DatePicker](https://img.shields.io/badge/React%20DatePicker-7.5.0-216BA5)](https://reactdatepicker.com/)
[![React Icons](https://img.shields.io/badge/React%20Icons-5.3.0-E91E63)](https://react-icons.github.io/react-icons)
[![React Hot Toast](https://img.shields.io/badge/React%20Hot%20Toast-2.4.1-FF4444)](https://react-hot-toast.com/)
[![Yet Another React Lightbox](https://img.shields.io/badge/Yet%20Another%20React%20Lightbox-3.17.0-00A5E0)](https://yet-another-react-lightbox.com/)
[![Hello Pangea DnD](https://img.shields.io/badge/Hello%20Pangea%20DnD-17.0.0-yellow)](https://github.com/hello-pangea/dnd)

### 지도 & 소셜
Expand Down
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"react-kakao-maps-sdk": "^1.1.27",
"react-responsive": "^10.0.0",
"tailwind-merge": "^2.5.4",
"yet-another-react-lightbox": "^3.21.7",
"zod": "^3.23.8",
"zustand": "^5.0.1"
},
Expand Down
Binary file modified public/og-image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions src/app/(auth)/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default function LoginPage() {
// 로그인 훅과 로딩 상태 관리
const { login, isPending } = useLogin();
const [isSocialLogin, setIsSocialLogin] = useState(false);
const [currentProvider, setCurrentProvider] = useState<OAuthProvider>(oauthProviders.GOOGLE);
const [, setCurrentProvider] = useState<OAuthProvider>(oauthProviders.GOOGLE);

// 폼 유효성 검사 및 상태 관리
const {
Expand Down Expand Up @@ -86,7 +86,7 @@ export default function LoginPage() {
<div className="text-grayscale-900 text-center text-3xl font-bold tracking-tight">로그인</div>
<p className="text-grayscale-600 mt-2 text-center text-sm">
아직 계정이 없으신가요?{" "}
<Link href="/signup" className="font-medium text-primary-orange-300 hover:text-primary-orange-200">
<Link href="/signup" className="font-bold text-primary-orange-300 hover:text-primary-orange-200">
회원가입하기
</Link>
</p>
Expand Down
4 changes: 2 additions & 2 deletions src/app/(auth)/signup/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default function SignupPage() {
<h2 className="text-grayscale-900 text-center text-3xl font-bold tracking-tight">회원 유형 선택</h2>
<p className="text-grayscale-600 mt-2 text-center text-sm">
이미 계정이 있으신가요?{" "}
<Link href="/login" className="font-medium text-primary-orange-300 hover:text-primary-orange-200">
<Link href="/login" className="font-bold text-primary-orange-300 hover:text-primary-orange-200">
로그인하기
</Link>
</p>
Expand All @@ -22,7 +22,7 @@ export default function SignupPage() {
{/* 지원자 회원가입 카드 */}
<Link
href="/signup/applicant"
className="flex flex-1 flex-col items-center rounded-lg border-2 border-transparent bg-primary-blue-50 p-8 transition-all hover:scale-105 hover:border-primary-orange-300 hover:shadow-lg"
className="flex flex-1 flex-col items-center rounded-lg border-2 border-transparent bg-[#ebfdeb] p-8 transition-all hover:scale-105 hover:border-primary-orange-300 hover:shadow-xl"
>
<div className="flex h-24 w-24 items-center justify-center rounded-full bg-primary-orange-50">
<FaUser className="h-12 w-12 text-primary-orange-300" />
Expand Down
14 changes: 7 additions & 7 deletions src/app/(home)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const slides = [
{
id: 1,
title: "쉽고 빨라요",
content: "1분만에 알바폼을 만들어 보세요!\n링크를 복사하여 어디서든지 사용하세요.",
content: "1분만에 워크폼을 만들어 보세요!\n링크를 복사하여 어디서든지 사용하세요.",
image: "/images/land/s2.svg",
},
{
Expand Down Expand Up @@ -65,7 +65,7 @@ const slides = [
{
id: 7,
title: "쉽고 빨라요",
content: "1분만에 알바폼을 만들어 보세요!\n링크를 복사하여 어디서든지 사용하세요.",
content: "1분만에 워크폼을 만들어 보세요!\n링크를 복사하여 어디서든지 사용하세요.",
image: "/images/land/s2.png",
},
{
Expand Down Expand Up @@ -273,7 +273,7 @@ export default function LandingPage() {
src={slides[currentSlide].blackAreaImage || ""}
alt={slides[currentSlide].blackAreaTitle || ""}
fill
className="object-contain transition-transform duration-500 hover:scale-105"
className="object-contain transition-transform duration-500"
sizes="(max-width: 768px) 100vw, 600px"
/>
</div>
Expand All @@ -284,7 +284,7 @@ export default function LandingPage() {
{/* 텍스트 섹션 - 장식 요소 제거 */}
<motion.div className="relative">
<motion.h2
className="text-center font-hakgyo text-4xl font-bold tracking-tight md:text-5xl lg:text-6xl"
className="text-center font-hakgyo text-4xl font-bold tracking-tight md:text-4xl lg:text-6xl"
style={{
background: "linear-gradient(to right, #71db77, #56c45d)",
WebkitBackgroundClip: "text",
Expand Down Expand Up @@ -488,7 +488,7 @@ export default function LandingPage() {
src={slides[currentSlide].image}
alt={slides[currentSlide].title}
fill
className="object-contain transition-transform duration-500 hover:scale-105"
className="object-contain transition-transform duration-500"
sizes="(max-width: 768px) 100vw, 600px"
/>
</div>
Expand All @@ -499,7 +499,7 @@ export default function LandingPage() {
{/* 텍스트 섹션 */}
<motion.div className="relative">
<motion.h2
className="text-center font-hakgyo text-4xl font-bold tracking-tight md:text-5xl lg:text-6xl"
className="text-center font-hakgyo text-4xl font-bold tracking-tight md:text-4xl lg:text-6xl"
style={{
color: "#ffffff",
letterSpacing: "-0.02em",
Expand Down Expand Up @@ -585,7 +585,7 @@ export default function LandingPage() {
className={`fixed ${
isLargeScreen
? "right-12 top-1/2 -translate-y-1/2 space-y-4"
: "bottom-12 left-1/2 flex -translate-x-1/2 space-x-4"
: "bottom-12 left-12 flex flex-col space-y-4"
}`}
>
{slides.slice(1).map((_, index) => (
Expand Down
93 changes: 67 additions & 26 deletions src/app/(pages)/(workform)/work/[formId]/components/FormImage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
"use client";

import Image from "next/image";
import Indicator from "@/app/components/pagination/Indicator";
import { isValidS3Url } from "@/utils/checkS3Url";
import { useState } from "react";
import Lightbox from "yet-another-react-lightbox";
import "yet-another-react-lightbox/styles.css";
import Zoom from "yet-another-react-lightbox/plugins/zoom";
import Counter from "yet-another-react-lightbox/plugins/counter";
import "yet-another-react-lightbox/plugins/counter.css";

interface FormImageProps {
imageUrls: string[];
Expand All @@ -9,32 +17,65 @@ interface FormImageProps {
}

export default function FormImage({ imageUrls, currentPage, onPageChange }: FormImageProps) {
const [isOpen, setIsOpen] = useState(false);

const handleImageClick = () => {
setIsOpen(true);
};

const slides = imageUrls.map((url) => ({
src: url,
}));

return (
<div className="relative flex h-[300px] justify-center lg:h-[460px]">
{/* 이미지 표시 */}
{imageUrls?.map((imageUrl, index) => (
<div
key={imageUrl}
className={`absolute h-full w-full transition-opacity duration-300 ${
index === currentPage ? "opacity-100" : "opacity-0"
}`}
>
<Image
src={imageUrl}
alt={`알바 이미지 ${index + 1}`}
className="h-full w-full rounded-lg object-cover"
priority={index === 0}
fill
/>
</div>
))}

{/* 인디케이터 */}
{imageUrls.filter((url) => isValidS3Url(url)).length > 1 && (
<div className="absolute bottom-4 left-1/2 -translate-x-1/2">
<Indicator imageCount={imageUrls?.length ?? 0} currentPage={currentPage} onPageChange={onPageChange} />
</div>
)}
</div>
<>
<div className="relative flex h-[300px] justify-center lg:h-[460px]">
{/* 이미지 표시 */}
{imageUrls?.map((imageUrl, index) => (
<div
key={imageUrl}
className={`absolute h-full w-full cursor-zoom-in transition-opacity duration-300 ${
index === currentPage ? "opacity-100" : "opacity-0"
}`}
onClick={handleImageClick}
role="button"
tabIndex={0}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
handleImageClick();
}
}}
>
<Image
src={imageUrl}
alt={`알바 이미지 ${index + 1}`}
className="h-full w-full rounded-lg object-cover"
priority={index === 0}
fill
/>
</div>
))}

{/* 인디케이터 */}
{imageUrls.filter((url) => isValidS3Url(url)).length > 1 && (
<div className="absolute bottom-4 left-1/2 -translate-x-1/2">
<Indicator imageCount={imageUrls?.length ?? 0} currentPage={currentPage} onPageChange={onPageChange} />
</div>
)}
</div>

{/* Lightbox */}
<Lightbox
open={isOpen}
close={() => setIsOpen(false)}
slides={slides}
index={currentPage}
plugins={[Zoom, Counter]}
counter={{ container: { style: { top: "unset", bottom: 0 } } }}
on={{
view: ({ index }) => onPageChange(index),
}}
/>
</>
);
}
3 changes: 2 additions & 1 deletion src/app/clientLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,11 @@ export default function ClientLayout({ children }: { children: React.ReactNode }
// 채널톡을 표시하지 않을 경로들
const excludePaths = ["/login", "/signup", "/auth/callback"];
const showChannelTalk = !excludePaths.some((path) => pathname.startsWith(path));
const isHome = pathname === "/";

return (
<QueryClientProvider client={queryClient}>
<div className="relative">
<div className={`relative min-h-[80vh] ${!isHome ? "pt-16" : ""}`}>
{children}
<MouseTrail />
<Toaster
Expand Down
2 changes: 1 addition & 1 deletion src/app/components/button/default/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const Button = ({
const colorStyles = {
orange: {
solid:
"bg-primary-orange-300 text-white hover:bg-primary-orange-200 focus:ring-1 focus:ring-primary-orange-200 focus:outline-none disabled:bg-primary-orange-100 disabled:cursor-not-allowed",
"bg-primary-orange-300 text-white hover:bg-primary-orange-350 focus:ring-1 focus:ring-primary-orange-200 focus:outline-none disabled:bg-primary-orange-100 disabled:cursor-not-allowed",
outlined:
"border-2 border-primary-orange-300 text-primary-orange-300 hover:border-primary-orange-200 hover:text-primary-orange-200 focus:ring-1 focus:ring-primary-orange-200 focus:outline-none disabled:border-primary-orange-100 disabled:text-grayscale-100 disabled:cursor-not-allowed disabled:hover:bg-transparent",
},
Expand Down
37 changes: 23 additions & 14 deletions src/app/components/input/text/LocationInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,34 @@ import { BaseInputProps } from "@/types/textInput";
import { forwardRef, useCallback, useState, useEffect } from "react";
import Script from "next/script";

// DaumPostcode 타입 정의
// Daum 우편번호 서비스에서 주소 검색 후 반환되는 데이터 타입
interface DaumPostcodeData {
address: string;
addressType: string;
bname: string;
buildingName: string;
zonecode: string;
[key: string]: string;
address: string; // 기본 주소 (도로명 주소 또는 지번 주소)
addressType: string; // 검색된 주소 타입 (R: 도로명, J: 지번)
bname: string; // 법정동/법정리 이름
buildingName: string; // 건물명
zonecode: string; // 우편번호
[key: string]: string; // 기타 가능한 추가 필드들
}

// 전역 Window 객체에 다음 우편번호 서비스 타입 선언
declare global {
interface Window {
daum: {
Postcode: new (config: { oncomplete: (data: DaumPostcodeData) => void }) => {
open: () => void;
// Postcode 클래스 정의
Postcode: new (config: {
oncomplete: (data: DaumPostcodeData) => void; // 주소 검색 완료 시 실행될 콜백 함수
}) => {
open: () => void; // 주소 검색 팝업을 여는 메서드
};
};
}
}

interface LocationInputProps extends BaseInputProps {
onAddressChange?: (fullAddress: string) => void;
readOnly?: boolean;
value?: string;
onAddressChange?: (fullAddress: string) => void; // 주소가 변경될 때 호출될 콜백 함수
readOnly?: boolean; // 입력 필드 읽기 전용 여부
value?: string; // 초기 주소 값
}

const LocationInput = forwardRef<HTMLInputElement, LocationInputProps>(
Expand All @@ -39,26 +43,31 @@ const LocationInput = forwardRef<HTMLInputElement, LocationInputProps>(
) => {
const [address, setAddress] = useState("");

// 외부에서 주소 값이 변경될 경우 내부 상태 업데이트
useEffect(() => {
if (value) {
setAddress(value);
}
}, [value]);

// 다음 우편번호 검색 팝업을 여는 함수
const handleOpenPostcode = useCallback(() => {
// SSR 환경이거나 다음 스크립트가 로드되지 않은 경우 실행하지 않음
if (typeof window === "undefined" || !window.daum) return;

// 다음 우편번호 검색 팝업 생성 및 설정
new window.daum.Postcode({
oncomplete: (data: DaumPostcodeData) => {
const newAddress = data.address;
setAddress(newAddress);
onAddressChange?.(newAddress);
setAddress(newAddress); // 내부 상태 업데이트
onAddressChange?.(newAddress); // 부모 컴포넌트에 주소 변경 알림
},
}).open();
}, [onAddressChange]);

return (
<>
{/* 다음 우편번호 서비스 스크립트 로드 */}
<Script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js" strategy="afterInteractive" />
<div className="relative w-full">
<BaseInput
Expand Down
16 changes: 12 additions & 4 deletions src/app/components/layout/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,29 @@ export default function Header() {

if (pathname === "/") {
return (
<header className="fixed left-0 right-0 top-0 z-40" data-slide-header>
<header className="fixed right-8 top-0 z-40" data-slide-header>
<nav className="mx-auto flex h-16 min-w-[327px] max-w-screen-xl items-center justify-end px-6">
<div className="flex items-center gap-4 md:gap-6">
<Link
href="/work-list"
className="text-sm text-white transition-colors hover:text-lime-400 md:text-base lg:text-lg"
className="text-sm text-white transition-colors hover:text-primary-orange-300 md:text-base lg:text-lg"
>
워크 채널
</Link>
<Link
href="/work-talk"
className="text-sm text-white transition-colors hover:text-lime-400 md:text-base lg:text-lg"
className="text-sm text-white transition-colors hover:text-primary-orange-300 md:text-base lg:text-lg"
>
워크톡
</Link>
{!user && !isLoading && (
<Link
href="/login"
className="text-sm text-white transition-colors hover:text-primary-orange-300 md:text-base lg:text-lg"
>
로그인
</Link>
)}
</div>
</nav>
</header>
Expand All @@ -62,7 +70,7 @@ export default function Header() {

return cn(
"font-medium transition-colors h-16 flex items-center",
"hover:text-lime-900 hover:font-bold hover:opacity-70",
"hover:font-bold hover:text-primary-orange-300",
isActive
? "text-lime-900 text-sm md:text-base lg:text-lg font-bold"
: "text-primary-orange-400 text-sm md:text-base"
Expand Down
Loading
Loading