Skip to content

Commit d32410e

Browse files
Zeff01claude
andcommitted
feat: add waitlist entry timestamp tracking for applicants
- Add waitlist_entered_at column to applicant table - Update TypeScript schema to include new field - Automatically save timestamp when applicant transitions from onboarding to waitlist - Add new Waitlist column in applicants page to display entry timestamp - Column shows date and time when applicant moved to waitlist status 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent bf92b27 commit d32410e

4 files changed

Lines changed: 80 additions & 0 deletions

File tree

‎apps/codebility/app/applicant/onboarding/_service/action.ts‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,30 @@ export async function completeOnboarding(codevId: string, newStatus: string = "w
201201
return { success: false, error };
202202
}
203203

204+
// If transitioning to waitlist, save the timestamp in applicant table
205+
if (newStatus === "waitlist") {
206+
const { data: applicantData } = await supabase
207+
.from("applicant")
208+
.select("id")
209+
.eq("codev_id", codevId)
210+
.single();
211+
212+
if (applicantData) {
213+
const { error: applicantError } = await supabase
214+
.from("applicant")
215+
.update({
216+
waitlist_entered_at: new Date().toISOString(),
217+
updated_at: new Date().toISOString(),
218+
})
219+
.eq("id", applicantData.id);
220+
221+
if (applicantError) {
222+
console.error("Error updating applicant waitlist timestamp:", applicantError);
223+
// Don't fail the whole operation if this fails
224+
}
225+
}
226+
}
227+
204228
revalidatePath("/applicant/onboarding");
205229
revalidatePath("/applicant/waiting");
206230
return { success: true };

‎apps/codebility/app/home/applicants/_components/_table/applicantColumns.tsx‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,48 @@ const waitlistColumns: ColumnDef<NewApplicantType>[] = [
455455
className: "w-28 text-center",
456456
},
457457
},
458+
{
459+
id: "waitlist_entered",
460+
accessorKey: "applicant.waitlist_entered_at",
461+
header: ({ column }) => {
462+
return (
463+
<Button
464+
variant="ghost"
465+
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
466+
className="flex h-8 items-center justify-center gap-1 px-2 py-1 text-xs font-semibold text-gray-800 hover:bg-gray-50 hover:text-gray-900 dark:text-gray-100 dark:hover:bg-gray-800 dark:hover:text-white"
467+
>
468+
Waitlist
469+
<ArrowUpDown className="h-3 w-3" />
470+
</Button>
471+
);
472+
},
473+
cell: ({ row }) => {
474+
const applicant = row.original;
475+
const waitlistEntered = applicant.applicant?.waitlist_entered_at;
476+
477+
return (
478+
<div className="flex items-center justify-center px-2 py-2">
479+
{waitlistEntered ? (
480+
<div className="flex flex-col items-center gap-0.5">
481+
<span className="text-xs font-medium text-gray-900 dark:text-gray-100">
482+
{new Date(waitlistEntered).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: '2-digit' })}
483+
</span>
484+
<span className="text-[10px] text-gray-500 dark:text-gray-400">
485+
{new Date(waitlistEntered).toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' })}
486+
</span>
487+
</div>
488+
) : (
489+
<span className="text-xs text-gray-500 dark:text-gray-500">
490+
N/A
491+
</span>
492+
)}
493+
</div>
494+
);
495+
},
496+
meta: {
497+
className: "w-28 text-center",
498+
},
499+
},
458500
];
459501

460502
/**

‎apps/codebility/app/home/applicants/_service/types.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export const newApplicantsSchema = z.object({
4444
quiz_completed_at: z.string().datetime({ offset: true }).nullable(),
4545
can_do_mobile: z.boolean().nullable(),
4646
commitment_signed_at: z.string().datetime({ offset: true }).nullable(),
47+
waitlist_entered_at: z.string().datetime({ offset: true }).nullable(),
4748
signature_data: z.string().nullable(),
4849
created_at: z.string().datetime({ offset: true }),
4950
updated_at: z.string().datetime({ offset: true }),
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
-- Add waitlist_entered_at timestamp to applicant table
2+
-- This tracks when an applicant transitions from onboarding to waitlist status
3+
4+
ALTER TABLE public.applicant
5+
ADD COLUMN IF NOT EXISTS waitlist_entered_at TIMESTAMPTZ;
6+
7+
-- Add comment for documentation
8+
COMMENT ON COLUMN public.applicant.waitlist_entered_at IS 'Timestamp when the applicant moved from onboarding to waitlist status';
9+
10+
-- Add index for querying applicants by waitlist entry date
11+
CREATE INDEX IF NOT EXISTS idx_applicant_waitlist_entered
12+
ON public.applicant(waitlist_entered_at)
13+
WHERE waitlist_entered_at IS NOT NULL;

0 commit comments

Comments
 (0)