student table optimization adn docker testing

This commit is contained in:
Om Lanke
2025-07-02 22:10:56 +05:30
parent 449629ece2
commit 0032a4743c
18 changed files with 297 additions and 19 deletions

18
.dockerignore Normal file
View File

@@ -0,0 +1,18 @@
Dockerfile
.dockerignore
node_modules
npm-debug.log
README.md
.next
.git
.pnp
.pnp.js
.turbo
.vercel
.next/
out/
build
dist
npm-debug.log*
.DS_Store
*.pem

29
Dockerfile Normal file
View File

@@ -0,0 +1,29 @@
FROM node:22-alpine AS base
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable && corepack prepare pnpm@latest --activate
FROM base AS builder
RUN apk update && apk add --no-cache libc6-compat
WORKDIR /app
RUN pnpm add -g turbo@^2
COPY . .
RUN turbo prune admin --docker
FROM base AS installer
RUN apk update && apk add --no-cache libc6-compat
WORKDIR /app
COPY --from=builder /app/out/json/ .
RUN pnpm fetch --frozen-lockfile
RUN pnpm install --offline --frozen-lockfile --prod=false
COPY --from=builder /app/out/full/ .
RUN pnpm turbo run build
FROM base AS runner
WORKDIR /app
RUN addgroup --system --gid 1001 nodejs && adduser --system --uid 1001 nextjs
USER nextjs
COPY --from=installer --chown=nextjs:nodejs /app/apps/web/.next/standalone ./
COPY --from=installer --chown=nextjs:nodejs /app/apps/web/.next/static ./apps/web/.next/static
COPY --from=installer --chown=nextjs:nodejs /app/apps/web/public ./apps/web/public
CMD node apps/web/server.js

29
apps/admin/Dockerfile Normal file
View File

@@ -0,0 +1,29 @@
FROM node:22-alpine AS base
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable && corepack prepare pnpm@latest --activate
FROM base AS builder
RUN apk update && apk add --no-cache libc6-compat
WORKDIR /app
RUN pnpm add -g turbo@^2
COPY . .
RUN turbo prune admin --docker
FROM base AS installer
RUN apk update && apk add --no-cache libc6-compat
WORKDIR /app
COPY --from=builder /app/out/json/ .
RUN pnpm fetch --frozen-lockfile
RUN pnpm install --offline --frozen-lockfile --prod=false
COPY --from=builder /app/out/full/ .
RUN pnpm turbo run build
FROM base AS runner
WORKDIR /app
RUN addgroup --system --gid 1001 nodejs && adduser --system --uid 1001 nextjs
USER nextjs
COPY --from=installer --chown=nextjs:nodejs /app/apps/web/.next/standalone ./
COPY --from=installer --chown=nextjs:nodejs /app/apps/web/.next/static ./apps/web/.next/static
COPY --from=installer --chown=nextjs:nodejs /app/apps/web/public ./apps/web/public
CMD node apps/web/server.js

View File

