mirror of
https://github.com/System-End/scraps.git
synced 2026-04-19 16:28:20 +00:00
17th
This commit is contained in:
parent
eadf80d523
commit
7e65d9eee8
3 changed files with 67 additions and 1 deletions
|
|
@ -491,6 +491,30 @@ projects.get("/:id", async ({ params, headers }) => {
|
|||
hasSubmittedFeedback = feedbackCheck.length > 0;
|
||||
}
|
||||
|
||||
// Check if project can be resubmitted (first submission must be on or before March 17th, 2026)
|
||||
let canResubmit = true;
|
||||
if (isOwner) {
|
||||
const firstSubmission = await db
|
||||
.select({ createdAt: projectActivityTable.createdAt })
|
||||
.from(projectActivityTable)
|
||||
.where(
|
||||
and(
|
||||
eq(projectActivityTable.projectId, parseInt(params.id)),
|
||||
eq(projectActivityTable.action, "project_submitted"),
|
||||
),
|
||||
)
|
||||
.orderBy(projectActivityTable.createdAt)
|
||||
.limit(1);
|
||||
|
||||
if (firstSubmission.length > 0) {
|
||||
const cutoffDate = new Date("2026-03-18T00:00:00Z");
|
||||
canResubmit = firstSubmission[0].createdAt < cutoffDate;
|
||||
} else {
|
||||
// Never submitted before - cannot submit new projects
|
||||
canResubmit = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate effective hours (subtract overlapping shipped project hours)
|
||||
// Uses activity-derived shipped dates for ordering (consistent with Airtable sync and admin review)
|
||||
const projectHours = project[0].hoursOverride ?? project[0].hours ?? 0;
|
||||
|
|
@ -533,6 +557,7 @@ projects.get("/:id", async ({ params, headers }) => {
|
|||
owner: projectOwner[0] || null,
|
||||
isOwner,
|
||||
hasSubmittedFeedback: isOwner ? hasSubmittedFeedback : undefined,
|
||||
canResubmit: isOwner ? canResubmit : undefined,
|
||||
activity,
|
||||
};
|
||||
});
|
||||
|
|
@ -840,6 +865,27 @@ projects.post("/:id/submit", async ({ params, headers, body }) => {
|
|||
return { error: "Project cannot be submitted in current status" };
|
||||
}
|
||||
|
||||
// Check if this is a resubmission - if so, verify first submission was on or before March 17th
|
||||
const firstSubmission = await db
|
||||
.select({ createdAt: projectActivityTable.createdAt })
|
||||
.from(projectActivityTable)
|
||||
.where(
|
||||
and(
|
||||
eq(projectActivityTable.projectId, parseInt(params.id)),
|
||||
eq(projectActivityTable.action, "project_submitted"),
|
||||
),
|
||||
)
|
||||
.orderBy(projectActivityTable.createdAt)
|
||||
.limit(1);
|
||||
|
||||
if (firstSubmission.length > 0) {
|
||||
// This is a resubmission - check if first submission was on or before March 17th, 2026
|
||||
const cutoffDate = new Date("2026-03-18T00:00:00Z"); // Midnight March 18th = end of March 17th
|
||||
if (firstSubmission[0].createdAt >= cutoffDate) {
|
||||
return { error: "Resubmissions are only allowed for projects first submitted on or before March 17th" };
|
||||
}
|
||||
}
|
||||
|
||||
// Sync hours from Hackatime before submitting
|
||||
if (project[0].hackatimeProject) {
|
||||
await syncSingleProject(parseInt(params.id));
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@
|
|||
let owner = $state<Owner | null>(null);
|
||||
let isOwner = $state(false);
|
||||
let isAdmin = $state(false);
|
||||
let canResubmit = $state(true);
|
||||
let activity = $state<ActivityEntry[]>([]);
|
||||
let loading = $state(true);
|
||||
let error = $state<string | null>(null);
|
||||
|
|
@ -104,6 +105,7 @@
|
|||
project = result.project;
|
||||
owner = result.owner;
|
||||
isOwner = result.isOwner;
|
||||
canResubmit = result.canResubmit ?? true;
|
||||
activity = result.activity || [];
|
||||
} catch (e) {
|
||||
error = e instanceof Error ? e.message : 'Failed to load project';
|
||||
|
|
@ -454,7 +456,7 @@
|
|||
<Send size={18} />
|
||||
{$t.project.awaitingReview}
|
||||
</span>
|
||||
{:else if project.status === 'shipped'}
|
||||
{:else if project.status === 'shipped' && canResubmit}
|
||||
<a
|
||||
href="/projects/{project.id}/submit"
|
||||
class="flex flex-1 cursor-pointer items-center justify-center gap-2 rounded-full border-4 border-black bg-black px-4 py-3 text-sm font-bold text-white transition-all duration-200 hover:bg-gray-800 sm:px-6 sm:text-base"
|
||||
|
|
@ -462,6 +464,13 @@
|
|||
<RefreshCw size={18} />
|
||||
ship update
|
||||
</a>
|
||||
{:else if project.status === 'shipped' && !canResubmit}
|
||||
<span
|
||||
class="flex flex-1 cursor-not-allowed items-center justify-center gap-2 rounded-full border-4 border-black bg-gray-200 px-4 py-3 text-center text-sm font-bold text-gray-600 sm:px-6 sm:text-base"
|
||||
>
|
||||
<CheckCircle size={18} />
|
||||
shipped
|
||||
</span>
|
||||
{:else if project.status === 'permanently_rejected'}
|
||||
<span
|
||||
class="flex flex-1 cursor-not-allowed items-center justify-center gap-2 rounded-full border-4 border-black bg-red-100 px-4 py-3 text-center text-sm font-bold text-red-600 sm:px-6 sm:text-base"
|
||||
|
|
@ -469,6 +478,13 @@
|
|||
<XCircle size={18} />
|
||||
{$t.project.permanentlyRejected}
|
||||
</span>
|
||||
{:else if !canResubmit}
|
||||
<span
|
||||
class="flex flex-1 cursor-not-allowed items-center justify-center gap-2 rounded-full border-4 border-black bg-gray-200 px-4 py-3 text-center text-sm font-bold text-gray-600 sm:px-6 sm:text-base"
|
||||
>
|
||||
<XCircle size={18} />
|
||||
submissions closed
|
||||
</span>
|
||||
{:else if $tutorialActiveStore}
|
||||
<span
|
||||
data-tutorial="submit-button"
|
||||
|
|
|
|||
|
|
@ -128,6 +128,10 @@
|
|||
if (!responseData.isOwner) {
|
||||
throw new Error('You can only submit your own projects');
|
||||
}
|
||||
// Check if resubmission is allowed
|
||||
if (responseData.canResubmit === false) {
|
||||
throw new Error('Resubmissions are only allowed for projects first submitted on or before March 17th');
|
||||
}
|
||||
project = responseData.project;
|
||||
imagePreview = project?.image || null;
|
||||
hasSubmittedFeedbackBefore = responseData.hasSubmittedFeedback ?? false;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue