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
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,10 @@ This template is used in the [Building An Activity](https://discord.com/develope

Read more about building Discord Activities with the Embedded App SDK at [https://discord.com/developers/docs/activities/overview](https://discord.com/developers/docs/activities/overview).

# web-app
# web-app
# installation
WIP

run
npm run dev in ./server and ./client
cloudflared tunnel --url http://localhost:5173
then fix the discord app and vite.config.js
131 changes: 131 additions & 0 deletions Task.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// Task.js (React Component)
import React, { useState } from 'react';
import TaskLabel from './client/components/TaskLabel';
import Member from './client/components/Member';
import '/styles/popup.css';
import '/styles/task.css';

const TaskPopup = ({
isVisible,
onClose,
onSave,
members,
}) => {
const [taskName, setTaskName] = useState('');
const [taskDetails, setTaskDetails] = useState('');
const [startDate, setStartDate] = useState('');
const [dueDate, setDueDate] = useState('');
const [assignedMember, setAssignedMember] = useState(null);
const [selectedLabel, setSelectedLabel] = useState(null);

const handleSave = () => {
if (!taskName) {
alert('Task name is required.');
return;
}
const taskData = {
name: taskName,
details: taskDetails,
startDate,
dueDate,
assignedMember,
label: selectedLabel,
};
onSave(taskData);
handleClose();
};

const handleClose = () => {
setTaskName('');
setTaskDetails('');
setStartDate('');
setDueDate('');
setAssignedMember(null);
setSelectedLabel(null);
onClose();
};

if (!isVisible) return null;

return (
<div className="task-popup-overlay" onClick={handleClose}>
<div className="task-popup" onClick={(e) => e.stopPropagation()}>
<div className="popup-header">
<h3>Create Task</h3>
<button className="close-button" onClick={handleClose}>
</button>
</div>

<div className="popup-body">
<div className="form-group">
<label>Task Name</label>
<input
type="text"
value={taskName}
onChange={(e) => setTaskName(e.target.value)}
placeholder="Enter task name"
/>
</div>

<div className="form-group">
<label>Task Details</label>
<textarea
value={taskDetails}
onChange={(e) => setTaskDetails(e.target.value)}
placeholder="Enter task details"
/>
</div>

<div className="form-group date-inputs">
<div>
<label>Start Date</label>
<input
type="date"
value={startDate}
onChange={(e) => setStartDate(e.target.value)}
/>
</div>

<div>
<label>Due Date</label>
<input
type="date"
value={dueDate}
onChange={(e) => setDueDate(e.target.value)}
/>
</div>
</div>

<div className="form-group">
<label>Assigned Member</label>
<Member
members={members}
selectedMember={assignedMember}
onSelectMember={setAssignedMember}
/>
</div>

<div className="form-group">
<label>Task Label</label>
<TaskLabel
selectedLabel={selectedLabel}
onSelectLabel={setSelectedLabel}
/>
</div>
</div>

<div className="popup-footer">
<button className="cancel-button" onClick={handleClose}>
Cancel
</button>
<button className="save-button" onClick={handleSave}>
Save
</button>
</div>
</div>
</div>
);
};

export default TaskPopup;
18 changes: 18 additions & 0 deletions client/App.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react';
import { MemoryRouter, Route, Routes } from 'react-router-dom';
import AppProject from './components/pages/Project';
import './styles/sidebar.css';
import './index.css';
// Example components for different routes

const App = () => (
<MemoryRouter>
<div>
<Routes>
<Route path="/" element={<AppProject />} />
</Routes>
</div>
</MemoryRouter>
);

export default App;
35 changes: 35 additions & 0 deletions client/ErrorBoundary.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// ErrorBoundary.js
import React, { Component } from 'react';

class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { hasError: false, errorMessage: '' };
}

static getDerivedStateFromError(error) {
// Update state to display fallback UI
return { hasError: true, errorMessage: error.message };
}

componentDidCatch(error, info) {
// Log error information to an external service (e.g., Sentry, LogRocket)
console.error('Error caught by Error Boundary:', error, info);
}

render() {
if (this.state.hasError) {
// Display custom error message or fallback UI
return (
<div>
<h1>Something went wrong.</h1>
<p>{this.state.errorMessage}</p>
</div>
);
}

return this.props.children;
}
}