@@ -1,19 +1,13 @@
import Login from '@/components/login';
import Studs from '@/components/studs';
import { db, admins } from '@workspace/db';
import { auth, signIn, signOut } from '@/auth';
import { db, students } from '@workspace/db';
import { auth, signOut } from '@/auth';
async function getStudents() {
'use server';
const s = await db.select().from(admins);
const s = await db.select().from(students);
console.log(s);
}
async function logIn() {
'use server';
await signIn('google');
}
async function logOut() {
'use server';
await signOut();
@@ -25,7 +19,6 @@ export default async function Page() {
<div className="flex items-center justify-center min-h-svh">
<div className="flex flex-col items-center justify-center gap-4">
<h1 className="text-2xl font-bold">Hello admin {session?.user?.name}</h1>
{!session?.user && <Login action={logIn} />}
<Studs action={getStudents} logOut={logOut} />
</div>
</div>

View File

@@ -6,20 +6,39 @@ const studentSelectSchema = createSelectSchema(students);
export type Student = z.infer<typeof studentSelectSchema>;
export const columns: ColumnDef<Student>[] = [
{
accessorKey: 'id',
header: 'ID',
},
{
accessorKey: 'firstName',
header: 'First Name',
filterFn: 'includesString',
},
{
accessorKey: 'lastName',
header: 'Last Name',
filterFn: 'includesString',
},
{
accessorKey: 'rollNumber',
header: 'Roll Number',
filterFn: 'includesString',
},
{
accessorKey: 'email',
header: 'Email',
filterFn: 'includesString',
},
{
accessorKey: 'yearOfGraduation',
header: 'Year of Graduation',
filterFn: 'includesString',
},
{
accessorKey: 'degree',
header: 'Degree',
filterFn: 'includesString',
},
{
accessorKey: 'branch',
header: 'Branch',
filterFn: 'includesString',
},
];

View File

@@ -1,6 +1,12 @@
'use client';
import { ColumnDef, flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table';
import {
ColumnDef,
flexRender,
getCoreRowModel,
getPaginationRowModel,
useReactTable,
} from '@tanstack/react-table';
import {
Table,
@@ -21,6 +27,7 @@ export function DataTable<TData, TValue>({ columns, data }: DataTableProps<TData
data,
columns,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
});
return (

View File

@@ -0,0 +1,30 @@
'use client';
import { useEffect } from 'react';
import { Button } from '@workspace/ui/components/button';
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
useEffect(() => {
console.error('Students page error:', error);
}, [error]);
return (
<div className="container mx-auto py-10">
<div className="flex flex-col items-center justify-center space-y-4 p-8">
<h2 className="text-2xl font-semibold">Something went wrong!</h2>
<p className="text-muted-foreground text-center">
Failed to load students data. Please try again.
</p>
<Button onClick={reset} variant="outline">
Try again
</Button>
</div>
</div>
);
}

View File

@@ -0,0 +1,63 @@
import { Skeleton } from '@workspace/ui/components/skeleton';
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@workspace/ui/components/table';
export default function Loading() {
return (
<div className="container mx-auto py-10">
<div className="space-y-4">
{/* Header skeleton */}
<div className="flex items-center justify-between">
<h1 className="text-2xl font-semibold tracking-tight">Students</h1>
<Skeleton className="h-4 w-24" />
</div>
{/* Table skeleton */}
<div className="rounded-md border">
<Table>
<TableHeader>
<TableRow>
<TableHead>
<Skeleton className="h-4 w-8" />
</TableHead>
<TableHead>
<Skeleton className="h-4 w-20" />
</TableHead>
<TableHead>
<Skeleton className="h-4 w-20" />
</TableHead>
<TableHead>
<Skeleton className="h-4 w-32" />
</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{Array.from({ length: 8 }).map((_, index) => (
<TableRow key={index}>
<TableCell>
<Skeleton className="h-4 w-8" />
</TableCell>
<TableCell>
<Skeleton className="h-4 w-24" />
</TableCell>
<TableCell>
<Skeleton className="h-4 w-24" />
</TableCell>
<TableCell>
<Skeleton className="h-4 w-40" />
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
</div>
</div>
);
}

View File

@@ -3,16 +3,32 @@ import { DataTable } from './data-table';
import { db, students } from '@workspace/db';
async function getData(): Promise<Student[]> {
const data = db.select().from(students);
const data = await db.select().from(students);
return data;
}
export default async function DemoPage() {
async function StudentsTable() {
const data = await getData();
return (
<div className="container mx-auto py-10">
<div className="space-y-4">
<div className="flex items-center justify-between">
<h1 className="text-2xl font-semibold tracking-tight">Students</h1>
<div className="text-sm text-muted-foreground">
{data.length} {data.length === 1 ? 'student' : 'students'} total
</div>
</div>
<DataTable columns={columns} data={data} />
</div>
</div>
);
}
export default function StudentsPage() {
return (
<StudentsTable />
);
}
export const dynamic = 'force-dynamic';

View File

@@ -1,6 +1,12 @@
/** @type {import('next').NextConfig} */
import path from 'path';
const __dirname = path.resolve();
const nextConfig = {
transpilePackages: ['@workspace/ui', '@workspace/db'],
output: 'standalone',
outputFileTracingRoot: path.join(__dirname, '../../'),
};
export default nextConfig;

View File

@@ -12,6 +12,7 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@tailwindcss/postcss": "^4.0.8",
"@tanstack/react-table": "^8.21.3",
"@workspace/db": "workspace:*",
"@workspace/ui": "workspace:*",
@@ -22,6 +23,7 @@
"next-themes": "^0.4.6",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"tailwindcss": "^4.0.8",
"zod": "^3.25.67"
},
"devDependencies": {

38
apps/student/Dockerfile Normal file
View File

@@ -0,0 +1,38 @@
FROM node:22-alpine AS base
FROM base AS builder
RUN apk update
RUN apk add --no-cache libc6-compat
WORKDIR /app
RUN corepack enable pnpm && pnpm add -g turbo@^2
COPY . .
RUN turbo prune student --docker
FROM base AS installer
RUN apk update
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY --from=builder /app/out/json/ .
RUN yarn install --frozen-lockfile
COPY --from=builder /app/out/full/ .
RUN pnpm turbo run build
FROM base AS runner
WORKDIR /app
# Don't run production as root
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
USER nextjs
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=installer --chown=nextjs:nodejs /app/apps/web/.next/standalone ./
COPY --from=installer --chown=nextjs:nodejs /app/apps/web/.next/static ./apps/web/.next/static
COPY --from=installer --chown=nextjs:nodejs /app/apps/web/public ./apps/web/public
CMD node apps/web/server.js

View File

@@ -1,6 +1,12 @@
/** @type {import('next').NextConfig} */
import path from 'path';
const __dirname = path.resolve();
const nextConfig = {
transpilePackages: ['@workspace/ui', '@workspace/db'],
output: 'standalone',
outputFileTracingRoot: path.join(__dirname, '../../'),
};
export default nextConfig;

View File

@@ -6,6 +6,7 @@
"build": "turbo build",
"dev": "turbo dev",
"lint": "turbo lint",
"start": "turbo start",
"format": "prettier --write \"**/*.{ts,tsx,md}\"",
"db:check": "pnpm --filter @workspace/db check",
"db:generate": "pnpm --filter @workspace/db generate",

View File

@@ -0,0 +1,12 @@
import { cn } from '@workspace/ui/lib/utils';
function Skeleton({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
return (
<div
className={cn('animate-pulse rounded-md bg-muted', className)}
{...props}
/>
);
}
export { Skeleton };

6
pnpm-lock.yaml generated
View File

@@ -26,6 +26,9 @@ importers:
apps/admin:
dependencies:
'@tailwindcss/postcss':
specifier: ^4.0.8
version: 4.1.11
'@tanstack/react-table':
specifier: ^8.21.3
version: 8.21.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
@@ -56,6 +59,9 @@ importers:
react-dom:
specifier: ^19.1.0
version: 19.1.0(react@19.1.0)
tailwindcss:
specifier: ^4.0.8
version: 4.1.11
zod:
specifier: ^3.25.67
version: 3.25.67

View File

@@ -16,6 +16,9 @@
"dev": {
"cache": false,
"persistent": true
},
"start": {
"persistent": true
}
}
}