Skip to content

Commit

Permalink
basic demo working
Browse files Browse the repository at this point in the history
  • Loading branch information
trevorpfiz committed May 10, 2024
1 parent eb0b9b1 commit 8f267f3
Show file tree
Hide file tree
Showing 21 changed files with 286 additions and 59 deletions.
3 changes: 2 additions & 1 deletion apps/api/src/api/api_v1/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

from src.api.api_v1.routers import health, upload


api_router = APIRouter()


api_router.include_router(
health.router,
prefix="/health",
Expand Down
4 changes: 2 additions & 2 deletions apps/api/src/api/api_v1/routers/health.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
router = APIRouter()


@router.get("/health", status_code=200)
async def health_check(user: str = Depends(verify_token)):
@router.get("", status_code=200)
async def check(user: str = Depends(verify_token)):
"""Secured health check endpoint."""
if not user:
raise HTTPException(status_code=401, detail="Unauthorized")
Expand Down
4 changes: 2 additions & 2 deletions apps/api/src/api/api_v1/routers/upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
router = APIRouter()


@router.post("/upload", status_code=200)
async def upload_zip(file: UploadFile = File(...), user: str = Depends(verify_token)):
@router.post("", status_code=200)
async def zip(file: UploadFile = File(...), user: str = Depends(verify_token)):
"""Secure endpoint to upload and process zip files, ensuring valid JWTs."""
try:
with tempfile.TemporaryDirectory() as temp_dir:
Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class Settings(BaseSettings):

model_config = SettingsConfigDict(env_file=".env")
openapi_url: str = "/openapi.json"
API_VERSION: str = "/api/v1"
API_VERSION: str = "/v1"
ROOT: str = ROOT_PATH


Expand Down
31 changes: 24 additions & 7 deletions apps/api/src/main.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import logging
import os

from fastapi import APIRouter, FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.routing import APIRoute
Expand Down Expand Up @@ -35,13 +38,27 @@ def get_application():
openapi_url=settings.openapi_url,
)

_app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
origins = ["https://app.getwellchart.com"]
environment = os.getenv("VERCEL_ENV", "development")

if environment in ["development"]:
logger = logging.getLogger("uvicorn")
logger.warning("Running in development mode - allowing CORS for all origins")
_app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
else:
_app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)

_app.include_router(api_router, prefix=settings.API_VERSION)
_app.include_router(info_router, tags=[""])
Expand Down
10 changes: 7 additions & 3 deletions apps/nextjs/src/app/(app)/account/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SignOutButton } from "~/components/auth/sign-out-button";
import { createClient } from "~/utils/supabase/server";
import UserSettings from "./user-settings";

Expand All @@ -11,9 +12,12 @@ export default async function Account() {

return (
<main>
<h1 className="my-4 text-2xl font-semibold">Account</h1>
<div className="space-y-4">
<UserSettings user={data.user} />
<div className="flex flex-col gap-4">
<h1 className="my-4 text-2xl font-semibold">Account</h1>
<div className="space-y-4 pb-4">
<UserSettings user={data.user} />
</div>
<SignOutButton />
</div>
</main>
);
Expand Down
16 changes: 6 additions & 10 deletions apps/nextjs/src/app/(app)/dashboard/page.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
import { SignOutButton } from "~/components/auth/sign-out-button";
import { api } from "~/trpc/server";
import { FileUpload } from "~/components/upload/file-upload";
import { createClient } from "~/utils/supabase/server";

export default async function Home() {
const supabase = createClient();
const { data } = await supabase.auth.getSession();

const test = await api.report.test({
token: data?.session?.access_token ?? "",
});

console.log(test);
const token = data?.session?.access_token ?? "";

return (
<main className="">
<h1 className="my-2 text-2xl font-bold">Profile</h1>
<p>{test?.message}</p>
<SignOutButton />
<div className="flex flex-col gap-8">
<h1 className="my-2 text-2xl font-bold">Upload a patient's chart</h1>
<FileUpload token={token} />
</div>
</main>
);
}
38 changes: 38 additions & 0 deletions apps/nextjs/src/app/(app)/reports/[reportId]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Suspense } from "react";
import { notFound } from "next/navigation";

import Loading from "~/app/loading";
import ReportModal from "~/components/reports/report-modal";
import { BackButton } from "~/components/shared/back-button";
import { api } from "~/trpc/server";

