Connect FE with BE api

This commit is contained in:
2024-09-25 22:03:32 +02:00
parent a135f28fd5
commit b2e99fa39e
7 changed files with 222 additions and 64 deletions

View File

@@ -1,23 +1,67 @@
import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import { GeistProvider, CssBaseline } from '@geist-ui/core';
import Editor from './components/Editor';
import FileTree from './components/FileTree';
import { fetchFileList, fetchFileContent } from './services/api';
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']);
const [files, setFiles] = useState([]);
const [selectedFile, setSelectedFile] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
const loadFileList = async () => {
try {
const fileList = await fetchFileList();
if (Array.isArray(fileList)) {
setFiles(fileList);
} else {
throw new Error('File list is not an array');
}
} catch (error) {
console.error('Failed to load file list:', error);
setError('Failed to load file list. Please try again later.');
}
};
loadFileList();
}, []);
const handleFileSelect = async (filePath) => {
try {
const fileContent = await fetchFileContent(filePath);
setContent(fileContent);
setSelectedFile(filePath);
} catch (error) {
console.error('Failed to load file content:', error);
setError('Failed to load file content. Please try again.');
}
};
return (
<div className="App">
<div className="sidebar">
<FileTree files={files} />
<GeistProvider>
<CssBaseline />
<div className="App">
<div className="sidebar">
{error ? (
<div className="error">{error}</div>
) : (
<FileTree
files={files}
onFileSelect={handleFileSelect}
selectedFile={selectedFile}
/>
)}
</div>
<div className="main-content">
<h1>NovaMD</h1>
<Editor content={content} onChange={setContent} />
</div>
</div>
<div className="main-content">
<h1>NovaMD</h1>
<Editor content={content} onChange={setContent} />
</div>
</div>
</GeistProvider>
);
}
export default App;
export default App;

View File

@@ -1,33 +1,49 @@
// Variables
$sidebar-width: 250px;
$border-color: #eaeaea;
$padding: 20px;
.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;
display: flex;
height: 100vh;
.sidebar {
width: $sidebar-width;
padding: $padding;
border-right: 1px solid $border-color;
overflow-y: auto;
}
.main-content {
flex-grow: 1;
padding: $padding;
overflow-y: auto;
h1 {
margin-top: 0;
}
}
}
// Geist UI Tree component customization
:global {
.file-tree {
ul {
list-style-type: none;
padding-left: 20px;
.label {
display: flex;
align-items: center;
}
li {
margin-bottom: 5px;
cursor: pointer;
&:hover {
text-decoration: underline;
}
.icon {
margin-right: 8px;
}
}
.name {
font-size: 14px;
}
.selected {
color: #0070f3;
font-weight: bold;
}
}
}

View File

@@ -1,15 +1,38 @@
import React from 'react';
import { Tree } from '@geist-ui/core';
import { File, Folder } from '@geist-ui/icons';
const FileTree = ({
files = [],
onFileSelect = () => {},
selectedFile = null
}) => {
if (files.length === 0) {
return <div>No files to display</div>;
}
const handleSelect = (filePath) => {
onFileSelect(filePath);
};
const renderLabel = (node) => {
const path = getFilePath(node);
return (
<span style={{ color: path === selectedFile ? '#0070f3' : 'inherit' }}>
{node.name}
</span>
);
};
const renderIcon = ({ type }) => type === 'directory' ? <Folder /> : <File />;
const FileTree = ({ files }) => {
return (
<div className="file-tree">
<h3>Files</h3>
<ul>
{files.map((file, index) => (
<li key={index}>{file}</li>
))}
</ul>
</div>
<Tree
value={files}
onClick={handleSelect}
renderIcon={renderIcon}
renderLabel={renderLabel}
/>
);
};

View File

@@ -0,0 +1,27 @@
const API_BASE_URL = 'http://localhost:8080/api/v1';
export const fetchFileList = async () => {
try {
const response = await fetch(`${API_BASE_URL}/files`);
if (!response.ok) {
throw new Error('Failed to fetch file list');
}
return await response.json();
} catch (error) {
console.error('Error fetching file list:', error);
throw error;
}
};
export const fetchFileContent = async (filePath) => {
try {
const response = await fetch(`${API_BASE_URL}/files/${filePath}`);
if (!response.ok) {
throw new Error('Failed to fetch file content');
}
return await response.text();
} catch (error) {
console.error('Error fetching file content:', error);
throw error;
}
};