Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions apps/web/app/api/sources/[sourceId]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { requireCurrentAccountScope } from "@/server/accounts/current";
import { createSourceDetailRouteHandlers } from "@/server/sources/http";
import { readPastedSource } from "@/server/sources/service";

const handlers = createSourceDetailRouteHandlers({
requireAccountScope: requireCurrentAccountScope,
readPastedSource,
});

export const GET = handlers.GET;
12 changes: 12 additions & 0 deletions apps/web/app/api/sources/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { requireCurrentAccountScope } from "@/server/accounts/current";
import { createSourcesRouteHandlers } from "@/server/sources/http";
import { createPastedSource, listPastedSources } from "@/server/sources/service";

const handlers = createSourcesRouteHandlers({
requireAccountScope: requireCurrentAccountScope,
createPastedSource,
listPastedSources,
});

export const GET = handlers.GET;
export const POST = handlers.POST;
180 changes: 180 additions & 0 deletions apps/web/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,164 @@ h1 {
padding: 10px 12px;
}

.sourceWorkspace {
display: grid;
gap: 16px;
grid-template-columns: minmax(0, 1.05fr) minmax(280px, 0.95fr);
margin: 0 auto 24px;
max-width: 1120px;
}

.sourceComposer,
.sourceListPanel {
background: var(--panel);
border: 1px solid var(--line);
border-radius: 8px;
padding: 18px;
}

.sourceComposer {
display: grid;
gap: 14px;
}

.sourceComposer h2,
.sourceListHeader h2 {
font-size: 1.25rem;
line-height: 1.25;
margin-bottom: 0;
}

.sourceComposer label {
display: grid;
font-size: 0.9rem;
font-weight: 700;
gap: 6px;
}

.sourceComposer input,
.sourceComposer textarea {
border: 1px solid var(--line);
border-radius: 6px;
color: var(--ink);
font: inherit;
padding: 10px 12px;
width: 100%;
}

.sourceComposer input {
min-height: 42px;
}

.sourceComposer textarea {
line-height: 1.5;
min-height: 220px;
resize: vertical;
}

.sourceComposer input:disabled,
.sourceComposer textarea:disabled {
background: #f2f4f1;
cursor: not-allowed;
}

.sourceComposerFooter,
.sourceListHeader {
align-items: center;
display: flex;
gap: 12px;
justify-content: space-between;
}

.sourceComposerFooter span {
color: var(--muted);
font-size: 0.82rem;
}

.sourceListPanel {
align-content: start;
display: grid;
gap: 14px;
min-height: 320px;
}

.sourceListHeader strong {
align-items: center;
background: #eaf7f4;
border: 1px solid #b7dcd3;
border-radius: 999px;
color: var(--teal);
display: inline-flex;
font-size: 0.9rem;
justify-content: center;
min-height: 34px;
min-width: 40px;
padding: 0 12px;
}

.sourceState {
align-self: start;
color: var(--muted);
font-size: 0.92rem;
line-height: 1.5;
margin: 0;
}

.sourceList {
display: grid;
gap: 0;
list-style: none;
margin: 0;
padding: 0;
}

.sourceList li {
align-items: start;
border-top: 1px solid var(--line);
display: grid;
gap: 12px;
grid-template-columns: minmax(0, 1fr) auto;
padding: 14px 0;
}

.sourceList li:first-child {
border-top: 0;
padding-top: 0;
}

.sourceList h3 {
font-size: 0.98rem;
line-height: 1.3;
margin: 0 0 4px;
overflow-wrap: anywhere;
}

.sourceList p {
color: var(--muted);
font-size: 0.82rem;
margin: 0;
}

.sourceList dl {
display: grid;
gap: 8px;
margin: 0;
min-width: 112px;
}

.sourceList dt {
color: var(--muted);
font-size: 0.7rem;
font-weight: 700;
text-transform: uppercase;
}

.sourceList dd {
font-size: 0.9rem;
font-weight: 700;
margin: 2px 0 0;
}

.authSwitch {
color: var(--muted);
font-size: 0.9rem;
Expand Down Expand Up @@ -291,6 +449,10 @@ h1 {
.workspaceGrid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}

.sourceWorkspace {
grid-template-columns: 1fr;
}
}

@media (max-width: 560px) {
Expand All @@ -305,4 +467,22 @@ h1 {
.workspaceGrid {
grid-template-columns: 1fr;
}

.sourceComposerFooter,
.sourceList li {
align-items: stretch;
grid-template-columns: 1fr;
}

.sourceComposerFooter {
flex-direction: column;
}

.sourceComposerFooter .buttonLink {
width: 100%;
}

.sourceList dl {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
11 changes: 8 additions & 3 deletions apps/web/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import { HomeShell } from "@/features/home/components/HomeShell";
import { auth } from "@/server/auth";
import { getAccountScopeFromSessionValue } from "@/server/accounts/current";
import { listPastedSources } from "@/server/sources/service";

export default async function Page() {
const session = await auth();
const scope = await getAccountScopeFromSessionValue(session);
const sources = scope ? await listPastedSources(scope) : [];

return (
<HomeShell
initialSources={sources}
user={
session?.user?.accountId
scope
? {
accountId: session.user.accountId,
email: session.user.email,
accountId: scope.accountId,
email: session?.user?.email,
}
: null
}
Expand Down
7 changes: 6 additions & 1 deletion apps/web/features/home/components/HomeShell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@ import { SiteShell } from "@/components/layout/SiteShell";
import { LaneCard } from "@/components/ui/LaneCard";
import { AuthStatus } from "@/features/auth/components/AuthStatus";
import { homeLanes } from "@/features/home/constants";
import { SourcesWorkspace } from "@/features/sources/components/SourcesWorkspace";
import type { SourceSummary } from "@ancora/shared-types";

type HomeShellProps = Readonly<{
user: {
email: string | null | undefined;
accountId: string;
} | null;
initialSources: readonly SourceSummary[];
}>;

export function HomeShell({ user }: HomeShellProps) {
export function HomeShell({ user, initialSources }: HomeShellProps) {
return (
<main className="page">
<header className="workspaceHeader">
Expand All @@ -30,6 +33,8 @@ export function HomeShell({ user }: HomeShellProps) {
</div>
</header>

<SourcesWorkspace initialSources={initialSources} isAuthenticated={Boolean(user)} />

<SiteShell>
{homeLanes.map((lane) => (
<LaneCard key={lane.title} {...lane} />
Expand Down
Loading