RankPreviewPanel.tsx 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. 'use client';
  2. import type { FormState } from '../types';
  3. import { MOCK_RANKING } from '../constants';
  4. type Props = {
  5. form: FormState;
  6. };
  7. /** 순위별 폰트 스타일 반환 (1~3등은 커스텀, 나머지는 기본) */
  8. const getRankStyle = (rank: number, form: FormState): React.CSSProperties => {
  9. if (rank === 1) {
  10. return {
  11. fontFamily: form.rank1FontFamily || undefined,
  12. fontSize: `${form.rank1FontSizePx}px`,
  13. color: form.rank1FontColor
  14. };
  15. }
  16. if (rank === 2) {
  17. return {
  18. fontFamily: form.rank2FontFamily || undefined,
  19. fontSize: `${form.rank2FontSizePx}px`,
  20. color: form.rank2FontColor
  21. };
  22. }
  23. if (rank === 3) {
  24. return {
  25. fontFamily: form.rank3FontFamily || undefined,
  26. fontSize: `${form.rank3FontSizePx}px`,
  27. color: form.rank3FontColor
  28. };
  29. }
  30. return {};
  31. };
  32. export default function RankPreviewPanel({ form }: Props) {
  33. const visibleRanking = MOCK_RANKING.slice(0, form.maxRankCount);
  34. const titleStyle: React.CSSProperties = {
  35. fontFamily: form.titleFontFamily || undefined,
  36. fontSize: `${form.titleFontSizePx}px`,
  37. color: form.titleFontColor
  38. };
  39. return (
  40. <aside className="rank-config__preview-panel">
  41. <div className="rank-config__widget">
  42. <div className="rank-config__widget-label">미리보기</div>
  43. <div className={`rank-config__widget-body rank-config__widget-body--${['basic', 'dark', 'minimal'][form.theme] ?? 'basic'}`}>
  44. <div className="rank-preview">
  45. <div className="rank-preview__title" style={titleStyle}>
  46. {form.title || '후원 순위'}
  47. </div>
  48. <div className="rank-preview__list">
  49. {visibleRanking.map(item => {
  50. const badgeClass = item.rank <= 3 ? `rank-preview__badge--${item.rank}` : 'rank-preview__badge--default';
  51. const nameStyle = getRankStyle(item.rank, form);
  52. return (
  53. <div key={item.rank} className={`rank-preview__item rank-preview__item--${item.rank}`}>
  54. <div className={`rank-preview__badge ${badgeClass}`}>{item.rank}</div>
  55. {form.isShowMemberIcon && (
  56. <div className="rank-preview__member-icon" />
  57. )}
  58. {form.isShowGradeIcon && (
  59. <div className="rank-preview__grade-icon" />
  60. )}
  61. <div className="rank-preview__name" style={nameStyle}>
  62. {item.sponsorName}
  63. </div>
  64. <div className="rank-preview__meta">
  65. {form.isShowAmount && (
  66. <span className="rank-preview__amount" style={nameStyle}>
  67. {item.totalAmount.toLocaleString()}원
  68. </span>
  69. )}
  70. {form.isShowDonationCount && (
  71. <span className="rank-preview__count">
  72. {item.donationCount}회
  73. </span>
  74. )}
  75. </div>
  76. </div>
  77. );
  78. })}
  79. {visibleRanking.length === 0 && (
  80. <div className="rank-preview__empty">순위 데이터 없음</div>
  81. )}
  82. </div>
  83. </div>
  84. </div>
  85. </div>
  86. </aside>
  87. );
  88. }