submission from employee side done.
This commit is contained in:
parent
a7b6b78890
commit
26663b1c58
@ -4,57 +4,103 @@ import { useEffect, useState } from "react";
|
||||
import { databases } from "../lib/appwrite";
|
||||
import { databaseId, membersCollectionId } from "../lib/appwrite";
|
||||
import { getCurrentUserWithRole } from "../utils/auth";
|
||||
import { Query } from "appwrite";
|
||||
|
||||
export default function MemberList() {
|
||||
const [members, setMembers] = useState([]);
|
||||
const [user, setUser] = useState(null);
|
||||
const [currentUser, setCurrentUser] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
getCurrentUserWithRole().then(setUser);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const getMembers = async () => {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
// Get current user with role first
|
||||
const user = await getCurrentUserWithRole();
|
||||
setCurrentUser(user);
|
||||
|
||||
// Then fetch members with proper error handling
|
||||
const res = await databases.listDocuments(
|
||||
databaseId,
|
||||
membersCollectionId
|
||||
membersCollectionId,
|
||||
[Query.orderDesc("$createdAt")] // Optional: sort by creation date
|
||||
);
|
||||
setMembers(res.documents); // <-- Add this line
|
||||
|
||||
setMembers(res.documents);
|
||||
} catch (err) {
|
||||
console.error("Error fetching members:", err);
|
||||
console.error("Error fetching data:", err);
|
||||
setError("Failed to load member data");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
getMembers();
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
if (loading) {
|
||||
return <div className="p-4">Loading members...</div>;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return <div className="p-4 text-red-500">{error}</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mt-8">
|
||||
<div className="mt-8 p-4">
|
||||
<h2 className="text-xl font-semibold mb-4">All Members</h2>
|
||||
|
||||
{/* Current user info */}
|
||||
{currentUser && (
|
||||
<div className="mb-6 p-4 bg-blue-50 rounded-lg">
|
||||
<p className="font-medium">You are logged in as: {currentUser.name}</p>
|
||||
<p>Your role: <span className="capitalize font-semibold">{currentUser.role}</span></p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Members table */}
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full border">
|
||||
<thead>
|
||||
<tr className="bg-gray-100">
|
||||
<th className="p-2 text-left">Name</th>
|
||||
<th className="p-2">Phone</th>
|
||||
<th className="p-2">Join Date</th>
|
||||
<th className="p-2">Role</th>
|
||||
<th className="p-3 text-left">Name</th>
|
||||
<th className="p-3">Email</th>
|
||||
<th className="p-3">Phone</th>
|
||||
<th className="p-3">Join Date</th>
|
||||
<th className="p-3">Role</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{members.map((m) => (
|
||||
<tr key={m.$id} className="border-t">
|
||||
<td className="p-2">{m.name}</td>
|
||||
<td className="p-2">{m.phone}</td>
|
||||
<td className="p-2">{m.joinDate}</td>
|
||||
<td className="p-2">{m.role}</td>
|
||||
{members.length > 0 ? (
|
||||
members.map((member) => (
|
||||
<tr key={member.$id} className="border-t hover:bg-gray-50">
|
||||
<td className="p-3">{member.name || "N/A"}</td>
|
||||
<td className="p-3">{member.email || "N/A"}</td>
|
||||
<td className="p-3">{member.phone || "N/A"}</td>
|
||||
<td className="p-3">
|
||||
{member.joinDate ? new Date(member.joinDate).toLocaleDateString() : "N/A"}
|
||||
</td>
|
||||
<td className="p-3 capitalize">
|
||||
<span className={`px-2 py-1 rounded-full text-xs ${
|
||||
member.role === "admin"
|
||||
? "bg-purple-100 text-purple-800"
|
||||
: "bg-blue-100 text-blue-800"
|
||||
}`}>
|
||||
{member.role || "unknown"}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
))
|
||||
) : (
|
||||
<tr>
|
||||
<td colSpan="5" className="p-4 text-center text-gray-500">
|
||||
No members found
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{/* Render role only if user is loaded */}
|
||||
{user ? <p className="mt-4">Role: {user.role}</p> : <p>Loading role...</p>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -9,7 +9,7 @@ client
|
||||
const account = new Account(client);
|
||||
const databases = new Databases(client);
|
||||
|
||||
// ✅ Import from .env
|
||||
// Import from .env
|
||||
const databaseId = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID;
|
||||
const membersCollectionId = process.env.NEXT_PUBLIC_COLLECTION_MEMBERS_ID;
|
||||
|
||||
|
@ -1,18 +0,0 @@
|
||||
// app/admin/members/layout.js
|
||||
|
||||
export const metadata = {
|
||||
title: "Manage Members | Admin",
|
||||
description: "Add or view team members in the portal",
|
||||
};
|
||||
|
||||
export default function AdminLayout({ children }) {
|
||||
return (
|
||||
<section className="p-6">
|
||||
<h1 className="text-2xl font-bold mb-4">Team Members</h1>
|
||||
<div className="bg-white shadow-md rounded-lg p-4">
|
||||
{children}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
@ -1,18 +0,0 @@
|
||||
// app/admin/members/layout.js
|
||||
|
||||
export const metadata = {
|
||||
title: "Manage Members | Admin",
|
||||
description: "Add or view team members in the portal",
|
||||
};
|
||||
|
||||
export default function MembersLayout({ children }) {
|
||||
return (
|
||||
<section className="p-6">
|
||||
<h1 className="text-2xl font-bold mb-4">Team Members</h1>
|
||||
<div className="bg-white shadow-md rounded-lg p-4">
|
||||
{children}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
@ -1,120 +1,225 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { databases, account } from "../../lib/appwrite";
|
||||
import { databases } from "../../lib/appwrite";
|
||||
import { ID } from "appwrite";
|
||||
import { getCurrentUserWithRole } from "../../utils/auth";
|
||||
|
||||
export default function AssignmentsPage() {
|
||||
const [assignments, setAssignments] = useState([]);
|
||||
const [submissionLinks, setSubmissionLinks] = useState({});
|
||||
const [userId, setUserId] = useState(null);
|
||||
const [loadingUser, setLoadingUser] = useState(true); // 🟡 Loading state
|
||||
const [currentUser, setCurrentUser] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [newAssignment, setNewAssignment] = useState({
|
||||
title: "",
|
||||
deadline: ""
|
||||
});
|
||||
|
||||
// Fetch assignments and user on mount
|
||||
// Fetch assignments and user
|
||||
useEffect(() => {
|
||||
const fetchAssignments = async () => {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const response = await databases.listDocuments(
|
||||
const [user, assignmentsResponse] = await Promise.all([
|
||||
getCurrentUserWithRole(),
|
||||
databases.listDocuments(
|
||||
"67e1452b00016444b37f",
|
||||
"67f0f285001a1614b4e8"
|
||||
);
|
||||
setAssignments(response.documents);
|
||||
)
|
||||
]);
|
||||
setCurrentUser(user);
|
||||
setAssignments(assignmentsResponse.documents);
|
||||
} catch (error) {
|
||||
console.error("Error fetching assignments:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const fetchUser = async () => {
|
||||
try {
|
||||
const user = await account.get();
|
||||
setUserId(user.$id);
|
||||
} catch (error) {
|
||||
console.error("User not logged in:", error);
|
||||
console.error("Error:", error);
|
||||
} finally {
|
||||
setLoadingUser(false); // ✅ Done loading
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchAssignments();
|
||||
fetchUser();
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
const handleInputChange = (assignmentId, value) => {
|
||||
setSubmissionLinks({
|
||||
...submissionLinks,
|
||||
[assignmentId]: value,
|
||||
});
|
||||
};
|
||||
|
||||
const handleSubmit = async (assignmentId) => {
|
||||
if (!userId) {
|
||||
alert("User not logged in. Cannot submit.");
|
||||
return;
|
||||
}
|
||||
|
||||
const submissionLink = submissionLinks[assignmentId];
|
||||
if (!submissionLink) {
|
||||
alert("Submission link is empty.");
|
||||
const handleCreateAssignment = async () => {
|
||||
if (!currentUser || currentUser.role !== 'admin') {
|
||||
alert("Only admins can create assignments");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await databases.createDocument(
|
||||
"67e1452b00016444b37f",
|
||||
"67f5ea0a000393d31806", // ✅ Replace with correct ID
|
||||
"67f0f285001a1614b4e8",
|
||||
ID.unique(),
|
||||
{
|
||||
assignmentId,
|
||||
userId,
|
||||
submissionLink,
|
||||
title: newAssignment.title,
|
||||
deadline: newAssignment.deadline,
|
||||
userId: currentUser.$id, // Add current user's ID
|
||||
submitted: false,
|
||||
submittedLate: false,
|
||||
submittedLink: ""
|
||||
}
|
||||
);
|
||||
alert("Submitted!");
|
||||
|
||||
// Refresh assignments
|
||||
const updated = await databases.listDocuments(
|
||||
"67e1452b00016444b37f",
|
||||
"67f0f285001a1614b4e8"
|
||||
);
|
||||
setAssignments(updated.documents);
|
||||
setNewAssignment({ title: "", deadline: "" });
|
||||
|
||||
alert("Assignment created successfully!");
|
||||
} catch (error) {
|
||||
console.error("Submission failed:", error);
|
||||
alert("Submission failed: " + error.message);
|
||||
console.error("Creation failed:", error);
|
||||
alert(`Error: ${error.message}`);
|
||||
}
|
||||
};
|
||||
|
||||
if (loadingUser) {
|
||||
return <div>Loading...</div>; // Optional loading indicator
|
||||
const handleSubmitAssignment = async (assignmentId) => {
|
||||
const link = submissionLinks[assignmentId];
|
||||
if (!link) {
|
||||
alert("Please provide a submission link");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const isLate = new Date() > new Date(
|
||||
assignments.find(a => a.$id === assignmentId).deadline
|
||||
);
|
||||
|
||||
await databases.updateDocument(
|
||||
"67e1452b00016444b37f",
|
||||
"67f0f285001a1614b4e8",
|
||||
assignmentId,
|
||||
{
|
||||
submitted: true,
|
||||
submittedLate: isLate,
|
||||
submittedLink: link
|
||||
}
|
||||
);
|
||||
|
||||
// Refresh assignments
|
||||
const updated = await databases.listDocuments(
|
||||
"67e1452b00016444b37f",
|
||||
"67f0f285001a1614b4e8"
|
||||
);
|
||||
setAssignments(updated.documents);
|
||||
setSubmissionLinks({...submissionLinks, [assignmentId]: ""});
|
||||
|
||||
alert(`Submission ${isLate ? 'completed (late)' : 'completed on time'}`);
|
||||
} catch (error) {
|
||||
console.error("Submission failed:", error);
|
||||
alert("Submission failed");
|
||||
}
|
||||
};
|
||||
|
||||
if (loading) return <div>Loading...</div>;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="p-4">
|
||||
<h1 className="text-2xl font-bold mb-4">Assignments</h1>
|
||||
|
||||
{currentUser && (
|
||||
<p className="mb-4">Role: <span className="capitalize font-semibold">{currentUser.role}</span></p>
|
||||
)}
|
||||
|
||||
{/* Admin-only creation form */}
|
||||
{currentUser?.role === 'admin' && (
|
||||
<div className="mb-6 p-4 border rounded-lg bg-gray-50">
|
||||
<h2 className="text-xl font-semibold mb-4">Create New Assignment</h2>
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-1">Title*</label>
|
||||
<input
|
||||
type="text"
|
||||
value={newAssignment.title}
|
||||
onChange={(e) => setNewAssignment({...newAssignment, title: e.target.value})}
|
||||
className="w-full border px-3 py-2 rounded"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-1">Deadline*</label>
|
||||
<input
|
||||
type="datetime-local"
|
||||
value={newAssignment.deadline}
|
||||
onChange={(e) => setNewAssignment({...newAssignment, deadline: e.target.value})}
|
||||
className="border px-3 py-2 rounded"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
onClick={handleCreateAssignment}
|
||||
className="bg-green-600 text-white px-4 py-2 rounded disabled:bg-gray-400"
|
||||
disabled={!newAssignment.title || !newAssignment.deadline}
|
||||
>
|
||||
Create Assignment
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Assignments list */}
|
||||
<div className="space-y-4">
|
||||
{assignments.length === 0 ? (
|
||||
<p>No assignments available.</p>
|
||||
) : (
|
||||
assignments.map((assignment) => (
|
||||
<div key={assignment.$id} className="mb-6 border p-4 rounded-lg">
|
||||
<div key={assignment.$id} className="border p-4 rounded-lg">
|
||||
<div className="flex justify-between items-start">
|
||||
<div>
|
||||
<h2 className="text-xl font-semibold">{assignment.title}</h2>
|
||||
<p className="text-gray-600">{assignment.description}</p>
|
||||
<p className="text-sm text-gray-400">
|
||||
Deadline: {assignment.deadline}
|
||||
<p className="text-sm text-gray-600 mt-1">
|
||||
Deadline: {new Date(assignment.deadline).toLocaleString()}
|
||||
</p>
|
||||
</div>
|
||||
{assignment.submitted && (
|
||||
<span className={`px-2 py-1 text-xs rounded-full ${
|
||||
assignment.submittedLate
|
||||
? 'bg-red-100 text-red-800'
|
||||
: 'bg-green-100 text-green-800'
|
||||
}`}>
|
||||
{assignment.submittedLate ? 'Late' : 'Submitted'}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{!assignment.submitted && currentUser?.role !== 'admin' && (
|
||||
<div className="mt-4">
|
||||
<input
|
||||
type="text"
|
||||
className="mt-2 border px-2 py-1 w-full"
|
||||
placeholder="Paste your GitHub/Firebase/Netlify link"
|
||||
placeholder="Paste submission link"
|
||||
value={submissionLinks[assignment.$id] || ""}
|
||||
onChange={(e) =>
|
||||
handleInputChange(assignment.$id, e.target.value)
|
||||
}
|
||||
onChange={(e) => setSubmissionLinks({
|
||||
...submissionLinks,
|
||||
[assignment.$id]: e.target.value
|
||||
})}
|
||||
className="w-full border px-3 py-2 rounded"
|
||||
/>
|
||||
|
||||
<button
|
||||
onClick={() => handleSubmit(assignment.$id)}
|
||||
className="mt-2 bg-blue-600 text-white px-4 py-1 rounded"
|
||||
onClick={() => handleSubmitAssignment(assignment.$id)}
|
||||
className="mt-2 bg-blue-600 text-white px-4 py-2 rounded"
|
||||
disabled={!submissionLinks[assignment.$id]}
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{assignment.submitted && assignment.submittedLink && (
|
||||
<div className="mt-3">
|
||||
<a
|
||||
href={assignment.submittedLink}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-blue-600 hover:underline"
|
||||
>
|
||||
View Submission
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
226
src/app/pages/submissionPage/page.js
Normal file
226
src/app/pages/submissionPage/page.js
Normal file
@ -0,0 +1,226 @@
|
||||
"use client";
|
||||
import { useEffect, useState } from "react";
|
||||
import { databases } from "../../lib/appwrite";
|
||||
import { ID, Query } from "appwrite";
|
||||
import { getCurrentUserWithRole } from "../../utils/auth";
|
||||
|
||||
export default function SubmissionPage() {
|
||||
const [assignments, setAssignments] = useState([]);
|
||||
const [submissionLink, setSubmissionLink] = useState("");
|
||||
const [selectedAssignment, setSelectedAssignment] = useState("");
|
||||
const [currentUser, setCurrentUser] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
// Database IDs
|
||||
const databaseId = "67e1452b00016444b37f";
|
||||
const assignmentsCollectionId = "67f0f285001a1614b4e8";
|
||||
const submissionsCollectionId = "67f5ea0a000393d31806";
|
||||
const employeeCollectionId = "67f143f00010e2cd2652"; // FSPL HR Employee Management
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const [user, assignmentsResponse] = await Promise.all([
|
||||
getCurrentUserWithRole(),
|
||||
databases.listDocuments(databaseId, assignmentsCollectionId, [
|
||||
Query.equal("submitted", false)
|
||||
])
|
||||
]);
|
||||
setCurrentUser(user);
|
||||
setAssignments(assignmentsResponse.documents);
|
||||
} catch (error) {
|
||||
console.error("Error:", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!selectedAssignment || !submissionLink || !currentUser?.$id) {
|
||||
alert("Please fill all required fields");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 1. Create the submission document
|
||||
await databases.createDocument(
|
||||
databaseId,
|
||||
submissionsCollectionId,
|
||||
ID.unique(),
|
||||
{
|
||||
assignmentId: selectedAssignment,
|
||||
userId: currentUser.$id,
|
||||
submissionLink
|
||||
}
|
||||
);
|
||||
|
||||
// 2. Update the assignment status
|
||||
const assignment = assignments.find(a => a.$id === selectedAssignment);
|
||||
await databases.updateDocument(
|
||||
databaseId,
|
||||
assignmentsCollectionId,
|
||||
selectedAssignment,
|
||||
{
|
||||
submitted: true,
|
||||
submittedLate: new Date() > new Date(assignment.deadline),
|
||||
submittedLink: submissionLink
|
||||
}
|
||||
);
|
||||
|
||||
// 3. Optionally update employee record if needed
|
||||
try {
|
||||
await databases.updateDocument(
|
||||
databaseId,
|
||||
employeeCollectionId,
|
||||
currentUser.$id, // Assuming document ID matches user ID
|
||||
{
|
||||
lastSubmission: new Date().toISOString(),
|
||||
lastSubmissionLink: submissionLink
|
||||
}
|
||||
);
|
||||
} catch (employeeError) {
|
||||
console.log("Employee record not updated (optional):", employeeError);
|
||||
}
|
||||
|
||||
alert("Submission successful!");
|
||||
setSubmissionLink("");
|
||||
setSelectedAssignment("");
|
||||
|
||||
// Refresh assignments list
|
||||
const updated = await databases.listDocuments(
|
||||
databaseId,
|
||||
assignmentsCollectionId,
|
||||
[Query.equal("submitted", false)]
|
||||
);
|
||||
setAssignments(updated.documents);
|
||||
} catch (error) {
|
||||
console.error("Submission failed:", error);
|
||||
alert(`Submission failed: ${error.message}`);
|
||||
}
|
||||
};
|
||||
|
||||
if (loading) return <div className="p-4">Loading...</div>;
|
||||
|
||||
return (
|
||||
<div className="p-4">
|
||||
<h1 className="text-2xl font-bold mb-6">Submit Assignment</h1>
|
||||
|
||||
<div className="space-y-4 max-w-md">
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-1">Select Assignment*</label>
|
||||
<select
|
||||
value={selectedAssignment}
|
||||
onChange={(e) => setSelectedAssignment(e.target.value)}
|
||||
className="w-full border px-3 py-2 rounded"
|
||||
required
|
||||
>
|
||||
<option value="">-- Select Assignment --</option>
|
||||
{assignments.map((assignment) => (
|
||||
<option key={assignment.$id} value={assignment.$id}>
|
||||
{assignment.title} (Due: {new Date(assignment.deadline).toLocaleDateString()})
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-1">Submission Link*</label>
|
||||
<input
|
||||
type="url"
|
||||
placeholder="https://github.com/your-repo"
|
||||
value={submissionLink}
|
||||
onChange={(e) => setSubmissionLink(e.target.value)}
|
||||
className="w-full border px-3 py-2 rounded"
|
||||
required
|
||||
/>
|
||||
<p className="text-xs text-gray-500 mt-1">GitHub, Gitea, or other repository link</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={handleSubmit}
|
||||
className="bg-green-600 text-white px-4 py-2 rounded hover:bg-green-700 disabled:bg-gray-400"
|
||||
disabled={!selectedAssignment || !submissionLink}
|
||||
>
|
||||
Submit Assignment
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Previous Submissions Section */}
|
||||
<div className="mt-8">
|
||||
<h2 className="text-xl font-semibold mb-4">Your Submissions</h2>
|
||||
<div className="border rounded-lg overflow-hidden">
|
||||
<table className="w-full">
|
||||
<thead className="bg-gray-100">
|
||||
<tr>
|
||||
<th className="p-3 text-left">Assignment</th>
|
||||
<th className="p-3 text-left">Submission Link</th>
|
||||
<th className="p-3 text-left">Submitted At</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{currentUser?.$id && (
|
||||
<SubmissionList
|
||||
userId={currentUser.$id}
|
||||
assignments={assignments}
|
||||
/>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Separate component for fetching and displaying submissions
|
||||
function SubmissionList({ userId, assignments }) {
|
||||
const [submissions, setSubmissions] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchSubmissions = async () => {
|
||||
try {
|
||||
const response = await databases.listDocuments(
|
||||
"67e1452b00016444b37f",
|
||||
"67f5ea0a000393d31806",
|
||||
[Query.equal("userId", userId)]
|
||||
);
|
||||
setSubmissions(response.documents);
|
||||
} catch (error) {
|
||||
console.error("Error fetching submissions:", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchSubmissions();
|
||||
}, [userId]);
|
||||
|
||||
if (loading) return <tr><td colSpan="3" className="p-4 text-center">Loading submissions...</td></tr>;
|
||||
if (submissions.length === 0) return <tr><td colSpan="3" className="p-4 text-center">No submissions found</td></tr>;
|
||||
|
||||
return submissions.map((submission) => {
|
||||
const assignment = assignments.find(a => a.$id === submission.assignmentId);
|
||||
return (
|
||||
<tr key={submission.$id} className="border-t hover:bg-gray-50">
|
||||
<td className="p-3">{assignment?.title || submission.assignmentId}</td>
|
||||
<td className="p-3">
|
||||
<a
|
||||
href={submission.submissionLink}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-blue-600 hover:underline"
|
||||
>
|
||||
View Submission
|
||||
</a>
|
||||
</td>
|
||||
<td className="p-3">
|
||||
{new Date(submission.$createdAt).toLocaleString()}
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
});
|
||||
}
|
@ -9,31 +9,52 @@ const databases = new Databases(client);
|
||||
|
||||
export async function getCurrentUserWithRole() {
|
||||
try {
|
||||
// 1. Get current user from Auth
|
||||
const user = await account.get();
|
||||
|
||||
if (!user || !user.$id) {
|
||||
throw new Error("User not authenticated");
|
||||
}
|
||||
|
||||
// 2. Database constants
|
||||
const dbId = "67e1452b00016444b37f";
|
||||
const collectionId = "67f0f1200006897dc192";
|
||||
const collectionId = "67f0f1200006897dc192"; // Your employee collection
|
||||
|
||||
// 3. Try to get employee record
|
||||
let role = "unknown"; // Default role if not found
|
||||
let userDoc = null;
|
||||
|
||||
try {
|
||||
const response = await databases.listDocuments(dbId, collectionId, [
|
||||
Query.equal("userId", user.$id),
|
||||
Query.limit(1)
|
||||
]);
|
||||
|
||||
const userDoc = response.documents[0];
|
||||
if (response.documents.length > 0) {
|
||||
userDoc = response.documents[0];
|
||||
role = userDoc.role || "employee"; // Use "employee" if role exists but is empty
|
||||
}
|
||||
} catch (dbError) {
|
||||
console.error("Database error:", dbError);
|
||||
// Continue with default role
|
||||
}
|
||||
|
||||
// 4. Return combined data
|
||||
return {
|
||||
$id: user.$id, // Make sure to include this
|
||||
name: user.name,
|
||||
email: user.email,
|
||||
role: userDoc?.role || "unknown",
|
||||
// Include the document ID if needed
|
||||
docId: userDoc?.$id
|
||||
...user, // All original user properties
|
||||
role, // Determined role ("admin", "employee", or "unknown")
|
||||
isAdmin: role === "admin", // Convenience boolean
|
||||
employeeDoc: userDoc // Full employee document if available
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error fetching user with role:", error);
|
||||
throw error; // Throw instead of returning null
|
||||
console.error("Error in getCurrentUserWithRole:", error);
|
||||
|
||||
// Convert Appwrite errors to more user-friendly messages
|
||||
if (error.type === "general_unauthorized_scope") {
|
||||
throw new Error("Please login to access this feature");
|
||||
}
|
||||
|
||||
throw error; // Re-throw for components to handle
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user