Skip to content
Open
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
13 changes: 6 additions & 7 deletions apps/backend/lambdas/projects/db.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Kysely, PostgresDialect } from 'kysely';
import { Pool } from 'pg';
import type { DB } from './db-types';
import { Kysely, PostgresDialect } from 'kysely'
import { Pool } from 'pg'
import type { DB } from './db-types'

const db = new Kysely<DB>({
dialect: new PostgresDialect({
Expand All @@ -10,9 +10,8 @@ const db = new Kysely<DB>({
user: process.env.DB_USER ?? 'branch_dev',
password: process.env.DB_PASSWORD ?? 'password',
database: process.env.DB_NAME ?? 'branch_db',
ssl: false,
ssl: false,
}),
}),
});

export default db;
})
export default db
22 changes: 19 additions & 3 deletions apps/backend/lambdas/projects/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
import db from './db';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm is there any chance you're not on a clean branch? These changes don't look related to the header component

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same with db.ts, openai.yaml changes

import { ProjectValidationUtils } from './validation-utils';


export const handler = async (event: any): Promise<APIGatewayProxyResult> => {
try {
// Support both API Gateway and Lambda Function URL events
Expand All @@ -19,7 +18,25 @@ export const handler = async (event: any): Promise<APIGatewayProxyResult> => {

// >>> ROUTES-START (do not remove this marker)
// CLI-generated routes will be inserted here

// GET /projects/{id}/members
if (normalizedPath.startsWith('/projects/') && normalizedPath.split('/').length === 4 && method === 'GET') {
const id = normalizedPath.split('/')[2];
if (!id) return json(400, { message: 'id is required' });
const users = await db
.selectFrom('branch.project_memberships as pm')
.innerJoin('branch.users as u', 'u.user_id', 'pm.user_id')
.select([
'u.user_id',
'u.name',
'u.email',
'pm.role'
])
.where('pm.project_id', '=', id)
.execute();
return json(200, { ok: true, route: 'GET /projects/{id}/members', pathParams: { id }, body: {
users
}});
}
// GET /projects
if (rawPath === '/' && method === 'GET') {
const projects = await db.selectFrom("branch.projects").selectAll().execute();
Expand Down Expand Up @@ -72,7 +89,6 @@ export const handler = async (event: any): Promise<APIGatewayProxyResult> => {
}
}
// <<< ROUTES-END

return json(404, { message: 'Not Found', path: normalizedPath, method });
} catch (err) {
console.error('Lambda error:', err);
Expand Down
9 changes: 9 additions & 0 deletions apps/backend/lambdas/projects/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ paths:
ok:
type: boolean

/projects/{id}/members:
get:
summary: GET /projects/{id}/members
parameters:
- in: path
name: id
required: true
schema:
type: string
/projects:
post:
summary: POST /projects
Expand Down
20 changes: 20 additions & 0 deletions apps/frontend/src/app/components/Header.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom'; // Add this line to fix the error
import Header from './Header';

describe('Header Component', () => {
it('renders the default title when no props are provided', () => {
render(<Header />);
expect(screen.getByText(/BRANCH Accounting Platform/i)).toBeInTheDocument();
});
});

it('renders a custom title when the text prop is provided', () => {
render(<Header text="Custom Title" />);
expect(screen.getByText(/Custom Title/i)).toBeInTheDocument();
});

it('renders a custom icon when the icon prop is provided', () => {
render(<Header icon={<span data-testid="custom-icon">★</span>} />);
expect(screen.getByTestId('custom-icon')).toBeInTheDocument();
});
32 changes: 32 additions & 0 deletions apps/frontend/src/app/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react';

interface HeaderProps {
text?: string;
icon?: React.ReactNode;
}

const Header: React.FC<HeaderProps> = ({
text = "BRANCH Accounting Platform",
icon
}) => {
return (
<header className="flex h-16 w-full items-center justify-between border-b border-gray-200 bg-white px-8">
{/* Dynamic Text Section */}
<span className="text-sm font-bold text-gray-800">
{text}
</span>

{/* Flexible Icon Section */}
<div className="flex items-center">
{icon || (
// Default Profile Icon matching Figma
<div className="h-8 w-8 rounded-full border border-gray-300 flex items-center justify-center">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle></svg>
</div>
)}
</div>
</header>
);
};

export default Header;
111 changes: 15 additions & 96 deletions apps/frontend/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,103 +1,22 @@
import Image from "next/image";
import Header from "./components/Header";

export default function Home() {
return (
<div className="font-sans grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20">
<main className="flex flex-col gap-[32px] row-start-2 items-center sm:items-start">
<Image
className="dark:invert"
src="/next.svg"
alt="Next.js logo"
width={180}
height={38}
priority
/>
<ol className="font-mono list-inside list-decimal text-sm/6 text-center sm:text-left">
<li className="mb-2 tracking-[-.01em]">
Get started by editing{" "}
<code className="bg-black/[.05] dark:bg-white/[.06] font-mono font-semibold px-1 py-0.5 rounded">
src/app/page.tsx
</code>
.
</li>
<li className="tracking-[-.01em]">
Save and see your changes instantly.
</li>
</ol>
<div className="min-h-screen bg-gray-50 font-sans">
{/* 1. Default Header - Verify this matches Figma */}
<Header />

<div className="flex gap-4 items-center flex-col sm:flex-row">
<a
className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-foreground text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:w-auto"
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
className="dark:invert"
src="/vercel.svg"
alt="Vercel logomark"
width={20}
height={20}
/>
Deploy now
</a>
<a
className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 w-full sm:w-auto md:w-[158px]"
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Read our docs
</a>
</div>
</main>
<footer className="row-start-3 flex gap-[24px] flex-wrap items-center justify-center">
<a
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
aria-hidden
src="/file.svg"
alt="File icon"
width={16}
height={16}
/>
Learn
</a>
<a
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
aria-hidden
src="/window.svg"
alt="Window icon"
width={16}
height={16}
/>
Examples
</a>
<a
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
aria-hidden
src="/globe.svg"
alt="Globe icon"
width={16}
height={16}
/>
Go to nextjs.org →
</a>
</footer>
<main className="p-10 flex flex-col gap-8">
<section>
<h2 className="text-sm font-semibold text-gray-500 uppercase tracking-wider mb-4">
Visual Verification
</h2>
<p className="text-gray-600">
The header above should show <strong>"BRANCH Accounting Platform"</strong> and the
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great for testing but can we remove this extra text for now? Shouldn't need any changes to this file!

profile icon on the far right.
</p>
</section>
</main>
</div>
);
}
Loading