diff --git a/apps/web/src/components/dashboard/QuickCaptureWidget.tsx b/apps/web/src/components/dashboard/QuickCaptureWidget.tsx
index 3a763e8..96cac82 100644
--- a/apps/web/src/components/dashboard/QuickCaptureWidget.tsx
+++ b/apps/web/src/components/dashboard/QuickCaptureWidget.tsx
@@ -3,8 +3,19 @@
import { useState } from "react";
import { Button } from "@mosaic/ui";
import { useRouter } from "next/navigation";
+import { ComingSoon } from "@/components/ui/ComingSoon";
-export function QuickCaptureWidget(): React.JSX.Element {
+/**
+ * Check if we're in development mode (runtime check for testability)
+ */
+function isDevelopment(): boolean {
+ return process.env.NODE_ENV === "development";
+}
+
+/**
+ * Internal Quick Capture Widget implementation
+ */
+function QuickCaptureWidgetInternal(): React.JSX.Element {
const [idea, setIdea] = useState("");
const router = useRouter();
@@ -48,3 +59,27 @@ export function QuickCaptureWidget(): React.JSX.Element {
);
}
+
+/**
+ * Quick Capture Widget (Dashboard version)
+ *
+ * In production: Shows Coming Soon placeholder
+ * In development: Full widget functionality
+ */
+export function QuickCaptureWidget(): React.JSX.Element {
+ // In production, show Coming Soon placeholder
+ if (!isDevelopment()) {
+ return (
+
+
+
+ );
+ }
+
+ // In development, show full widget functionality
+ return ;
+}
diff --git a/apps/web/src/components/dashboard/__tests__/QuickCaptureWidget.test.tsx b/apps/web/src/components/dashboard/__tests__/QuickCaptureWidget.test.tsx
new file mode 100644
index 0000000..91cac92
--- /dev/null
+++ b/apps/web/src/components/dashboard/__tests__/QuickCaptureWidget.test.tsx
@@ -0,0 +1,93 @@
+/**
+ * QuickCaptureWidget (Dashboard) Component Tests
+ * Tests environment-based behavior
+ */
+
+import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
+import { render, screen } from "@testing-library/react";
+import { QuickCaptureWidget } from "../QuickCaptureWidget";
+
+// Mock next/navigation
+vi.mock("next/navigation", () => ({
+ useRouter: (): { push: () => void } => ({
+ push: vi.fn(),
+ }),
+}));
+
+describe("QuickCaptureWidget (Dashboard)", (): void => {
+ beforeEach((): void => {
+ vi.clearAllMocks();
+ });
+
+ afterEach((): void => {
+ vi.unstubAllEnvs();
+ });
+
+ describe("Development mode", (): void => {
+ beforeEach((): void => {
+ vi.stubEnv("NODE_ENV", "development");
+ });
+
+ it("should render the widget form in development", (): void => {
+ render();
+
+ // Should show the header
+ expect(screen.getByText("Quick Capture")).toBeInTheDocument();
+ // Should show the textarea
+ expect(screen.getByRole("textbox")).toBeInTheDocument();
+ // Should show the Save Note button
+ expect(screen.getByRole("button", { name: /save note/i })).toBeInTheDocument();
+ // Should show the Create Task button
+ expect(screen.getByRole("button", { name: /create task/i })).toBeInTheDocument();
+ // Should NOT show Coming Soon badge
+ expect(screen.queryByText("Coming Soon")).not.toBeInTheDocument();
+ });
+
+ it("should have a placeholder for the textarea", (): void => {
+ render();
+
+ const textarea = screen.getByRole("textbox");
+ expect(textarea).toHaveAttribute("placeholder", "What's on your mind?");
+ });
+ });
+
+ describe("Production mode", (): void => {
+ beforeEach((): void => {
+ vi.stubEnv("NODE_ENV", "production");
+ });
+
+ it("should show Coming Soon placeholder in production", (): void => {
+ render();
+
+ // Should show Coming Soon badge
+ expect(screen.getByText("Coming Soon")).toBeInTheDocument();
+ // Should show feature name
+ expect(screen.getByText("Quick Capture")).toBeInTheDocument();
+ // Should NOT show the textarea
+ expect(screen.queryByRole("textbox")).not.toBeInTheDocument();
+ // Should NOT show the buttons
+ expect(screen.queryByRole("button", { name: /save note/i })).not.toBeInTheDocument();
+ expect(screen.queryByRole("button", { name: /create task/i })).not.toBeInTheDocument();
+ });
+
+ it("should show description in Coming Soon placeholder", (): void => {
+ render();
+
+ expect(screen.getByText(/jot down ideas for later organization/i)).toBeInTheDocument();
+ });
+ });
+
+ describe("Test mode (non-development)", (): void => {
+ beforeEach((): void => {
+ vi.stubEnv("NODE_ENV", "test");
+ });
+
+ it("should show Coming Soon placeholder in test mode", (): void => {
+ render();
+
+ // Test mode is not development, so should show Coming Soon
+ expect(screen.getByText("Coming Soon")).toBeInTheDocument();
+ expect(screen.queryByRole("textbox")).not.toBeInTheDocument();
+ });
+ });
+});
diff --git a/apps/web/src/components/widgets/QuickCaptureWidget.tsx b/apps/web/src/components/widgets/QuickCaptureWidget.tsx
index b201f6f..46085a2 100644
--- a/apps/web/src/components/widgets/QuickCaptureWidget.tsx
+++ b/apps/web/src/components/widgets/QuickCaptureWidget.tsx
@@ -1,12 +1,48 @@
/**
* Quick Capture Widget - idea/brain dump input
+ *
+ * In production, shows a Coming Soon placeholder since the feature
+ * is not yet complete. Full functionality available in development mode.
*/
import { useState } from "react";
import { Send, Lightbulb } from "lucide-react";
import type { WidgetProps } from "@mosaic/shared";
-export function QuickCaptureWidget({ id: _id, config: _config }: WidgetProps): React.JSX.Element {
+/**
+ * Check if we're in development mode (runtime check for testability)
+ */
+function isDevelopment(): boolean {
+ return process.env.NODE_ENV === "development";
+}
+
+/**
+ * Compact Coming Soon placeholder for widget contexts
+ */
+function WidgetComingSoon(): React.JSX.Element {
+ return (
+
+ {/* Lightbulb Icon */}
+
+
+ {/* Coming Soon Badge */}
+
+ Coming Soon
+
+
+ {/* Feature Name */}
+
Quick Capture
+
+ {/* Description */}
+
Quickly jot down ideas for later organization.
+
+ );
+}
+
+/**
+ * Internal Quick Capture Widget implementation
+ */
+function QuickCaptureWidgetInternal({ id: _id, config: _config }: WidgetProps): React.JSX.Element {
const [input, setInput] = useState("");
const [isSubmitting, setIsSubmitting] = useState(false);
const [recentCaptures, setRecentCaptures] = useState([]);
@@ -92,3 +128,19 @@ export function QuickCaptureWidget({ id: _id, config: _config }: WidgetProps): R
);
}
+
+/**
+ * Quick Capture Widget
+ *
+ * In production: Shows Coming Soon placeholder
+ * In development: Full widget functionality
+ */
+export function QuickCaptureWidget(props: WidgetProps): React.JSX.Element {
+ // In production, show Coming Soon placeholder
+ if (!isDevelopment()) {
+ return ;
+ }
+
+ // In development, show full widget functionality
+ return ;
+}
diff --git a/apps/web/src/components/widgets/__tests__/QuickCaptureWidget.test.tsx b/apps/web/src/components/widgets/__tests__/QuickCaptureWidget.test.tsx
index 1fd2704..3c4d5e1 100644
--- a/apps/web/src/components/widgets/__tests__/QuickCaptureWidget.test.tsx
+++ b/apps/web/src/components/widgets/__tests__/QuickCaptureWidget.test.tsx
@@ -3,7 +3,7 @@
* Following TDD principles
*/
-import { describe, it, expect, vi, beforeEach } from "vitest";
+import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { QuickCaptureWidget } from "../QuickCaptureWidget";
@@ -13,6 +13,12 @@ global.fetch = vi.fn() as typeof global.fetch;
describe("QuickCaptureWidget", (): void => {
beforeEach((): void => {
vi.clearAllMocks();
+ // Set development mode by default for existing tests
+ vi.stubEnv("NODE_ENV", "development");
+ });
+
+ afterEach((): void => {
+ vi.unstubAllEnvs();
});
it("should render input field", (): void => {
@@ -147,4 +153,48 @@ describe("QuickCaptureWidget", (): void => {
expect(screen.getByText("Test note")).toBeInTheDocument();
});
});
+
+ describe("Environment-based behavior", (): void => {
+ it("should show Coming Soon placeholder in production", (): void => {
+ vi.stubEnv("NODE_ENV", "production");
+
+ render();
+
+ // Should show Coming Soon badge
+ expect(screen.getByText("Coming Soon")).toBeInTheDocument();
+ // Should show feature name
+ expect(screen.getByText("Quick Capture")).toBeInTheDocument();
+ // Should show description
+ expect(
+ screen.getByText(/Quickly jot down ideas for later organization/i)
+ ).toBeInTheDocument();
+ // Should NOT show the input field
+ expect(screen.queryByRole("textbox")).not.toBeInTheDocument();
+ // Should NOT show the submit button
+ expect(screen.queryByRole("button")).not.toBeInTheDocument();
+ });
+
+ it("should show full widget in development mode", (): void => {
+ vi.stubEnv("NODE_ENV", "development");
+
+ render();
+
+ // Should show the input field
+ expect(screen.getByRole("textbox")).toBeInTheDocument();
+ // Should show the submit button
+ expect(screen.getByRole("button", { name: /submit/i })).toBeInTheDocument();
+ // Should NOT show Coming Soon badge
+ expect(screen.queryByText("Coming Soon")).not.toBeInTheDocument();
+ });
+
+ it("should show Coming Soon placeholder in test mode (non-development)", (): void => {
+ vi.stubEnv("NODE_ENV", "test");
+
+ render();
+
+ // Test mode is not development, so should show Coming Soon
+ expect(screen.getByText("Coming Soon")).toBeInTheDocument();
+ expect(screen.queryByRole("textbox")).not.toBeInTheDocument();
+ });
+ });
});