| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- 'use client';
- import { useEffect, useState, type CSSProperties } from 'react';
- import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
- import { faPlay } from '@fortawesome/free-solid-svg-icons';
- import {
- DONATION_AMOUNT_MIN, DONATION_AMOUNT_MAX, DONATION_AMOUNT_STEP, DONATION_AMOUNT_DEFAULT
- } from '@/constants/donation';
- import type { FormState } from '../types';
- type Props = {
- form: FormState;
- };
- export default function GoalPreviewPanel({ form }: Props) {
- const [previewAmount, setPreviewAmount] = useState(DONATION_AMOUNT_DEFAULT);
- const [simulatedAmount, setSimulatedAmount] = useState(0);
- // form.startAmount가 변경되면 시뮬레이션 누적값 초기화
- useEffect(() => {
- setSimulatedAmount(0);
- }, [form.startAmount]);
- const currentAmount = form.startAmount + simulatedAmount;
- const percent = form.targetAmount > 0 ? Math.min((currentAmount / form.targetAmount) * 100, 100) : 0;
- const titleStyle = {
- '--title-font': form.titleFontFamily || 'inherit',
- '--title-size': `${form.titleFontSizePx}px`,
- '--title-color': form.titleFontColor
- } as CSSProperties;
- const barWrapStyle = {
- '--bar-height': `${form.barHeightPx}px`,
- '--bar-bg': form.barBackgroundColor
- } as CSSProperties;
- const barFillStyle = {
- '--bar-percent': `${percent}%`,
- '--bar-color': form.barColor
- } as CSSProperties;
- const amountStyle = {
- '--amount-font': form.amountFontFamily || 'inherit',
- '--amount-size': `${form.amountFontSizePx}px`,
- '--amount-color': form.amountFontColor
- } as CSSProperties;
- const handlePreview = () => {
- setSimulatedAmount(prev => prev + (previewAmount || DONATION_AMOUNT_DEFAULT));
- };
- const handleReset = () => {
- setSimulatedAmount(0);
- };
- return (
- <aside className="goal-config__preview-panel">
- <div className="goal-config__widget">
- <div className="goal-config__widget-label">미리보기</div>
- <div className="goal-config__widget-body">
- <div className="goal-preview">
- <div className="goal-preview__title" style={titleStyle}>
- {form.title || '후원 목표'}
- </div>
- <div className="goal-preview__bar-wrap" style={barWrapStyle}>
- <div className="goal-preview__bar-fill" style={barFillStyle} />
- <div className="goal-preview__amount" style={amountStyle}>
- {currentAmount.toLocaleString()}원 / {form.targetAmount.toLocaleString()}원
- {form.isShowPercent && (
- <span className="goal-preview__percent">
- {' '}({Math.round(percent)}%)
- </span>
- )}
- </div>
- </div>
- </div>
- </div>
- </div>
- <fieldset className="goal-config__fieldset">
- <legend className="goal-config__legend">미리보기</legend>
- <div className="goal-config__preview-form">
- <div className="goal-config__field">
- <label htmlFor="goal-preview-amount" className="goal-config__field-label">후원 금액 (원)</label>
- <input
- id="goal-preview-amount"
- type="number"
- className="goal-config__input"
- min={DONATION_AMOUNT_MIN}
- max={DONATION_AMOUNT_MAX}
- step={DONATION_AMOUNT_STEP}
- value={previewAmount}
- onChange={e => setPreviewAmount(parseInt(e.target.value) || DONATION_AMOUNT_DEFAULT)}
- />
- </div>
- <div className="goal-config__preview-actions">
- <button
- type="button"
- className="goal-config__btn goal-config__btn--primary goal-config__preview-btn"
- onClick={handlePreview}
- >
- <FontAwesomeIcon icon={faPlay} />
- 미리보기
- </button>
- <button
- type="button"
- className="goal-config__btn"
- onClick={handleReset}
- disabled={simulatedAmount === 0}
- >
- 초기화
- </button>
- </div>
- {simulatedAmount > 0 && (
- <p className="goal-config__field-hint">누적: +{simulatedAmount.toLocaleString()}원</p>
- )}
- </div>
- </fieldset>
- </aside>
- );
- }
|