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
29 changes: 22 additions & 7 deletions src/domains/mypage/components/EditNickName.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import TextButton from '@/shared/components/button/TextButton';
import Input from '@/shared/components/Input-box/Input';
import ModalLayout from '@/shared/components/modal-pop/ModalLayout';
import { useToast } from '@/shared/hook/useToast';
import { Dispatch, SetStateAction } from 'react';
import { Dispatch, SetStateAction, useEffect, useState } from 'react';

interface Props {
open: boolean;
onClose: () => void;
nickname: string;
setNickName: (v: string) => void;
setIsOpen: Dispatch<SetStateAction<boolean>>;
editNickName: string;
Expand All @@ -18,14 +19,22 @@ interface Props {
function EditNickName({
open,
onClose,
nickname,
setNickName,
setIsOpen,
editNickName,
setEditNickName,
}: Props) {
const { toastError } = useToast();
const [defaultNickname, setDefaultNickname] = useState(nickname);
const { toastSuccess, toastError } = useToast();

useEffect(() => {
setEditNickName(nickname);
setDefaultNickname(nickname);
}, [nickname, setEditNickName]);

const handlesave = async () => {
if (editNickName.length <= 1) {
if (editNickName.length <= 1 || editNickName.length >= 8) {
toastError('닉네임은 2글자 이상 입력해야합니다');
return;
}
Expand All @@ -43,16 +52,21 @@ function EditNickName({
}),
});
await setIsOpen(false);
toastSuccess('닉네임이 저장되었습니다.');
};

const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setEditNickName(e.target.value);
};

const handleDefaultNickname = () => {
setEditNickName(defaultNickname);
};

return (
<ModalLayout
title="닉네임 수정"
description="닉네임을 수정해주세요."
title="닉네임 변경"
description="닉네임을 변경해주세요."
open={open}
onClose={onClose}
buttons={
Expand All @@ -67,11 +81,12 @@ function EditNickName({
</label>
<Input
onChange={(e) => handleChange(e)}
placeholder="8글자 이내로 입력해주세요"
placeholder="닉네임을 2글자 이상 8글자 이내로 입력해주세요"
id="editNickName"
value={editNickName}
className="w-full"
/>
<TextButton onClick={onClose}>기존 이름으로 돌아가기</TextButton>
<TextButton onClick={handleDefaultNickname}>전 닉네임으로 돌아가기</TextButton>
</div>
</ModalLayout>
);
Expand Down
57 changes: 29 additions & 28 deletions src/domains/mypage/components/ToggleBtn.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
'use client';
import { getApi } from '@/app/api/config/appConfig';
import { useToast } from '@/shared/hook/useToast';
import clsx from 'clsx';
import { useEffect, useState } from 'react';
import AlarmConfirm from './pages/my-alarm/AlarmConfirm';

function ToggleBtn() {
const [isClick, setIsClick] = useState<boolean | null>(null);
const { toastSuccess } = useToast();
const [isAlarm, setIsAlarm] = useState<boolean | null>(null);
const [isClick, setIsClick] = useState<boolean>(false);

useEffect(() => {
const fetchToggle = async () => {
Expand All @@ -16,7 +16,8 @@ function ToggleBtn() {
credentials: 'include',
});
const json = await res.json();
setIsClick(json.data.enabled);
console.log(json);
setIsAlarm(json.data.enabled);
} catch {
console.error();
}
Expand All @@ -25,36 +26,36 @@ function ToggleBtn() {
}, []);

const handleClick = async () => {
if (isClick === null) return;
const next = !isClick;
setIsClick(next);

await fetch(`${getApi}/me/notification-setting`, {
method: 'PATCH',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
enabled: next,
}),
});
next ? toastSuccess('알림이 설정되었습니다.') : toastSuccess('알림이 해제되었습니다');
setIsClick(true);
};

return (
<button
className={clsx(
'rounded-full flex py-0.5 pl-[2px] w-17 h-7 duration-300',
isClick ? 'bg-tertiary' : 'bg-white'
<div>
{isClick && (
<AlarmConfirm
open={isClick}
onClose={() => setIsClick(false)}
state={isAlarm}
cancle={() => setIsClick(isClick)}
setIsAlarm={setIsAlarm}
setIsClick={setIsClick}
/>
)}
onClick={handleClick}
>
<div
<button
className={clsx(
'rounded-full w-6 h-6 duration-300',
isClick ? 'bg-secondary translate-x-10' : 'bg-gray-dark'
'rounded-full flex py-0.5 pl-[2px] w-17 h-7 duration-300',
isAlarm ? 'bg-tertiary' : 'bg-white'
)}
></div>
</button>
onClick={handleClick}
>
<div
className={clsx(
'rounded-full w-6 h-6 duration-300',
isAlarm ? 'bg-secondary translate-x-10' : 'bg-gray-dark'
)}
></div>
</button>
</div>
);
}
export default ToggleBtn;
27 changes: 27 additions & 0 deletions src/domains/mypage/components/pages/my-alarm/AlarmConfirm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useConfirm } from '@/domains/mypage/hook/useConfirm';
import ConfirmModal from '@/shared/components/modal-pop/ConfirmModal';
import { Dispatch, SetStateAction } from 'react';

interface Props {
open: boolean;
onClose: () => void;
state: boolean | null;
cancle: () => void;
setIsAlarm: Dispatch<SetStateAction<boolean | null>>;
setIsClick: Dispatch<SetStateAction<boolean>>;
}

function AlarmConfirm({ open, onClose, state, cancle, setIsAlarm, setIsClick }: Props) {
const { patchAlarm } = useConfirm(state, setIsAlarm, setIsClick);

return (
<ConfirmModal
open={open}
onClose={onClose}
description={state ? '알림을 해제하시겠습니까?' : '알림을 설정하시겠습니까?'}
onConfirm={patchAlarm}
onCancel={cancle}
></ConfirmModal>
);
}
export default AlarmConfirm;
18 changes: 10 additions & 8 deletions src/domains/mypage/components/pages/my-bar/MyBar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use client';
import { getApi } from '@/app/api/config/appConfig';
import CocktailCard from '@/domains/shared/components/cocktail-card/CocktailCard';
import Link from 'next/link';
import { useEffect, useState } from 'react';

interface MyCocktail {
Expand Down Expand Up @@ -37,14 +38,15 @@ function MyBar() {
"
>
{myCocktail.map(({ cocktailId, cocktailName, imageUrl }) => (
<CocktailCard
key={cocktailId}
src={imageUrl}
textSize1="text-xl"
name={cocktailName}
nameKo="올드 패션드"
keep={false}
></CocktailCard>
<Link href={`/recipe/${cocktailId}`} key={cocktailId}>
<CocktailCard
src={imageUrl}
textSize1="text-xl"
name={cocktailName}
nameKo="올드 패션드"
keep={false}
></CocktailCard>
</Link>
))}
</div>
) : (
Expand Down
27 changes: 27 additions & 0 deletions src/domains/mypage/hook/useConfirm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { getApi } from '@/app/api/config/appConfig';
import { useToast } from '@/shared/hook/useToast';
import { Dispatch, SetStateAction } from 'react';

export function useConfirm(
state: boolean | null,
setIsAlarm: Dispatch<SetStateAction<boolean | null>>,
setIsClick: Dispatch<SetStateAction<boolean>>
) {
const { toastSuccess } = useToast();
const next = !state;
const patchAlarm = async () => {
await fetch(`${getApi}/me/notification-setting`, {
method: 'PATCH',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
enabled: next,
}),
});
setIsAlarm(next);
setIsClick(false);

(await next) ? toastSuccess('알림이 설정되었습니다.') : toastSuccess('알림이 해제되었습니다');
};
return { patchAlarm };
}
19 changes: 17 additions & 2 deletions src/domains/mypage/main/MyAbv.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@ function MyAbv({ abv }: { abv: number }) {
const viewPoint = isMd ? 'web' : 'mobileLongText';
const fixedAbv = abv.toFixed(1);

const t = Math.min(1, Math.max(0, abv / 100));

// HEX → RGB
const from = [255, 202, 141]; // FFCA8D
const to = [250, 36, 36]; // FA2424

// RGB
const r = Math.round(from[0] + (to[0] - from[0]) * t);
const g = Math.round(from[1] + (to[1] - from[1]) * t);
const b = Math.round(from[2] + (to[2] - from[2]) * t);
const color = `rgb(${r}, ${g}, ${b})`;

return (
<dl className="flex justify-between items-center text-gray-dark gap-2">
<dt className="flex gap-1 items-center">
Expand All @@ -22,8 +34,11 @@ function MyAbv({ abv }: { abv: number }) {
<Help />
</ToolTip>
</dt>
<dd className="text-base">
<span className="text-2xl md:text-4xl font-bold">{fixedAbv}</span>%
<dd className="text-base flex gap-[2px] items-end">
<span className="text-2xl md:text-4xl font-bold" style={{ color }}>
{fixedAbv}
</span>
%
</dd>
</dl>
);
Expand Down
10 changes: 3 additions & 7 deletions src/domains/mypage/main/MySetting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import EditNickName from '@/domains/mypage/components/EditNickName';
import ToggleBtn from '@/domains/mypage/components/ToggleBtn';
import WithdrawModal from '@/domains/mypage/components/WithdrawModal';
import Button from '@/shared/components/button/Button';
import TextButton from '@/shared/components/button/TextButton';
import { useEffect, useState } from 'react';
import useFetchProfile from '../api/fetchProfile';
Expand All @@ -26,6 +25,7 @@ function MySetting() {
<section className="flex flex-col h-80 md:h-100 lg:h-125 justify-between">
{isOpen && (
<EditNickName
nickname={nickname ?? ''}
setIsOpen={setIsOpen}
editNickName={editNickName}
setEditNickName={setEditNickName}
Expand All @@ -42,16 +42,12 @@ function MySetting() {
</div>
<div className="flex justify-between py-5">
<h2>알람설정</h2>

<ToggleBtn />
</div>
</div>
<div className="flex justify-between items-center">
<div className="flex justify-end items-center">
<TextButton onClick={() => setIsQuit(!isQuit)}>회원탈퇴</TextButton>

<div className="flex gap-2 ">
<Button color="purple">취소</Button>
<Button>변경상태 저장</Button>
</div>
</div>
</section>
);
Expand Down
6 changes: 3 additions & 3 deletions src/domains/recipe/details/DetailItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,16 @@ function DetailItem({ name, nameKo, story, src, abv, glassType }: Props) {
<div className="flex flex-col gap-1 items-center md:items-end md:w-1/2">
<span>{alcoholTitle && <Label title={alcoholTitle} />}</span>
<h2 className="flex flex-col gap-2">
<span className="w-fit font-serif font-bold text-right text-3xl lg:text-4xl text-secondary ">
<span className="w-fit font-serif font-bold text-center md:text-right text-3xl lg:text-4xl text-secondary ">
{name}
</span>
<span className="font-serif font-bold text-right text-xl lg:whitespace-nowrap lg:text-4xl text-secondary">
<span className="font-serif font-bold text-center md:text-right text-xl lg:whitespace-nowrap lg:text-4xl text-secondary">
{nameKo}
</span>
</h2>
</div>

<p className=" text-base self-center w-3/4 md:text-sm md:self-end text-secondary md:w-70 lg:text-base lg:w-100">
<p className=" text-base self-center md:w-1/2 md:text-sm md:self-end text-secondary lg:text-base lg:w-100">
{story}
</p>

Expand Down
2 changes: 1 addition & 1 deletion src/domains/shared/components/abv-graph/AbvGraph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ function AbvGraph({ max, abv, type = 'cocktail' }: Props) {

const bandClass = clsx(
'h-full rounded-full transition-[width] duration-500',
'bg-gradient-to-r from-amber-300 to-red-500', // 기본 그라데이션
'bg-gradient-to-r from-[#FFCA8D] to-[#FA2424]', // 기본 그라데이션
pct >= 80 && 'shadow-[0_0_12px_rgba(250,36,36,0.45)]'
);

Expand Down
4 changes: 4 additions & 0 deletions src/domains/shared/components/keep/Keep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import KeepIcon from '@/shared/assets/icons/keep_36.svg';
import KeepIconActive from '@/shared/assets/icons/keep_active_36.svg';
import { useState } from 'react';
import { deleteKeep, postKeep } from '../../api/keep/keep';
import { useToast } from '@/shared/hook/useToast';

interface Props {
className?: string;
Expand All @@ -13,6 +14,7 @@ interface Props {
// 만약 타입 안맞는다면 그냥 두셔도 됩니다.

function Keep({ className, cocktailId }: Props) {
const { toastSuccess } = useToast();
const [isClick, setIsClick] = useState(false);

const handleClick = async (e: React.MouseEvent<HTMLButtonElement>) => {
Expand All @@ -25,8 +27,10 @@ function Keep({ className, cocktailId }: Props) {
if (!cocktailId) return;
if (!isClick) {
await postKeep(cocktailId);
toastSuccess('저장에 성공하셨습니다.');
} else {
await deleteKeep(cocktailId);
toastSuccess('저장을 취소하셨습니다.');
}
} catch (err) {
console.error(err);
Expand Down
4 changes: 2 additions & 2 deletions src/shared/components/select-box/SelectBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ function SelectBox({ id, groupKey, ref, option, title, value, onChange, use }: P
</button>

<ul
className={`w-30 text-gray-dark p-2 rounded-xl z-99 duration-200 absolute transition-all
className={`w-fit min-w-30 text-gray-dark p-2 rounded-xl z-99 duration-200 absolute transition-all
${
groupKey
? localOpen
Expand All @@ -104,7 +104,7 @@ function SelectBox({ id, groupKey, ref, option, title, value, onChange, use }: P
<li
key={v + i}
role="option"
className="cursor-pointer p-1 hover:bg-secondary aria-selected:bg-secondary"
className="cursor-pointer whitespace-nowrap p-1 hover:bg-secondary aria-selected:bg-secondary"
onClick={() => handleChoose(v)}
aria-selected={v === select}
>
Expand Down