export default async function Report({
params,
}: {
params: { reportId: string };
}) {
const { report } = await api.report.byId({ id: Number(params.reportId) });

if (!report) notFound();
return (
<main className="overflow-y-auto">
<Suspense fallback={<Loading />}>
<div className="relative">
<BackButton currentResource="reports" />

<div className="m-4">
<div className="mb-4 flex items-end justify-between">
<h1 className="text-2xl font-semibold">{report.title}</h1>
<div className="flex gap-2">
<ReportModal report={report} />
</div>
</div>
<pre className={"text-wrap break-all rounded-lg bg-secondary p-4"}>
{report.content}
</pre>
</div>
</div>
</Suspense>
</main>
);
}
17 changes: 14 additions & 3 deletions apps/nextjs/src/app/(app)/reports/page.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
import { Suspense } from "react";

import Loading from "~/app/loading";
import ReportList from "~/components/reports/report-list";
import NewReportModal from "~/components/reports/report-modal";
import { api } from "~/trpc/server";

export default async function Reports() {
const reports = await api.report.byUser();
export default function Reports() {
const reports = api.report.byUser();

return (
<main>
<div className="flex justify-between">
<h1 className="my-2 text-2xl font-semibold">Reports</h1>
<NewReportModal />
</div>
<ReportList reports={reports} />
<Suspense
fallback={
<div className="flex w-full flex-col gap-4">
<Loading />
</div>
}
>
<ReportList reports={reports} />
</Suspense>
</main>
);
}
6 changes: 6 additions & 0 deletions apps/nextjs/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,14 @@ import { TRPCReactProvider } from "~/trpc/react";

import "~/app/globals.css";

import { OpenAPI } from "@wellchart/api/client";

import { env } from "~/env";

if (process.env.NODE_ENV === "production") {
OpenAPI.BASE = env.FASTAPI_URL;
}

export const metadata: Metadata = {
metadataBase: new URL(
env.VERCEL_ENV === "production"
Expand Down
8 changes: 7 additions & 1 deletion apps/nextjs/src/components/reports/report-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,13 @@ const ReportForm = ({
}

await utils.report.byUser.invalidate();
router.refresh();

if (action === "delete") {
router.push("/reports");
} else if (action === "update") {
router.refresh();
}

if (closeModal) closeModal();
toast.success(`Report ${action}d!`);
};
Expand Down
20 changes: 11 additions & 9 deletions apps/nextjs/src/components/reports/report-list.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
"use client";

import { use } from "react";
import Link from "next/link";

import type { RouterOutputs } from "@wellchart/api";
import type { Report } from "@wellchart/db/schema";
import { Button } from "@wellchart/ui/button";

import { api } from "~/trpc/react";
import ReportModal from "./report-modal";

type UserReportsOutput = RouterOutputs["report"]["byUser"];

export default function ReportList({
reports,
}: {
reports: UserReportsOutput;
export default function ReportList(props: {
reports: Promise<RouterOutputs["report"]["byUser"]>;
}) {
const initialData = use(props.reports);
const { data: r } = api.report.byUser.useQuery(undefined, {
initialData: reports,
refetchOnMount: false,
initialData,
});

if (r.reports.length === 0) {
Expand All @@ -37,7 +37,9 @@ const Report = ({ report }: { report: Report }) => {
<div className="w-full">
<div>{report.title}</div>
</div>
<ReportModal report={report} />
<Button variant={"ghost"} size={"sm"} asChild>
<Link href={`/reports/${report.id}`}>{"View"}</Link>
</Button>
</li>
);
};
Expand Down
33 changes: 33 additions & 0 deletions apps/nextjs/src/components/shared/back-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"use client";

import Link from "next/link";
import { usePathname } from "next/navigation";
import { ChevronLeftIcon } from "lucide-react";

import { Button } from "@wellchart/ui/button";

export function useBackPath(currentResource: string) {
const pathname = usePathname();
const segmentCount = pathname.slice(1).split("/");
const backPath =
segmentCount.length > 2
? pathname.slice(0, pathname.indexOf(currentResource) - 1)
: pathname.slice(0, pathname.indexOf(segmentCount[1]));
return backPath;
}

export function BackButton({
currentResource,
}: {
/* must be in kebab-case */
currentResource: string;
}) {
const backPath = useBackPath(currentResource);
return (
<Button variant={"ghost"} asChild>
<Link href={backPath}>
<ChevronLeftIcon />
</Link>
</Button>
);
}
Loading

0 comments on commit 8f267f3

Please sign in to comment.