export default ErrorBoundary;
131 changes: 131 additions & 0 deletions client/components/BoardProject.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import React, { useState, useRef, useEffect } from 'react';
import '/styles/project.css';
import '/styles/sidebar.css';
import '/styles/board.css';
import BoardSection from './BoardSection';
import ProjectSection from './ProjectSection';

const BoardProject = () => {
const [isBoardVisible, setIsBoardVisible] = useState(true);

// Store boards and active board
const [boards, setBoards] = useState([]);
const [activeBoard, setActiveBoard] = useState(null);

const [projects, setProjects] = useState([]);
const [activeProject, setActiveProject] = useState(null);

const [settingsVisible, setSettingsVisible] = useState(false);
const settingsRef = useRef(null);

// Close settings popup when clicking outside
useEffect(() => {
function handleClickOutside(event) {
if (settingsRef.current && !settingsRef.current.contains(event.target)) {
setSettingsVisible(false);
}
}
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, []);

const toggleSection = () => {
// Prevent toggling section if settings popup is open
if (!settingsVisible) {
setIsBoardVisible((prev) => !prev);
}
};

const deleteProject = () => {
if (!activeProject) return; // No project selected

const updatedProjects = projects.filter((project) => project.id !== activeProject.id);
setProjects(updatedProjects); // Update the project list

// Remove boards associated with this project
const updatedBoards = { ...boards };
delete updatedBoards[activeProject.id];
setBoards(updatedBoards);

// Reset active project and active board
setActiveProject(null);
setActiveBoard(null);
setSettingsVisible(false); // Close the settings popup
};

return (
<div id="main-container">
{/* Project Box */}
<div id="project-container" className="clickable" onClick={toggleSection}>
<div id={`project-box-${activeProject ? activeProject.id : 'none'}`} className="projectbox">
{/* Triangle Symbol */}
<div className={`triangle-symbol ${isBoardVisible ? 'triangle-right' : 'triangle-down'}`}></div>

{/* Project Text Content */}
<div id="project-box-content">
<div id="project-box-name">{activeProject ? activeProject.name : 'project name'}</div>
<div id="project-box-description">{activeProject ? activeProject.description : 'project description'}</div>
</div>

{/* Project Settings Icon (Click to Toggle Popup) */}
<img
src="/assets/setting.svg"
alt="Settings"
className="project-settings-icon"
onClick={(e) => {
e.stopPropagation(); // Prevents toggleSection from being triggered
setSettingsVisible(!settingsVisible);
}}
/>

{/* Settings Popup */}
{settingsVisible && (
<div
className="project-settings-popup"
ref={settingsRef}
onClick={(e) => e.stopPropagation()} // Prevents toggling the board/project
>
<div className="project-settings-option" onClick={() => alert("Share Project Clicked")}>
Share Project
</div>
<div className="project-settings-option" onClick={() => alert("Edit Project Clicked")}>
Edit Project
</div>
<div className="project-settings-option delete" onClick={deleteProject}>
Delete Project
</div>
</div>
)}
</div>
</div>

{/* Conditionally Render Board or Project Section */}
{isBoardVisible ? (
activeProject ? ( // ✅ Only pass projectId if activeProject exists
<BoardSection
projectId={activeProject.id}
boards={boards[activeProject.id] || []}
setBoards={setBoards}
activeBoard={activeBoard}
setActiveBoard={setActiveBoard}
/>
) : (
<div className='please-create-project' id='please-create-project'>
Please Create Project
</div>
)
) : (
<ProjectSection
projects={projects}
setProjects={setProjects}
activeProject={activeProject}
setActiveProject={setActiveProject}
/>
)}
</div>
);
};

export default BoardProject;
Loading