clean up email dashboard ui - #149
HangYeung1 wants to merge 35 commits into
Conversation
Use a full-viewport edge-to-edge shell and restyle the template sidebar to match the application review list pattern. Co-authored-by: Cursor <cursoragent@cursor.com>
The center workspace panel was clipping tall template editor content instead of scrolling within the viewport. Co-authored-by: Cursor <cursoragent@cursor.com>
Let organizers hide the template list behind a slim left rail with clear panel icons, and remember the collapsed state in local storage. Co-authored-by: Cursor <cursoragent@cursor.com>
Match the application review layout with draggable panel splits, persisted sizes, and collapsible templates integrated into the resizable sidebar. Co-authored-by: Cursor <cursoragent@cursor.com>
Move Builder/Styles/Send tabs and save actions into a fixed workspace header so controls stay consistent across panels and do not wrap when the column is narrow. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Unify the block list and editor, reorder fields into template info, subject, blocks, data, and AI, and move CTA under template info. Co-authored-by: Cursor <cursoragent@cursor.com>
Reorganize the builder into header, body blocks, and footer sections with inline block cards so organizers can remove all blocks and still save templates. Co-authored-by: Cursor <cursoragent@cursor.com>
Organizers can describe an email to generate via the free router or keep copying the manual prompt, with inline loading in the draft JSON box. Co-authored-by: Cursor <cursoragent@cursor.com>
Flatten section layout, move merge preview data beside the preview pane, and use subtle pencil icons with dotted hover underlines for template and block titles. Co-authored-by: Cursor <cursoragent@cursor.com>
Consolidate the header, drop type badges and icons, and move new/upload into a compact add menu beside search. Co-authored-by: Cursor <cursoragent@cursor.com>
Opens from a sparkle button in the template builder so drafting stays out of the main editor until needed. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…psed. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Starter templates were always merged back into the list, and the deleted notice leaked onto every other template. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…borders. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…d controls. Co-authored-by: Cursor <cursoragent@cursor.com>
…ces. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Keep AI draft parsing, preview, and send validation on one sample map and extractor so allowed fields cannot drift. Co-authored-by: Cursor <cursoragent@cursor.com>
Avoid reconciling a hidden desktop copy and a hidden mobile copy at once, including a second preview iframe. Co-authored-by: Cursor <cursoragent@cursor.com>
Those actions previously swallowed errors, so a failed parse or group load looked like a no-op. Co-authored-by: Cursor <cursoragent@cursor.com>
Drop the local control class strings so campaign editor controls match other admin surfaces. Co-authored-by: Cursor <cursoragent@cursor.com>
Reuse upsert and campaign content Zod parsers after normalizing markdown URLs so import limits cannot drift from save. Co-authored-by: Cursor <cursoragent@cursor.com>
Email campaigns and application review used identical get/set wrappers; keep one copy next to the other layout hooks. Co-authored-by: Cursor <cursoragent@cursor.com>
Keep the page orchestrator focused on state and layout, and move builder, send, styles, AI draft, and storage into sibling modules. Co-authored-by: Cursor <cursoragent@cursor.com>
Those banners were noisy on HTML upload and other actions; keep failures as toasts instead. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
| throw new EmailCampaignError("Email template not found", 404); | ||
| } | ||
|
|
||
| await hideSeedTemplate(deleted.sourceTemplateId, organizer.id); |
There was a problem hiding this comment.
deleteMasterTemplate hides the seed whose id equals the deleted row's sourceTemplateId, but sourceTemplateId is the renderer layout id that every new/uploaded template defaults to ("mhacks-announcement"), so deleting an unrelated template irreversibly hides the "MHacks announcement" starter for all organizers.
| description: z.string(), | ||
| subject: z.string(), | ||
| previewText: z.string(), | ||
| content: emailCampaignContentSchema.nullable(), |
There was a problem hiding this comment.
The draft-context schema validates the current template strictly (heading min(1), CTA url must be a valid http/mailto URL), so an in-progress template that hasn't been finalized makes generateEmailTemplateDraft throw a ZodError instead of drafting.
| ...getSeedMasterTemplates().filter( | ||
| (template) => | ||
| !hiddenSourceIds.has(template.sourceTemplateId) && | ||
| !usedSourceIds.has(template.sourceTemplateId), |
There was a problem hiding this comment.
listMasterTemplates drops a seed whenever any saved row shares its sourceTemplateId, but new and uploaded templates all default to "mhacks-announcement", so saving the first custom template makes the announcement starter disappear from the list.
| @@ -0,0 +1,89 @@ | |||
| "use client"; | |||

No description provided.