Skip to content

Commit

Permalink
add kakao pay template
Browse files Browse the repository at this point in the history
  • Loading branch information
jongwony committed Jan 20, 2025
1 parent 61ed874 commit 33b2cfd
Show file tree
Hide file tree
Showing 7 changed files with 211 additions and 107 deletions.
Binary file added public/get_kakao_url_guide.mp4
Binary file not shown.
Binary file added public/hero_kakao.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/kakaopay1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 4 additions & 2 deletions src/app/Hero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import Image from 'next/image';
const Hero: React.FC = () => {
const router = useRouter();
const states = [
{ text: '내 LinkedIn 프로필을', image: '/hero_linkedin.png' },
{ text: '내 Instagram 프로필을', image: '/hero_instagram.png' },
{ text: 'LinkedIn 프로필을', image: '/hero_linkedin.png' },
{ text: 'Instagram 프로필을', image: '/hero_instagram.png' },
{ text: '카카오페이로 송금하는 QR코드를', image: '/hero_kakao.png' },
// { text: '토스뱅크로 송금하는 QR코드를', image: '/hero_toss.png' },
];

const [currentStateIndex, setCurrentStateIndex] = useState(0);
Expand Down
50 changes: 30 additions & 20 deletions src/app/form/Template.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,17 @@ export default function ChooseTemplate({ templates, onThemeChange, onTemplateCha
})
};

const themeStyles: Record<string, string> = {
light: "bg-white border-blue-500 scale-110",
dark: "bg-black border-blue-500 scale-110",
insta_special: "bg-gradient-to-tr from-yellow-500 via-pink-500 to-blue-500 border-blue-500 scale-110",
kakaopay1: "bg-yellow-300 border-blue-500 scale-110",
};

const getThemeStyle = (theme: string) => {
return themeStyles[theme] || "border-transparent"; // 기본값 처리
};

