Skip to content

Feature/drafts and email automation - #9

Merged
ChitkulLakshya merged 3 commits into
mainfrom
feature/drafts-and-email-automation
Aug 7, 2026
Merged

Feature/drafts and email automation#9
ChitkulLakshya merged 3 commits into
mainfrom
feature/drafts-and-email-automation

Conversation

@ChitkulLakshya

Copy link
Copy Markdown
Collaborator

No description provided.

Copilot AI lite review requested due to automatic review settings August 7, 2026 19:04
@netlify

netlify Bot commented Aug 7, 2026

Copy link
Copy Markdown

Deploy Preview for leddger-ai ready!

Name Link
🔨 Latest commit 6f379f2
🔍 Latest deploy log https://app.netlify.com/projects/leddger-ai/deploys/6a762c2b4bfeae0008ccb233
😎 Deploy Preview https://deploy-preview-9--leddger-ai.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@ChitkulLakshya
ChitkulLakshya merged commit 5557200 into main Aug 7, 2026
4 of 5 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a drafts workflow for template builders: templates can be saved as private drafts first, then activated later with an explicit expiration time via a new Drafts dashboard, enabling generation of public form links.

Changes:

  • Added a Drafts dashboard UI to list drafts, schedule expiration, activate drafts, and copy public links.
  • Updated template builders to “Save as Draft” (no link generation in-builder) and show a success overlay animation.
  • Updated backend draft model/endpoints to support draft -> active -> expired status and activation-time expiration.

Reviewed changes

Copilot reviewed 11 out of 12 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
src/pages/TemplateBuilder.css Adds styling for a success overlay/video animation.
src/pages/TeamTemplateBuilder.jsx Removes in-builder link generation UI; adds success overlay on save.
src/pages/StudentTemplateBuilder.jsx Adds authenticated draft saving + success overlay and “Save Form” UI block.
src/pages/EmployeeTemplateBuilder.jsx Adds authenticated draft saving + success overlay and “Save Form” UI block.
src/pages/DraftsView.jsx New drafts management UI (list, activation scheduler, link generation/copy).
src/pages/DraftsView.css Styling for the Drafts dashboard split-pane layout and components.
src/App.jsx Adds “Drafts” + “Sent Forms” tabs and a public route for /form/:title/:draftId.
server/models/FormDraft.js Adjusts schema to allow expiresAt: null and default status: draft.
server/index.js Refactors draft creation + adds GET drafts and activation endpoint; blocks inactive public forms.
docs/feature-drafts-and-email.md New feature documentation (needs updates for the new flow + spelling).
docs/drafts-dashboard-architecture.md New architecture doc for drafts dashboard (minor layout correction needed).
Suppressed comments (5)

docs/feature-drafts-and-email.md:20

  • The Team Template Builder section describes the old "Save & Generate Link" + expiration dropdown flow, but the code now saves drafts without generating links and moves activation/scheduling to DraftsView. Updating this section will prevent onboarding confusion.
- Introduced a **"Save & Generate Link"** control panel.
- Allows recruiters to set an expiration period (`24 Hours`, `3 Days`, `7 Days`).
- **Draft Creation Flow**:
  1. Compiles the current UI configuration (`toggles`, `selectedDepartments`, `leadRestriction`, etc.) into a config object.
  2. Sends an authenticated `POST` request to `/api/drafts` with the configuration and expiration time.
  3. Receives a `draftId` and generates a public-facing URL: `/form/[Title]/[draftId]`.

src/pages/DraftsView.jsx:60

  • handleActivateDraft uses an optional token lookup, but still sends the request even if token is undefined, resulting in an invalid Authorization header and a confusing failure. Guard for a missing token before calling the activate endpoint, and avoid hardcoding localhost in the URL.
      const token = await auth.currentUser?.getIdToken();
      const res = await fetch(`http://localhost:5000/api/drafts/${selectedDraft.draftId}/activate`, {
        method: 'PUT',

server/index.js:85

  • POST /api/drafts relies on Mongoose validation for missing title/config, which turns a client error into a 500. Return a 400 when required fields are missing so API consumers get actionable feedback.
    const { title, config } = req.body;
    
    const draftId = uuidv4();

    const newDraft = await FormDraft.create({

src/pages/StudentTemplateBuilder.jsx:122

  • The success animation asset path is misspelled ("/Sucess.webm"). It works only as long as the public asset keeps the same typo, which is easy to break later. Consider renaming the asset to "/Success.webm" and updating all references.
      {showSuccess && (
        <div className="success-overlay">
          <video src="/Sucess.webm" autoPlay muted className="success-video" />
        </div>

src/pages/EmployeeTemplateBuilder.jsx:122

  • The success animation asset path is misspelled ("/Sucess.webm"). It works only as long as the public asset keeps the same typo, which is easy to break later. Consider renaming the asset to "/Success.webm" and updating all references.
      {showSuccess && (
        <div className="success-overlay">
          <video src="/Sucess.webm" autoPlay muted className="success-video" />
        </div>

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +169 to +172
{showSuccess && (
<div className="success-overlay">
<video src="/Sucess.webm" autoPlay muted className="success-video" />
</div>
Comment thread src/pages/DraftsView.jsx
Comment on lines +115 to +119
<div
key={draft.draftId}
className={`draft-card ${selectedDraft?.draftId === draft.draftId ? 'selected' : ''}`}
onClick={() => handleSelectDraft(draft)}
>
Comment thread server/index.js
Comment on lines +121 to +135
const { expiresAt } = req.body;

if (!expiresAt) {
return res.status(400).json({ error: 'expiresAt is required' });
}

const draft = await FormDraft.findOne({ draftId: req.params.draftId, recruiterId: req.user.uid });

if (!draft) {
return res.status(404).json({ error: 'Draft not found' });
}

draft.expiresAt = new Date(expiresAt);
draft.status = 'active';
await draft.save();
@@ -0,0 +1,65 @@
# Feature: Drafts, Temporary Links, & Email Automation

This document outlines the architecture, data models, and logic implemented to support the creation of form drafts, temporary public links, and automated email notifications in the Leddger AI platform.
- The UI simply has a "Save as Draft" button which persists the toggles.

### Drafts Dashboard (`src/pages/DraftsView.jsx`)
- **Split-Pane Layout**: A modern white-and-grey UI featuring a list of templates on the right, and an active configuration screen on the left.
Comment on lines +48 to +51
const token = await auth.currentUser.getIdToken();

const response = await fetch('http://localhost:5000/api/drafts', {
method: 'POST',
Comment on lines +48 to +51
const token = await auth.currentUser.getIdToken();

const response = await fetch('http://localhost:5000/api/drafts', {
method: 'POST',
Comment thread src/pages/DraftsView.jsx
Comment on lines +21 to +25
const token = await auth.currentUser?.getIdToken();
if (!token) return;

const res = await fetch('http://localhost:5000/api/drafts', {
headers: {
Comment thread src/pages/DraftsView.jsx
Comment on lines +184 to +190
value={`http://localhost:5173/form/${encodeURIComponent(selectedDraft.title)}/${selectedDraft.draftId}`}
readOnly
/>
<button
className="copy-btn"
onClick={() => navigator.clipboard.writeText(`http://localhost:5173/form/${encodeURIComponent(selectedDraft.title)}/${selectedDraft.draftId}`)}
>
Comment thread server/index.js
Comment on lines +156 to +158
if (draft.status === 'draft' || !draft.expiresAt) {
return res.status(403).json({ error: 'This form link is not yet active.' });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants