Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .env.sample
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
VITE_BACKEND_URL=http://backend.com
VITE_BACKEND_URL=http://backend.com
REACT_APP_GOOGLE_CLIENT_ID=your_google_client_id_here
REACT_APP_GOOGLE_API_KEY=your_google_api_key_here
# .env
VITE_API_BASE_URL=http://localhost:3001/api
REACT_APP_GOOGLE_CLIENT_ID=your_google_client_id_here
REACT_APP_GOOGLE_API_KEY=your_google_api_key_here
50 changes: 31 additions & 19 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,37 @@
import { BrowserRouter, Routes, Route, useLocation } from "react-router-dom";
import { useLayoutEffect } from "react";
import Editor from "./pages/Editor";
import BugReport from "./pages/BugReport";
import Templates from "./pages/Templates";
import LandingPage from "./pages/LandingPage";
import SettingsContextProvider from "./context/SettingsContext";
import NotFound from "./pages/NotFound";
// App.jsx (Final Updated Version)
import React, { useEffect } from 'react';
import { BrowserRouter, Routes, Route, useLocation } from 'react-router-dom';
import { useLayoutEffect } from 'react';
import Editor from './pages/Editor';
import BugReport from './pages/BugReport';
import Templates from './pages/Templates';
import LandingPage from './pages/LandingPage';
import SettingsContextProvider from './context/SettingsContext';
import { GoogleDriveProvider } from './context/GoogleDriveContext';
import { SyncProvider } from './context/synccontext';
import SyncToolbar from './components/synctoolbar';
import NotFound from './pages/NotFound';

export default function App() {
return (
<SettingsContextProvider>
<BrowserRouter>
<RestoreScroll />
<Routes>
<Route path="/" element={<LandingPage />} />
<Route path="/editor" element={<Editor />} />
<Route path="/bug-report" element={<BugReport />} />
<Route path="/templates" element={<Templates />} />
<Route path="*" element={<NotFound />} />
</Routes>
</BrowserRouter>
<SyncProvider>
<GoogleDriveProvider>
<BrowserRouter>
<RestoreScroll />
<div className="app-container">
<SyncToolbar />
<Routes>
<Route path="/" element={<LandingPage />} />
<Route path="/editor" element={<Editor />} />
<Route path="/bug-report" element={<BugReport />} />
<Route path="/templates" element={<Templates />} />
<Route path="*" element={<NotFound />} />
</Routes>
</div>
</BrowserRouter>
</GoogleDriveProvider>
</SyncProvider>
</SettingsContextProvider>
);
}
Expand All @@ -30,4 +42,4 @@ function RestoreScroll() {
window.scroll(0, 0);
}, [location.pathname]);
return null;
}
}
137 changes: 137 additions & 0 deletions src/components/authmodal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// components/AuthModal.jsx
import React, { useState } from 'react';
import { useSync } from '../context/synccontext';
import './AuthModal.css';

