page.tsx 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. 'use client';
  2. import { useState } from 'react';
  3. import { fetchApi } from '@/lib/utils/client';
  4. import { NoteSendRequest } from '@/types/request/note/send';
  5. export default function NoteSendPage() {
  6. const [receiverID, setReceiverID] = useState('');
  7. const [title, setTitle] = useState('');
  8. const [content, setContent] = useState('');
  9. const [sending, setSending] = useState(false);
  10. const [result, setResult] = useState<{ success: boolean; message: string }|null>(null);
  11. const handleSend = async () => {
  12. if (!receiverID || !title.trim() || !content.trim()) {
  13. setResult({ success: false, message: '모든 필드를 입력해주세요.' });
  14. return;
  15. }
  16. setSending(true);
  17. setResult(null);
  18. try {
  19. const res = await fetchApi('/api/note/send', {
  20. method: 'POST',
  21. body: {
  22. receiverMemberID: parseInt(receiverID),
  23. title: title.trim(),
  24. content: content.trim()
  25. } as NoteSendRequest
  26. });
  27. if (res.success) {
  28. setResult({ success: true, message: '쪽지를 보냈습니다.' });
  29. setTitle('');
  30. setContent('');
  31. } else {
  32. setResult({ success: false, message: res.message || '전송에 실패했습니다.' });
  33. }
  34. } catch (e: unknown) {
  35. const message = e instanceof Error ? e.message : '전송에 실패했습니다.';
  36. setResult({ success: false, message });
  37. }
  38. setSending(false);
  39. };
  40. return (
  41. <div className="container mx-auto max-w-lg p-4">
  42. <h1 className="text-xl font-bold mb-4">쪽지 보내기</h1>
  43. {result && (
  44. <div className={`p-3 rounded-lg mb-4 text-sm ${result.success ? 'bg-green-50 text-green-700 dark:bg-green-950 dark:text-green-300' : 'bg-red-50 text-red-700 dark:bg-red-950 dark:text-red-300'}`}>
  45. {result.message}
  46. </div>
  47. )}
  48. <div className="flex flex-col gap-3">
  49. <div>
  50. <label className="text-sm font-medium mb-1 block">받는 사람 (회원 ID)</label>
  51. <input type="number" value={receiverID} onChange={e => setReceiverID(e.target.value)} placeholder="회원 ID" className="w-full border rounded-lg px-3 py-2 text-sm" />
  52. </div>
  53. <div>
  54. <label className="text-sm font-medium mb-1 block">제목</label>
  55. <input type="text" value={title} onChange={e => setTitle(e.target.value)} maxLength={200} placeholder="제목을 입력하세요" className="w-full border rounded-lg px-3 py-2 text-sm" />
  56. </div>
  57. <div>
  58. <label className="text-sm font-medium mb-1 block">내용</label>
  59. <textarea value={content} onChange={e => setContent(e.target.value)} maxLength={2000} rows={6} placeholder="내용을 입력하세요" className="w-full border rounded-lg px-3 py-2 text-sm resize-none" />
  60. <div className="text-xs text-gray-400 text-right mt-1">{content.length}/2000</div>
  61. </div>
  62. <button type="button" onClick={handleSend} disabled={sending} className="w-full bg-blue-500 text-white py-2.5 rounded-lg font-medium text-sm hover:bg-blue-600 disabled:opacity-50">
  63. {sending ? '전송 중...' : '보내기'}
  64. </button>
  65. </div>
  66. <div className="mt-4 text-center">
  67. <a href="/note/inbox" className="text-sm text-blue-500 hover:underline">받은 쪽지함으로 돌아가기</a>
  68. </div>
  69. </div>
  70. );
  71. }