Initial frontend implementation

This commit is contained in:
2024-09-25 18:37:44 +02:00
parent 4a21b7de97
commit 646b683cbb
12 changed files with 7683 additions and 0 deletions

23
frontend/src/App.js Normal file
View File

@@ -0,0 +1,23 @@
import React, { useState } from 'react';
import Editor from './components/Editor';
import FileTree from './components/FileTree';
import './App.scss';
function App() {
const [content, setContent] = useState('# Welcome to NovaMD\n\nStart editing here!');
const [files, setFiles] = useState(['README.md', 'chapter1.md', 'chapter2.md']);
return (
<div className="App">
<div className="sidebar">
<FileTree files={files} />
</div>
<div className="main-content">
<h1>NovaMD</h1>
<Editor content={content} onChange={setContent} />
</div>
</div>
);
}
export default App;

33
frontend/src/App.scss Normal file
View File

@@ -0,0 +1,33 @@
.App {
display: flex;
height: 100vh;
.sidebar {
width: 200px;
background-color: #f0f0f0;
padding: 20px;
overflow-y: auto;
}
.main-content {
flex-grow: 1;
padding: 20px;
overflow-y: auto;
}
}
.file-tree {
ul {
list-style-type: none;
padding-left: 20px;
}
li {
margin-bottom: 5px;
cursor: pointer;
&:hover {
text-decoration: underline;
}
}
}

View File

@@ -0,0 +1,50 @@
import React, { useEffect, useRef } from "react";
import { basicSetup } from "codemirror";
import { EditorState } from "@codemirror/state";
import { EditorView, keymap } from "@codemirror/view";
import { markdown } from "@codemirror/lang-markdown";
import { defaultKeymap } from "@codemirror/commands";
const Editor = ({ content, onChange }) => {
const editorRef = useRef();
const viewRef = useRef();
useEffect(() => {
const state = EditorState.create({
doc: content,
extensions: [
basicSetup,
markdown(),
keymap.of(defaultKeymap),
EditorView.updateListener.of((update) => {
if (update.docChanged) {
onChange(update.state.doc.toString());
}
}),
],
});
const view = new EditorView({
state,
parent: editorRef.current,
});
viewRef.current = view;
return () => {
view.destroy();
};
}, []);
useEffect(() => {
if (viewRef.current && content !== viewRef.current.state.doc.toString()) {
viewRef.current.dispatch({
changes: { from: 0, to: viewRef.current.state.doc.length, insert: content }
});
}
}, [content]);
return <div ref={editorRef} />;
};
export default Editor;

View File

@@ -0,0 +1,16 @@
import React from 'react';
const FileTree = ({ files }) => {
return (
<div className="file-tree">
<h3>Files</h3>
<ul>
{files.map((file, index) => (
<li key={index}>{file}</li>
))}
</ul>
</div>
);
};
export default FileTree;

10
frontend/src/index.js Normal file
View File

@@ -0,0 +1,10 @@
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);