const AuthModal = ({ isOpen, onClose, onSuccess }) => {
const [activeTab, setActiveTab] = useState('login');
const [formData, setFormData] = useState({
email: '',
password: '',
username: '',
});
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');

const { register, login } = useSync();

const handleInputChange = (e) => {
setFormData({
...formData,
[e.target.name]: e.target.value,
});
};

const handleSubmit = async (e) => {
e.preventDefault();
setLoading(true);
setError('');

try {
if (activeTab === 'register') {
await register(formData.email, formData.password, formData.username);
} else {
await login(formData.email, formData.password);
}

onSuccess?.();
onClose();
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};

const handleTabChange = (tab) => {
setActiveTab(tab);
setError('');
setFormData({ email: '', password: '', username: '' });
};

if (!isOpen) return null;

return (
<div className="auth-modal-overlay">
<div className="auth-modal">
<div className="auth-modal-header">
<h2>Sync Your Work</h2>
<button className="close-button" onClick={onClose}>×</button>
</div>

<div className="auth-tabs">
<button
className={`auth-tab ${activeTab === 'login' ? 'active' : ''}`}
onClick={() => handleTabChange('login')}
>
Sign In
</button>
<button
className={`auth-tab ${activeTab === 'register' ? 'active' : ''}`}
onClick={() => handleTabChange('register')}
>
Create Account
</button>
</div>

<form onSubmit={handleSubmit} className="auth-form">
{error && <div className="auth-error">{error}</div>}

{activeTab === 'register' && (
<div className="form-group">
<label htmlFor="username">Username</label>
<input
type="text"
id="username"
name="username"
value={formData.username}
onChange={handleInputChange}
required
/>
</div>
)}

<div className="form-group">
<label htmlFor="email">Email</label>
<input
type="email"
id="email"
name="email"
value={formData.email}
onChange={handleInputChange}
required
/>
</div>

<div className="form-group">
<label htmlFor="password">Password</label>
<input
type="password"
id="password"
name="password"
value={formData.password}
onChange={handleInputChange}
required
/>
</div>

<button type="submit" disabled={loading} className="auth-submit-button">
{loading ? 'Processing...' : (activeTab === 'login' ? 'Sign In' : 'Create Account')}
</button>
</form>

<div className="auth-features">
<h4>With Sync You Can:</h4>
<ul>
<li>✨ Save projects to the cloud</li>
<li>🔄 Continue work on any device</li>
<li>🔒 Automatic backups</li>
<li>📱 Access your diagrams anywhere</li>
</ul>
</div>
</div>
</div>
);
};

export default AuthModal;
160 changes: 160 additions & 0 deletions src/components/datatypeselector.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
// components/DataTypeSelector.jsx
import React, { useState } from 'react';
import {
BASE_DATA_TYPES,
DATA_TYPE_CATEGORIES,
ENUM_TYPE,
CUSTOM_TYPE_TEMPLATES,
getDataTypeDefinition
} from '../utils/dataTypes';
import './DataTypeSelector.css';

const DataTypeSelector = ({ value, onChange, onEnumCreate }) => {
const [showCustomTypes, setShowCustomTypes] = useState(false);
const [customTypeName, setCustomTypeName] = useState('');
const [enumValues, setEnumValues] = useState(['']);
const [showEnumCreator, setShowEnumCreator] = useState(false);

const handleDataTypeChange = (dataType) => {
if (dataType === ENUM_TYPE) {
setShowEnumCreator(true);
} else {
onChange({
type: dataType,
definition: getDataTypeDefinition(dataType),
});
}
};

const handleEnumCreate = () => {
const validValues = enumValues.filter(val => val.trim() !== '');
if (validValues.length > 0) {
onEnumCreate?.(validValues);
onChange({
type: ENUM_TYPE,
definition: `ENUM('${validValues.join("','")}')`,
enumValues: validValues,
});
setShowEnumCreator(false);
setEnumValues(['']);
}
};

const addEnumValue = () => {
setEnumValues([...enumValues, '']);
};

const updateEnumValue = (index, value) => {
const newValues = [...enumValues];
newValues[index] = value;
setEnumValues(newValues);
};

const removeEnumValue = (index) => {
if (enumValues.length > 1) {
setEnumValues(enumValues.filter((_, i) => i !== index));
}
};

const addCustomType = () => {
if (customTypeName.trim()) {
// Here you would save the custom type to user preferences or context
console.log('Adding custom type:', customTypeName);
setCustomTypeName('');
setShowCustomTypes(false);
}
};

return (
<div className="data-type-selector">
<div className="data-type-categories">
{Object.entries(DATA_TYPE_CATEGORIES).map(([categoryKey, category]) => (
<div key={categoryKey} className="data-type-category">
<h4>{category.label}</h4>
<div className="data-type-options">
{category.types.map((dataType) => (
<button
key={dataType}
type="button"
className={`data-type-option ${
value?.type === dataType ? 'selected' : ''
}`}
onClick={() => handleDataTypeChange(dataType)}
>
{dataType}
{dataType === ENUM_TYPE && ' (ENUM)'}
</button>
))}
</div>
</div>
))}
</div>

{/* Enum Creator Modal */}
{showEnumCreator && (
<div className="modal-overlay">
<div className="modal-content">
<h3>Create ENUM Type</h3>
<p>Define the possible values for your ENUM type:</p>

<div className="enum-values">
{enumValues.map((value, index) => (
<div key={index} className="enum-value-input">
<input
type="text"
value={value}
onChange={(e) => updateEnumValue(index, e.target.value)}
placeholder={`Value ${index + 1}`}
/>
{enumValues.length > 1 && (
<button
type="button"
onClick={() => removeEnumValue(index)}
className="remove-enum-value"
>
×
</button>
)}
</div>
))}
</div>

<button type="button" onClick={addEnumValue} className="add-enum-value">
+ Add Value
</button>

<div className="modal-actions">
<button onClick={() => setShowEnumCreator(false)}>Cancel</button>
<button onClick={handleEnumCreate} className="primary">
Create ENUM
</button>
</div>
</div>
</div>
)}

{/* Custom Type Creator */}
{showCustomTypes && (
<div className="modal-overlay">
<div className="modal-content">
<h3>Add Custom Data Type</h3>
<input
type="text"
value={customTypeName}
onChange={(e) => setCustomTypeName(e.target.value)}
placeholder="Enter custom type name (e.g., status_type)"
/>
<div className="modal-actions">
<button onClick={() => setShowCustomTypes(false)}>Cancel</button>
<button onClick={addCustomType} className="primary">
Add Type
</button>
</div>
</div>
</div>
)}
</div>
);
};

export default DataTypeSelector;
Loading