From be257ac71e9b87f1672c406ad4a6b0d22c4eacb7 Mon Sep 17 00:00:00 2001 From: Alice Hernandez Date: Mon, 15 Jun 2026 22:32:36 +1000 Subject: [PATCH] =?UTF-8?q?=F0=9F=92=84=20spruce=20up=20markets=20and=20su?= =?UTF-8?q?bmissions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderer/App.tsx | 6 +- .../components/MarketsView/MarketsView.tsx | 205 ++++++++++++++++++ .../components/Sidebar/StorySidebar.tsx | 15 +- .../components/SubmissionPanel/StoryTab.tsx | 44 ++-- .../SubmissionPanel/SubmissionPanel.tsx | 21 +- src/renderer/store/borgesStore.ts | 8 +- src/renderer/styles/app.css | 79 +++++-- 7 files changed, 319 insertions(+), 59 deletions(-) create mode 100644 src/renderer/components/MarketsView/MarketsView.tsx diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index 03fe30c..65ef8c2 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -6,6 +6,7 @@ import { AnalysisToolbar } from './components/Toolbar/AnalysisToolbar' import { SubmissionPanel } from './components/SubmissionPanel/SubmissionPanel' import { ChatPanel } from './components/AIChat/ChatPanel' import { Dashboard } from './components/Dashboard/Dashboard' +import { MarketsView } from './components/MarketsView/MarketsView' import { SettingsDialog } from './components/Settings/SettingsDialog' export default function App(): JSX.Element { @@ -21,6 +22,7 @@ export default function App(): JSX.Element { setMarkets, setSubmissions, revisionPanelOpen, toggleRevisionPanel, + mainView, initPrefs, loadSession } = useBorgesStore() @@ -186,7 +188,9 @@ export default function App(): JSX.Element { {/* Editor area */}
- {activeStoryId ? ( + {mainView === 'markets' ? ( + + ) : activeStoryId ? ( <> {aiEnabled && } diff --git a/src/renderer/components/MarketsView/MarketsView.tsx b/src/renderer/components/MarketsView/MarketsView.tsx new file mode 100644 index 0000000..f33b892 --- /dev/null +++ b/src/renderer/components/MarketsView/MarketsView.tsx @@ -0,0 +1,205 @@ +import { useState } from 'react' +import { useBorgesStore } from '../../store/borgesStore' +import type { Market } from '../../types/borges' + +const EMPTY_MARKET: Omit = { + name: '', + url: '', + wordCountMax: 1000, + wordCountMin: undefined, + simultaneousSubs: false, + responseTimeWeeks: undefined, + genres: [], + notes: '', + active: true +} + +function slug(name: string): string { + return name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '') +} + +interface MarketFormProps { + market: Market + isNew: boolean + onSave: (m: Market) => void + onCancel: () => void + onDelete?: () => void +} + +function MarketForm({ market, isNew, onSave, onCancel, onDelete }: MarketFormProps): JSX.Element { + const [form, setForm] = useState({ ...market }) + const update = (key: K, value: Market[K]): void => setForm((f) => ({ ...f, [key]: value })) + + const handleSave = (): void => { + if (!form.name.trim()) return + const id = form.id || slug(form.name) + onSave({ ...form, id }) + } + + return ( +
+
{isNew ? 'Add market' : 'Edit market'}
+
+ + update('name', e.target.value)} placeholder="Smokelong Quarterly" /> +
+
+ + update('url', e.target.value)} placeholder="https://…" /> +
+
+
+ + update('wordCountMin', e.target.value ? parseInt(e.target.value) : undefined)} placeholder="0" /> +
+
+ + update('wordCountMax', parseInt(e.target.value) || 1000)} /> +
+
+
+
+ + update('responseTimeWeeks', e.target.value ? parseInt(e.target.value) : undefined)} /> +
+
+ + +
+
+
+ + update('genres', e.target.value.split(',').map((g) => g.trim()).filter(Boolean))} placeholder="flash, micro, speculative" /> +
+
+ +