diff --git a/src/components/forms/combined/CombinedResourceForm.js b/src/components/forms/combined/CombinedResourceForm.js index c6ea3c1..558437f 100644 --- a/src/components/forms/combined/CombinedResourceForm.js +++ b/src/components/forms/combined/CombinedResourceForm.js @@ -1,19 +1,17 @@ import React, { useState, useEffect, useCallback } from 'react'; import axios from 'axios'; -import { useRouter } from 'next/router'; import { InputText } from 'primereact/inputtext'; import { InputTextarea } from 'primereact/inputtextarea'; import { InputNumber } from 'primereact/inputnumber'; import { InputSwitch } from 'primereact/inputswitch'; import GenericButton from '@/components/buttons/GenericButton'; -import { useToast } from '@/hooks/useToast'; +import { useRouter } from 'next/router'; import { useSession } from 'next-auth/react'; -import dynamic from 'next/dynamic'; -import { Tooltip } from 'primereact/tooltip'; +import { useToast } from '@/hooks/useToast'; import 'primeicons/primeicons.css'; +import { Tooltip } from 'primereact/tooltip'; import 'primereact/resources/primereact.min.css'; - -const MDEditor = dynamic(() => import('@uiw/react-md-editor'), { ssr: false }); +import MarkdownEditor from '@/components/markdown/MarkdownEditor'; const CDN_ENDPOINT = process.env.NEXT_PUBLIC_CDN_ENDPOINT; @@ -199,9 +197,7 @@ const CombinedResourceForm = () => {
Content -
- -
+
diff --git a/src/components/forms/combined/EditDraftCombinedResourceForm.js b/src/components/forms/combined/EditDraftCombinedResourceForm.js index 832af72..4daa782 100644 --- a/src/components/forms/combined/EditDraftCombinedResourceForm.js +++ b/src/components/forms/combined/EditDraftCombinedResourceForm.js @@ -1,19 +1,17 @@ import React, { useState, useEffect, useCallback } from 'react'; import axios from 'axios'; -import { useRouter } from 'next/router'; import { InputText } from 'primereact/inputtext'; import { InputTextarea } from 'primereact/inputtextarea'; import { InputNumber } from 'primereact/inputnumber'; import { InputSwitch } from 'primereact/inputswitch'; import GenericButton from '@/components/buttons/GenericButton'; -import { useToast } from '@/hooks/useToast'; +import { useRouter } from 'next/router'; import { useSession } from 'next-auth/react'; -import dynamic from 'next/dynamic'; -import { Tooltip } from 'primereact/tooltip'; +import { useToast } from '@/hooks/useToast'; import 'primeicons/primeicons.css'; +import { Tooltip } from 'primereact/tooltip'; import 'primereact/resources/primereact.min.css'; - -const MDEditor = dynamic(() => import('@uiw/react-md-editor'), { ssr: false }); +import MarkdownEditor from '@/components/markdown/MarkdownEditor'; const CDN_ENDPOINT = process.env.NEXT_PUBLIC_CDN_ENDPOINT; @@ -242,9 +240,7 @@ const EditDraftCombinedResourceForm = ({ draft }) => {
Content -
- -
+
diff --git a/src/components/forms/combined/EditPublishedCombinedResourceForm.js b/src/components/forms/combined/EditPublishedCombinedResourceForm.js index d113993..930949a 100644 --- a/src/components/forms/combined/EditPublishedCombinedResourceForm.js +++ b/src/components/forms/combined/EditPublishedCombinedResourceForm.js @@ -1,23 +1,22 @@ import React, { useState, useEffect, useCallback } from 'react'; import axios from 'axios'; -import { useRouter } from 'next/router'; -import { useToast } from '@/hooks/useToast'; -import { useSession } from 'next-auth/react'; -import { useNDKContext } from '@/context/NDKContext'; -import GenericButton from '@/components/buttons/GenericButton'; -import { NDKEvent } from '@nostr-dev-kit/ndk'; -import { validateEvent } from '@/utils/nostr'; import { InputText } from 'primereact/inputtext'; import { InputTextarea } from 'primereact/inputtextarea'; import { InputNumber } from 'primereact/inputnumber'; import { InputSwitch } from 'primereact/inputswitch'; +import GenericButton from '@/components/buttons/GenericButton'; +import { useRouter } from 'next/router'; +import { useSession } from 'next-auth/react'; +import { useToast } from '@/hooks/useToast'; +import { useNDKContext } from '@/context/NDKContext'; +import { NDKEvent } from '@nostr-dev-kit/ndk'; +import { validateEvent } from '@/utils/nostr'; import { useEncryptContent } from '@/hooks/encryption/useEncryptContent'; import MoreInfo from '@/components/MoreInfo'; -import dynamic from 'next/dynamic'; - -const MDEditor = dynamic(() => import('@uiw/react-md-editor'), { - ssr: false, -}); +import 'primeicons/primeicons.css'; +import { Tooltip } from 'primereact/tooltip'; +import 'primereact/resources/primereact.min.css'; +import MarkdownEditor from '@/components/markdown/MarkdownEditor'; const EditPublishedCombinedResourceForm = ({ event }) => { const router = useRouter(); @@ -220,9 +219,7 @@ const EditPublishedCombinedResourceForm = ({ event }) => {
Video Embed -
- -
+ You can customize your video embed using markdown or HTML. For example, paste iframe embeds from YouTube or Vimeo, or use video tags for direct video files. @@ -239,9 +236,7 @@ const EditPublishedCombinedResourceForm = ({ event }) => {
Content -
- -
+
diff --git a/src/components/forms/course/embedded/EmbeddedDocumentForm.js b/src/components/forms/course/embedded/EmbeddedDocumentForm.js index ffc6e05..53bbc26 100644 --- a/src/components/forms/course/embedded/EmbeddedDocumentForm.js +++ b/src/components/forms/course/embedded/EmbeddedDocumentForm.js @@ -1,21 +1,20 @@ import React, { useState, useEffect, useCallback } from 'react'; +import axios from 'axios'; import { InputText } from 'primereact/inputtext'; +import { InputTextarea } from 'primereact/inputtextarea'; import { InputNumber } from 'primereact/inputnumber'; import { InputSwitch } from 'primereact/inputswitch'; +import { Calendar } from 'primereact/calendar'; import GenericButton from '@/components/buttons/GenericButton'; +import { useRouter } from 'next/router'; import { useSession } from 'next-auth/react'; import { useToast } from '@/hooks/useToast'; import { useNDKContext } from '@/context/NDKContext'; import { NDKEvent } from '@nostr-dev-kit/ndk'; -import dynamic from 'next/dynamic'; -import { useEncryptContent } from '@/hooks/encryption/useEncryptContent'; - -const MDEditor = dynamic(() => import('@uiw/react-md-editor'), { - ssr: false, -}); import 'primeicons/primeicons.css'; -import { Tooltip } from 'primereact/tooltip'; import 'primereact/resources/primereact.min.css'; +import { useEncryptContent } from '@/hooks/encryption/useEncryptContent'; +import MarkdownEditor from '@/components/markdown/MarkdownEditor'; const EmbeddedDocumentForm = ({ draft = null, isPublished = false, onSave, isPaid }) => { const [title, setTitle] = useState(draft?.title || ''); @@ -183,9 +182,7 @@ const EmbeddedDocumentForm = ({ draft = null, isPublished = false, onSave, isPai
Content -
- -
+
@@ -219,7 +216,6 @@ const EmbeddedDocumentForm = ({ draft = null, isPublished = false, onSave, isPai
-
{topics.map((topic, index) => ( diff --git a/src/components/forms/document/DocumentForm.js b/src/components/forms/document/DocumentForm.js index 8ffea2e..f48ea41 100644 --- a/src/components/forms/document/DocumentForm.js +++ b/src/components/forms/document/DocumentForm.js @@ -8,14 +8,10 @@ import GenericButton from '@/components/buttons/GenericButton'; import { useRouter } from 'next/router'; import { useSession } from 'next-auth/react'; import { useToast } from '@/hooks/useToast'; -import dynamic from 'next/dynamic'; -import 'primeicons/primeicons.css'; import { Tooltip } from 'primereact/tooltip'; +import 'primeicons/primeicons.css'; import 'primereact/resources/primereact.min.css'; - -const MDEditor = dynamic(() => import('@uiw/react-md-editor'), { - ssr: false, -}); +import MarkdownEditor from '@/components/markdown/MarkdownEditor'; const DocumentForm = () => { const [title, setTitle] = useState(''); @@ -149,9 +145,11 @@ const DocumentForm = () => {
Content -
- -
+
diff --git a/src/components/forms/document/EditDraftDocumentForm.js b/src/components/forms/document/EditDraftDocumentForm.js index 67de952..bcc1f67 100644 --- a/src/components/forms/document/EditDraftDocumentForm.js +++ b/src/components/forms/document/EditDraftDocumentForm.js @@ -8,10 +8,10 @@ import GenericButton from '@/components/buttons/GenericButton'; import { useRouter } from 'next/router'; import { useSession } from 'next-auth/react'; import { useToast } from '@/hooks/useToast'; -import dynamic from 'next/dynamic'; +import 'primeicons/primeicons.css'; import { Tooltip } from 'primereact/tooltip'; - -const MDEditor = dynamic(() => import('@uiw/react-md-editor'), { ssr: false }); +import 'primereact/resources/primereact.min.css'; +import MarkdownEditor from '@/components/markdown/MarkdownEditor'; const EditDraftDocumentForm = ({ draft }) => { const [title, setTitle] = useState(draft?.title || ''); @@ -143,9 +143,7 @@ const EditDraftDocumentForm = ({ draft }) => {
Content -
- -
+
diff --git a/src/components/forms/document/EditPublishedDocumentForm.js b/src/components/forms/document/EditPublishedDocumentForm.js index 7a64b93..46fb0f9 100644 --- a/src/components/forms/document/EditPublishedDocumentForm.js +++ b/src/components/forms/document/EditPublishedDocumentForm.js @@ -1,21 +1,21 @@ import React, { useState, useEffect, useCallback } from 'react'; import axios from 'axios'; -import { useRouter } from 'next/router'; -import { useToast } from '@/hooks/useToast'; -import { useSession } from 'next-auth/react'; -import { useNDKContext } from '@/context/NDKContext'; -import { useEncryptContent } from '@/hooks/encryption/useEncryptContent'; -import GenericButton from '@/components/buttons/GenericButton'; -import { NDKEvent } from '@nostr-dev-kit/ndk'; -import { validateEvent } from '@/utils/nostr'; import { InputText } from 'primereact/inputtext'; import { InputTextarea } from 'primereact/inputtextarea'; import { InputNumber } from 'primereact/inputnumber'; import { InputSwitch } from 'primereact/inputswitch'; +import GenericButton from '@/components/buttons/GenericButton'; +import { useRouter } from 'next/router'; +import { useSession } from 'next-auth/react'; +import { useToast } from '@/hooks/useToast'; +import { useNDKContext } from '@/context/NDKContext'; +import { NDKEvent } from '@nostr-dev-kit/ndk'; +import { validateEvent } from '@/utils/nostr'; +import { useEncryptContent } from '@/hooks/encryption/useEncryptContent'; +import 'primeicons/primeicons.css'; import { Tooltip } from 'primereact/tooltip'; -import dynamic from 'next/dynamic'; - -const MDEditor = dynamic(() => import('@uiw/react-md-editor'), { ssr: false }); +import 'primereact/resources/primereact.min.css'; +import MarkdownEditor from '@/components/markdown/MarkdownEditor'; const EditPublishedDocumentForm = ({ event }) => { const router = useRouter(); @@ -198,9 +198,7 @@ const EditPublishedDocumentForm = ({ event }) => {
Content -
- -
+
diff --git a/src/components/forms/video/EditPublishedVideoForm.js b/src/components/forms/video/EditPublishedVideoForm.js index 6eac234..5bbc48c 100644 --- a/src/components/forms/video/EditPublishedVideoForm.js +++ b/src/components/forms/video/EditPublishedVideoForm.js @@ -1,23 +1,22 @@ import React, { useState, useEffect, useCallback } from 'react'; import axios from 'axios'; -import { useRouter } from 'next/router'; -import { useToast } from '@/hooks/useToast'; -import { useSession } from 'next-auth/react'; -import { useNDKContext } from '@/context/NDKContext'; -import GenericButton from '@/components/buttons/GenericButton'; -import { NDKEvent } from '@nostr-dev-kit/ndk'; -import { validateEvent } from '@/utils/nostr'; import { InputText } from 'primereact/inputtext'; import { InputTextarea } from 'primereact/inputtextarea'; import { InputNumber } from 'primereact/inputnumber'; import { InputSwitch } from 'primereact/inputswitch'; +import GenericButton from '@/components/buttons/GenericButton'; +import { useRouter } from 'next/router'; +import { useSession } from 'next-auth/react'; +import { useToast } from '@/hooks/useToast'; +import { useNDKContext } from '@/context/NDKContext'; +import { NDKEvent } from '@nostr-dev-kit/ndk'; +import { validateEvent } from '@/utils/nostr'; import { useEncryptContent } from '@/hooks/encryption/useEncryptContent'; import MoreInfo from '@/components/MoreInfo'; -import dynamic from 'next/dynamic'; - -const MDEditor = dynamic(() => import('@uiw/react-md-editor'), { - ssr: false, -}); +import 'primeicons/primeicons.css'; +import { Tooltip } from 'primereact/tooltip'; +import 'primereact/resources/primereact.min.css'; +import MarkdownEditor from '@/components/markdown/MarkdownEditor'; const EditPublishedVideoForm = ({ event }) => { const router = useRouter(); @@ -190,9 +189,7 @@ const EditPublishedVideoForm = ({ event }) => {
Video Embed -
- -
+ You can customize your video embed using markdown or HTML. For example, paste iframe embeds from YouTube or Vimeo, or use video tags for direct video files. diff --git a/src/components/markdown/MarkdownEditor.js b/src/components/markdown/MarkdownEditor.js new file mode 100644 index 0000000..5950860 --- /dev/null +++ b/src/components/markdown/MarkdownEditor.js @@ -0,0 +1,128 @@ +import React from 'react'; +import dynamic from 'next/dynamic'; +import '@uiw/react-md-editor/markdown-editor.css'; +import '@uiw/react-markdown-preview/markdown.css'; +import 'github-markdown-css/github-markdown-dark.css'; + +// Custom theme for MDEditor +const mdEditorDarkTheme = { + markdown: '#fff', + markdownH1: '#fff', + markdownH2: '#fff', + markdownH3: '#fff', + markdownH4: '#fff', + markdownH5: '#fff', + markdownH6: '#fff', + markdownParagraph: '#fff', + markdownLink: '#58a6ff', + markdownCode: '#fff', + markdownList: '#fff', + markdownBlockquote: '#fff', + markdownTable: '#fff', +}; + +// Dynamically import MDEditor with custom theming +const MDEditor = dynamic(() => import('@uiw/react-md-editor').then(mod => { + // Override the module's default theme + if (mod.default) { + mod.default.Markdown = { + ...mod.default.Markdown, + ...mdEditorDarkTheme + }; + } + return mod; +}), { + ssr: false, +}); + +/** + * A reusable markdown editor component with proper dark mode styling + * + * @param {Object} props + * @param {string} props.value - The markdown content + * @param {Function} props.onChange - Callback function when content changes + * @param {number} props.height - Height of the editor (default: 300) + * @param {string} props.placeholder - Placeholder text for the editor + * @param {string} props.preview - Preview mode ('edit', 'preview', 'live') (default: 'edit') + * @param {string} props.className - Additional class names + * @returns {JSX.Element} + */ +const MarkdownEditor = ({ + value, + onChange, + height = 300, + placeholder = "Write your content here...", + preview = "edit", + className = "", + ...props +}) => { + return ( +
+ + +
+ ); +}; + +export default MarkdownEditor; \ No newline at end of file