diff --git a/modules/rsocials/mod.ts b/modules/rsocials/mod.ts index f8b1c84..6146357 100644 --- a/modules/rsocials/mod.ts +++ b/modules/rsocials/mod.ts @@ -242,8 +242,74 @@ function renderCampaignPage(space: string): string { +
+ Open Thread Builder + +
${phaseHTML} - `; +
+ + + `; } const CAMPAIGN_CSS = ` @@ -277,6 +343,44 @@ const CAMPAIGN_CSS = ` .campaign-post__content { font-size: 0.8rem; color: #94a3b8; line-height: 1.5; margin: 0 0 0.5rem; } .campaign-post__tags { display: flex; flex-wrap: wrap; gap: 0.25rem; } .campaign-tag { font-size: 0.65rem; color: #7dd3fc; } +.campaign-page__actions { display: flex; gap: 0.75rem; margin-bottom: 1.5rem; } +.campaign-action-btn { + padding: 0.5rem 1rem; border-radius: 8px; font-size: 0.85rem; font-weight: 600; + cursor: pointer; transition: all 0.15s; text-decoration: none; display: inline-flex; align-items: center; +} +.campaign-action-btn--primary { background: #6366f1; color: white; border: none; } +.campaign-action-btn--primary:hover { background: #818cf8; } +.campaign-action-btn--outline { background: transparent; color: #94a3b8; border: 1px solid #334155; } +.campaign-action-btn--outline:hover { border-color: #6366f1; color: #c4b5fd; } +.campaign-modal-overlay { + position: fixed; inset: 0; background: rgba(0,0,0,0.6); display: flex; + align-items: center; justify-content: center; z-index: 1000; +} +.campaign-modal-overlay[hidden] { display: none; } +.campaign-modal { + background: #1e293b; border: 1px solid #334155; border-radius: 0.75rem; + padding: 1.5rem; width: 90%; max-width: 540px; display: flex; flex-direction: column; gap: 1rem; +} +.campaign-modal__header { display: flex; align-items: center; justify-content: space-between; } +.campaign-modal__header h3 { margin: 0; font-size: 1.1rem; color: #f1f5f9; } +.campaign-modal__close { + background: none; border: none; color: #64748b; font-size: 1.5rem; cursor: pointer; + line-height: 1; padding: 0; +} +.campaign-modal__close:hover { color: #e2e8f0; } +.campaign-modal__textarea { + width: 100%; min-height: 200px; background: #0f172a; color: #e2e8f0; border: 1px solid #334155; + border-radius: 8px; padding: 0.75rem; font-family: inherit; font-size: 0.85rem; resize: vertical; + line-height: 1.5; box-sizing: border-box; +} +.campaign-modal__textarea:focus { outline: none; border-color: #6366f1; } +.campaign-modal__textarea::placeholder { color: #475569; } +.campaign-modal__row { display: flex; gap: 0.75rem; align-items: center; } +.campaign-modal__select { + flex: 1; background: #0f172a; color: #e2e8f0; border: 1px solid #334155; + border-radius: 8px; padding: 0.5rem 0.75rem; font-size: 0.85rem; +} +.campaign-modal__select:focus { outline: none; border-color: #6366f1; } `; routes.get("/campaign", (c) => { @@ -292,6 +396,183 @@ routes.get("/campaign", (c) => { })); }); +// โ”€โ”€ Thread Builder โ”€โ”€ +const THREAD_CSS = ` +.thread-page { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; max-width: 1100px; margin: 0 auto; padding: 2rem 1rem; min-height: 80vh; } +.thread-page__header { grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between; } +.thread-page__header h1 { margin: 0; font-size: 1.5rem; color: #f1f5f9; background: linear-gradient(135deg, #7dd3fc, #c4b5fd); -webkit-background-clip: text; -webkit-text-fill-color: transparent; } +.thread-btn { padding: 0.5rem 1rem; border-radius: 8px; border: none; font-size: 0.85rem; font-weight: 600; cursor: pointer; transition: all 0.15s; } +.thread-btn--primary { background: #6366f1; color: white; } +.thread-btn--primary:hover { background: #818cf8; } +.thread-btn--outline { background: transparent; color: #94a3b8; border: 1px solid #334155; } +.thread-btn--outline:hover { border-color: #6366f1; color: #c4b5fd; } +.thread-compose { position: sticky; top: 1rem; align-self: start; display: flex; flex-direction: column; gap: 1rem; } +.thread-compose__textarea { + width: 100%; min-height: 320px; background: #1e293b; color: #e2e8f0; border: 1px solid #334155; + border-radius: 0.75rem; padding: 1rem; font-family: inherit; font-size: 0.9rem; resize: vertical; + line-height: 1.6; box-sizing: border-box; +} +.thread-compose__textarea:focus { outline: none; border-color: #6366f1; } +.thread-compose__textarea::placeholder { color: #475569; } +.thread-compose__fields { display: flex; gap: 0.75rem; } +.thread-compose__input { + flex: 1; background: #1e293b; color: #e2e8f0; border: 1px solid #334155; + border-radius: 8px; padding: 0.5rem 0.75rem; font-size: 0.85rem; box-sizing: border-box; +} +.thread-compose__input:focus { outline: none; border-color: #6366f1; } +.thread-compose__input::placeholder { color: #475569; } +.thread-preview { display: flex; flex-direction: column; gap: 0; } +.thread-preview__empty { color: #475569; text-align: center; padding: 3rem 1rem; font-size: 0.9rem; } +.tweet-card { + position: relative; background: #1e293b; border: 1px solid #334155; border-radius: 0.75rem; + padding: 1rem; margin-bottom: 0; +} +.tweet-card + .tweet-card { border-top-left-radius: 0; border-top-right-radius: 0; margin-top: -1px; } +.tweet-card:has(+ .tweet-card) { border-bottom-left-radius: 0; border-bottom-right-radius: 0; } +.tweet-card__connector { + position: absolute; left: 29px; top: -1px; width: 2px; height: 1rem; + background: #334155; z-index: 1; +} +.tweet-card__header { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.5rem; } +.tweet-card__avatar { + width: 40px; height: 40px; border-radius: 50%; background: #6366f1; + display: flex; align-items: center; justify-content: center; color: white; + font-weight: 700; font-size: 1rem; flex-shrink: 0; +} +.tweet-card__name { font-weight: 700; color: #f1f5f9; font-size: 0.9rem; } +.tweet-card__handle { color: #64748b; font-size: 0.85rem; } +.tweet-card__dot { color: #64748b; font-size: 0.85rem; } +.tweet-card__time { color: #64748b; font-size: 0.85rem; } +.tweet-card__content { color: #e2e8f0; font-size: 0.95rem; line-height: 1.6; margin: 0 0 0.75rem; white-space: pre-wrap; word-break: break-word; } +.tweet-card__footer { display: flex; align-items: center; justify-content: space-between; } +.tweet-card__actions { display: flex; gap: 1.25rem; } +.tweet-card__action { display: flex; align-items: center; gap: 0.3rem; color: #64748b; font-size: 0.8rem; cursor: default; } +.tweet-card__action svg { width: 16px; height: 16px; } +.tweet-card__meta { display: flex; align-items: center; gap: 0.75rem; font-size: 0.75rem; color: #64748b; } +.tweet-card__chars { font-variant-numeric: tabular-nums; } +.tweet-card__chars--over { color: #ef4444; font-weight: 600; } +.tweet-card__thread-num { color: #6366f1; font-weight: 600; } +@media (max-width: 700px) { + .thread-page { grid-template-columns: 1fr; } + .thread-compose { position: static; } +} +`; + +function renderThreadBuilderPage(space: string): string { + return ` +
+
+

Thread Builder

+ +
+
+ +
+ + +
+
+
+
Your tweet thread preview will appear here
+
+
+ `; +} + +routes.get("/thread", (c) => { + const space = c.req.param("space") || "demo"; + return c.html(renderShell({ + title: `Thread Builder โ€” rSocials | rSpace`, + moduleId: "rsocials", + spaceSlug: space, + modules: getModuleInfoList(), + theme: "dark", + body: renderThreadBuilderPage(space), + styles: ``, + })); +}); + +// โ”€โ”€ Campaigns redirect (plural โ†’ singular) โ”€โ”€ +routes.get("/campaigns", (c) => { + const space = c.req.param("space") || "demo"; + return c.redirect(`/${space}/rsocials/campaign`); +}); + // โ”€โ”€ Page route โ”€โ”€ routes.get("/", (c) => { const space = c.req.param("space") || "demo";