CreateNotebookDrawer.tsx 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import React, { useState } from 'react'
  2. import { X, Plus, ChevronRight } from 'lucide-react'
  3. import { CreateGroupData } from '../types'
  4. import { useLanguage } from '../contexts/LanguageContext'
  5. interface CreateNotebookDrawerProps {
  6. isOpen: boolean
  7. onClose: () => void
  8. onCreate: (data: CreateGroupData) => Promise<void>
  9. }
  10. export const CreateNotebookDrawer: React.FC<CreateNotebookDrawerProps> = ({
  11. isOpen,
  12. onClose,
  13. onCreate,
  14. }) => {
  15. const { t } = useLanguage()
  16. const [name, setName] = useState('')
  17. const [description, setDescription] = useState('')
  18. const [intro, setIntro] = useState('')
  19. const [isSubmitting, setIsSubmitting] = useState(false)
  20. const handleSubmit = async (e: React.FormEvent) => {
  21. e.preventDefault()
  22. if (!name.trim()) return
  23. try {
  24. setIsSubmitting(true)
  25. await onCreate({
  26. name: name.trim(),
  27. description: description.trim(),
  28. intro: intro.trim(),
  29. color: '#3b82f6', // Default color
  30. })
  31. // Reset form
  32. setName('')
  33. setDescription('')
  34. setIntro('')
  35. onClose()
  36. } catch (error) {
  37. console.error('Failed to create notebook:', error)
  38. alert(t('createFailedRetry'))
  39. } finally {
  40. setIsSubmitting(false)
  41. }
  42. }
  43. return (
  44. <>
  45. {/* Backdrop */}
  46. {isOpen && (
  47. <div
  48. className="fixed inset-0 bg-black/20 backdrop-blur-sm z-40 transition-opacity duration-300"
  49. onClick={onClose}
  50. />
  51. )}
  52. {/* Drawer */}
  53. <div
  54. className={`fixed right-0 top-0 h-full w-full max-w-md bg-white shadow-2xl z-50 transform transition-transform duration-300 ease-out ${isOpen ? 'translate-x-0' : 'translate-x-full'
  55. }`}
  56. >
  57. <div className="flex flex-col h-full">
  58. {/* Header */}
  59. <div className="flex items-center justify-between px-6 py-4 border-b bg-slate-50">
  60. <h2 className="text-xl font-semibold text-slate-800 flex items-center gap-2">
  61. <Plus className="w-6 h-6 text-blue-600" />
  62. {t('createNotebookTitle')}
  63. </h2>
  64. <button
  65. onClick={onClose}
  66. className="p-2 text-slate-400 hover:text-slate-600 hover:bg-slate-200 rounded-full transition-colors"
  67. >
  68. <ChevronRight size={24} />
  69. </button>
  70. </div>
  71. {/* Content */}
  72. <div className="flex-1 overflow-y-auto p-6">
  73. <form id="create-notebook-form" onSubmit={handleSubmit} className="space-y-6">
  74. <div>
  75. <label className="block text-sm font-medium text-slate-700 mb-1">
  76. {t('name')} <span className="text-red-500">*</span>
  77. </label>
  78. <input
  79. type="text"
  80. value={name}
  81. onChange={(e) => setName(e.target.value)}
  82. className="w-full px-4 py-3 border rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500 bg-slate-50"
  83. placeholder={t('namePlaceholder')}
  84. required
  85. autoFocus
  86. />
  87. <p className="mt-1 text-xs text-slate-500">{t('nameHelp')}</p>
  88. </div>
  89. <div>
  90. <label className="block text-sm font-medium text-slate-700 mb-1">
  91. {t('shortDescription')}
  92. </label>
  93. <input
  94. type="text"
  95. value={description}
  96. onChange={(e) => setDescription(e.target.value)}
  97. className="w-full px-4 py-3 border rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500 bg-slate-50"
  98. placeholder={t('descPlaceholder')}
  99. />
  100. </div>
  101. <div>
  102. <label className="block text-sm font-medium text-slate-700 mb-1">
  103. {t('detailedIntro')}
  104. </label>
  105. <textarea
  106. value={intro}
  107. onChange={(e) => setIntro(e.target.value)}
  108. className="w-full px-4 py-3 border rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500 bg-slate-50 h-64 resize-none leading-relaxed"
  109. placeholder={t('introPlaceholder')}
  110. />
  111. <p className="mt-1 text-xs text-slate-500">{t('introHelp')}</p>
  112. </div>
  113. </form>
  114. </div>
  115. {/* Footer */}
  116. <div className="p-6 border-t bg-slate-50">
  117. <button
  118. type="submit"
  119. form="create-notebook-form"
  120. disabled={isSubmitting || !name.trim()}
  121. className="w-full flex items-center justify-center gap-2 px-6 py-3 bg-blue-600 text-white font-medium rounded-xl hover:bg-blue-700 active:scale-[0.98] transition-all disabled:opacity-50 disabled:cursor-not-allowed shadow-lg shadow-blue-600/20"
  122. >
  123. <Plus size={20} />
  124. {isSubmitting ? t('creating') : t('createNow')}
  125. </button>
  126. </div>
  127. </div>
  128. </div>
  129. </>
  130. )
  131. }