return (
<div className="w-full max-w-md mx-auto space-y-8">
<div className="relative rounded-2xl bg-zinc-900">
Expand Down Expand Up @@ -130,33 +141,32 @@ export default function ChooseTemplate({ templates, onThemeChange, onTemplateCha
</button>
</div>

{(templates[currentTemplate].src === '') ? (
<div className="flex justify-center items-center gap-4">
<button
type="button"
onClick={() => handleThemeChange("light")}
className={`w-8 h-8 rounded-full border-2 bg-white transition-all ${currentTheme === "light" ? "border-blue-500 scale-110" : "border-transparent"
}`}
aria-label="Light theme"
/>
<button
type="button"
onClick={() => handleThemeChange("dark")}
className={`w-8 h-8 rounded-full border-2 bg-black transition-all ${currentTheme === "dark" ? "border-blue-500 scale-110" : "border-transparent"
}`}
aria-label="Dark theme"
/>
</div>
{(templates[currentTemplate].src === '') ? (
<>
<button
type="button"
onClick={() => handleThemeChange("light")}
className={`w-8 h-8 rounded-full border-2 bg-white transition-all ${currentTheme === "light" ? "border-blue-500 scale-110" : "border-transparent"
}`}
aria-label="Light theme"
/>
<button
type="button"
onClick={() => handleThemeChange("dark")}
className={`w-8 h-8 rounded-full border-2 bg-black transition-all ${currentTheme === "dark" ? "border-blue-500 scale-110" : "border-transparent"
}`}
aria-label="Dark theme"
/>
</>
) : (
<div className="flex justify-center items-center gap-4">
<button
type="button"
className={`w-8 h-8 rounded-full border-2 bg-black transition-all bg-gradient-to-tr from-yellow-500 via-pink-500 to-blue-500 border-blue-500 scale-110"
}`}
className={`w-8 h-8 rounded-full border-2 bg-black transition-all ${getThemeStyle(templates[currentTemplate].id)}`}
aria-label="Special theme"
/>
</div>
)}
</div>
</div>
)
}
11 changes: 10 additions & 1 deletion src/app/form/Types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,13 @@ export interface Linkedin2Form {
theme: string;
}

export type FormDataTypes = Insta1Form | InstaSpecialForm | Linkedin1Form | Linkedin2Form;
export interface KakaopayForm {
template: string;
thumbnail?: string;
text?: string;
code: string;
email: string;
theme: string;
}

export type FormDataTypes = Insta1Form | InstaSpecialForm | Linkedin1Form | Linkedin2Form | KakaopayForm;
251 changes: 167 additions & 84 deletions src/app/form/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,17 @@ import { ImageProvider } from './ImageContext';
import { DisplayCroppedImage } from './CropImage';
import ProfilePictureUpload from './Profile';
import ChooseTemplate from './Template';
import { FormDataTypes, Insta1Form, InstaSpecialForm, Linkedin1Form, Linkedin2Form } from './Types';
import { FormDataTypes, Insta1Form, InstaSpecialForm, Linkedin1Form, Linkedin2Form, KakaopayForm } from './Types';
import { MessageCircleQuestion } from 'lucide-react';

const templates = [
{
id: 'kakaopay1',
name: 'KakaoPay: 로고가 가운데에 있는 템플릿',
src: '/kakaopay1.png',
dark: '',
light: '',
},
{
id: 'linkedin3',
name: 'LinkedIn: 가운데 정렬된 템플릿',
Expand Down Expand Up @@ -50,6 +58,12 @@ const FormPage = (): React.ReactElement => {
const [formData, setFormData] = useState<FormDataTypes>(() => ({} as FormDataTypes));
const [isSubmitting, setIsSubmitting] = useState(false);
const [errorMessage, setErrorMessage] = useState('');
const [showPopup, setShowPopup] = useState(false);

const handlePopupToggle = () => {
console.log('test', showPopup)
setShowPopup(prevState => !prevState);
};

const handleChange = (e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
const { name, value } = e.target;
Expand Down Expand Up @@ -115,6 +129,10 @@ const FormPage = (): React.ReactElement => {
return data.template === 'linkedin2' || data.template === 'linkedin3';
};

const isKakaoPayForm = (data: FormDataTypes): data is KakaopayForm => {
return data.template === 'kakaopay1';
}

return (
<div className="flex min-h-screen bg-zinc-900 text-zinc-100">
<div className="flex-1 flex items-center justify-center p-4">
Expand Down Expand Up @@ -147,7 +165,55 @@ const FormPage = (): React.ReactElement => {
/>
</div>
<div className="items-center space-x-2">
<label htmlFor="code" className="m-2 whitespace-nowrap text-sm font-medium">프로필 링크 <span className="text-red-500 font-semibold">*</span></label>
<label htmlFor="code" className="m-2 whitespace-nowrap text-sm font-medium">
{isKakaoPayForm(formData) ? (
<>
<span>
송금 QR 코드
</span>
<span className="text-red-500 font-semibold"> * </span>
<button
onClick={handlePopupToggle}
className="text-blue-500"
type="button"
>
<MessageCircleQuestion className="text-gray-400" />
</button>

{/* 팝업 표시 */}
{showPopup && (
<div className="fixed inset-0 flex flex-col gap-4 items-center justify-center bg-black bg-opacity-70 backdrop-blur-sm">
<video className="rounded-2xl w-64 object-cover" autoPlay loop muted>
<source src="/get_kakao_url_guide.mp4" type="video/mp4" />
Your browser does not support the video tag.
</video>

<div className="text-center">
<p className="font-semibold">
카톡 더보기 &gt; Kakao Pay &gt; 페이머니 &gt; 송금코드 &gt; 링크복사
</p>
<p className="text-gray-500">
복사한 송금 QR 링크를 이곳에 붙여넣기 해주세요.
</p>
</div>

<button
onClick={handlePopupToggle}
className="px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors"
type="button"
>
닫기
</button>
</div>
)}
</>
) : (
<>
프로필 링크
<span className="text-red-500 font-semibold"> *</span>
</>
)}
</label>
<input
id="code"
name="code"
Expand All @@ -159,89 +225,105 @@ const FormPage = (): React.ReactElement => {
/>
</div>

{/* Insta 폼 필드 */}
{isInstaForm(formData) && (
<>
<div className="items-center space-x-2">
<label htmlFor="id" className="m-2 whitespace-nowrap text-sm font-medium">아이디</label>
<input
id="id"
name="id"
value={formData.id || ''}
onChange={handleChange}
className="w-full p-2 rounded-md placeholder-zinc-600 bg-zinc-800 border-zinc-700 text-zinc-100"
/>
</div>
<div className="items-center space-x-2">
<label htmlFor="name" className="m-2 whitespace-nowrap text-sm font-medium">이름</label>
<input
id="name"
name="name"
value={formData.name || ''}
onChange={handleChange}
className="w-full p-2 rounded-md placeholder-zinc-600 bg-zinc-800 border-zinc-700 text-zinc-100"
/>
</div>
<div className="items-center space-x-2">
<label htmlFor="bio" className="m-2 whitespace-nowrap text-sm font-medium">소개</label>
<input
id="bio"
name="bio"
value={formData.bio || ''}
onChange={handleChange}
className="w-full p-2 rounded-md placeholder-zinc-600 bg-zinc-800 border-zinc-700 text-zinc-100"
/>
</div>
</>
)}
{/* Kakao Pay 폼 필드 */}
{isKakaoPayForm(formData) && (
<>
<div className="items-center space-x-2">
<label htmlFor="id" className="m-2 whitespace-nowrap text-sm font-medium">텍스트</label>
<input
id="text"
name="text"
value={formData.text || ''}
onChange={handleChange}
className="w-full p-2 rounded-md placeholder-zinc-600 bg-zinc-800 border-zinc-700 text-zinc-100"
/>
</div>
</>
)}

{/* LinkedIn 폼 필드 */}
{(isLinkedin1Form(formData) || isLinkedin2Form(formData)) && (
<>
<div className="items-center space-x-2">
<label htmlFor="name" className="m-2 whitespace-nowrap text-sm font-medium">이름</label>
<input
id="name"
name="name"
value={formData.name || ''}
onChange={handleChange}
className="w-full p-2 rounded-md placeholder-zinc-600 bg-zinc-800 border-zinc-700 text-zinc-100"
/>
</div>
<div className="items-center space-x-2">
<label htmlFor="role" className="m-2 whitespace-nowrap text-sm font-medium">직함</label>
<input
id="role"
name="role"
value={formData.role || ''}
onChange={handleChange}
className="w-full p-2 rounded-md placeholder-zinc-600 bg-zinc-800 border-zinc-700 text-zinc-100"
/>
</div>
<div className="items-center space-x-2">
<label htmlFor="company" className="m-2 whitespace-nowrap text-sm font-medium">회사</label>
<input
id="company"
name="company"
value={formData.company || ''}
onChange={handleChange}
className="w-full p-2 rounded-md placeholder-zinc-600 bg-zinc-800 border-zinc-700 text-zinc-100"
/>
</div>
{isLinkedin1Form(formData) && (
<div className="items-center space-x-2">
<label htmlFor="joinDate" className="m-2 whitespace-nowrap text-sm font-medium">근무 기간</label>
<input
id="joinDate"
name="joinDate"
value={formData.joinDate || ''}
onChange={handleChange}
className="w-full p-2 rounded-md placeholder-zinc-600 bg-zinc-800 border-zinc-700 text-zinc-100"
/>
</div>
)}
</>
)}
{/* Insta 폼 필드 */}
{isInstaForm(formData) && (
<>
<div className="items-center space-x-2">
<label htmlFor="id" className="m-2 whitespace-nowrap text-sm font-medium">아이디</label>
<input
id="id"
name="id"
value={formData.id || ''}
onChange={handleChange}
className="w-full p-2 rounded-md placeholder-zinc-600 bg-zinc-800 border-zinc-700 text-zinc-100"
/>
</div>
<div className="items-center space-x-2">
<label htmlFor="name" className="m-2 whitespace-nowrap text-sm font-medium">이름</label>
<input
id="name"
name="name"
value={formData.name || ''}
onChange={handleChange}
className="w-full p-2 rounded-md placeholder-zinc-600 bg-zinc-800 border-zinc-700 text-zinc-100"
/>
</div>
<div className="items-center space-x-2">
<label htmlFor="bio" className="m-2 whitespace-nowrap text-sm font-medium">소개</label>
<input
id="bio"
name="bio"
value={formData.bio || ''}
onChange={handleChange}
className="w-full p-2 rounded-md placeholder-zinc-600 bg-zinc-800 border-zinc-700 text-zinc-100"
/>
</div>
</>
)}

{/* LinkedIn 폼 필드 */}
{(isLinkedin1Form(formData) || isLinkedin2Form(formData)) && (
<>
<div className="items-center space-x-2">
<label htmlFor="name" className="m-2 whitespace-nowrap text-sm font-medium">이름</label>
<input
id="name"
name="name"
value={formData.name || ''}
onChange={handleChange}
className="w-full p-2 rounded-md placeholder-zinc-600 bg-zinc-800 border-zinc-700 text-zinc-100"
/>
</div>
<div className="items-center space-x-2">
<label htmlFor="role" className="m-2 whitespace-nowrap text-sm font-medium">직함</label>
<input
id="role"
name="role"
value={formData.role || ''}
onChange={handleChange}
className="w-full p-2 rounded-md placeholder-zinc-600 bg-zinc-800 border-zinc-700 text-zinc-100"
/>
</div>
<div className="items-center space-x-2">
<label htmlFor="company" className="m-2 whitespace-nowrap text-sm font-medium">회사</label>
<input
id="company"
name="company"
value={formData.company || ''}
onChange={handleChange}
className="w-full p-2 rounded-md placeholder-zinc-600 bg-zinc-800 border-zinc-700 text-zinc-100"
/>
</div>
{isLinkedin1Form(formData) && (
<div className="items-center space-x-2">
<label htmlFor="joinDate" className="m-2 whitespace-nowrap text-sm font-medium">근무 기간</label>
<input
id="joinDate"
name="joinDate"
value={formData.joinDate || ''}
onChange={handleChange}
className="w-full p-2 rounded-md placeholder-zinc-600 bg-zinc-800 border-zinc-700 text-zinc-100"
/>
</div>
)}
</>
)}

<div className="items-center justify-center">
<button
Expand All @@ -258,6 +340,7 @@ const FormPage = (): React.ReactElement => {
)}
</div>
</div>

</form>
</div>
</div>
Expand Down

0 comments on commit 33b2cfd

Please sign in to comment.