diff --git a/src/hooks/useReadmeState.js b/src/hooks/useReadmeState.js index 1e8246d..d859fe7 100644 --- a/src/hooks/useReadmeState.js +++ b/src/hooks/useReadmeState.js @@ -68,6 +68,14 @@ export function useReadmeState() { }); }, [sectionState, selectedTechs, selectedBadges, scheduleSave]); + const updateMultipleFields = useCallback((fieldsObj) => { + setFormData(prev => { + const next = { ...prev, ...fieldsObj }; + scheduleSave(next, sectionState, selectedTechs, selectedBadges); + return next; + }); + }, [sectionState, selectedTechs, selectedBadges, scheduleSave]); + const toggleSection = useCallback((id, checked) => { setSectionState(prev => { const next = { ...prev, [id]: checked }; @@ -145,7 +153,7 @@ export function useReadmeState() { }, []); return { - formData, updateField, + formData, updateField, updateMultipleFields, sectionState, toggleSection, selectedTechs, toggleTech, selectedBadges, toggleBadge, diff --git a/src/pages/ReadmeMaker/EditorPanel.jsx b/src/pages/ReadmeMaker/EditorPanel.jsx index 4fe52ff..ac8e94e 100644 --- a/src/pages/ReadmeMaker/EditorPanel.jsx +++ b/src/pages/ReadmeMaker/EditorPanel.jsx @@ -1,8 +1,9 @@ import { isValidUrl } from '../../hooks/useUrlValidation'; -import { useRef } from 'react'; +import { useRef, useState } from 'react'; import { TECHS, BADGES } from '../../utils/constants'; import { convertStructure } from '../../utils/structureUtils'; import { getWordCount } from '../../utils/markdownUtils'; +import { parseGitHubUrl, fetchRepoData } from '../../utils/githubApi'; function WordCount({ text }) { const count = getWordCount(text); @@ -34,10 +35,34 @@ export default function EditorPanel({ selectedTechs, toggleTech, selectedBadges, toggleBadge, screenshots, addScreenshots, removeScreenshot, + onGitHubImport, }) { const fileInputRef = useRef(null); const dropZoneRef = useRef(null); + const [ghUrl, setGhUrl] = useState(''); + const [ghLoading, setGhLoading] = useState(false); + const [ghStatus, setGhStatus] = useState({ type: '', message: '' }); + + async function handleGitHubFetch() { + setGhStatus({ type: '', message: '' }); + const parsed = parseGitHubUrl(ghUrl); + if (!parsed) { + setGhStatus({ type: 'error', message: 'Invalid GitHub URL. Use format: https://github.com/owner/repo' }); + return; + } + setGhLoading(true); + try { + const data = await fetchRepoData(parsed.owner, parsed.repo); + onGitHubImport(data); + setGhStatus({ type: 'success', message: `✓ Imported "${data.name}" successfully!` }); + } catch (err) { + setGhStatus({ type: 'error', message: err.message }); + } finally { + setGhLoading(false); + } + } + const structPreview = formData.rawStructure ? convertStructure(formData.rawStructure, formData.projName || 'project') : 'Paste structure above to preview...'; @@ -61,6 +86,37 @@ export default function EditorPanel({