diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..0d41776 --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,18 @@ +/** @type { import("eslint").Linter.Config } */ +module.exports = { + root: true, + env: { node: true, es2022: true }, + extends: ["eslint:recommended", "prettier"], + ignorePatterns: [ + "node_modules", + ".next", + "dist", + "build", + "coverage", + "*.config.js", + "*.config.cjs", + "*.config.mjs", + "*.config.ts", + ], +}; + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..adfc278 --- /dev/null +++ b/.gitignore @@ -0,0 +1,34 @@ +# Dependencies +node_modules/ +.pnpm-store/ + +# Build outputs +.next/ +out/ +dist/ +build/ +*.tsbuildinfo + +# Environment +.env +.env.local +.env.*.local + +# IDE / OS +.idea/ +.vscode/ +*.swp +.DS_Store +Thumbs.db + +# Debug / logs +npm-debug.log* +pnpm-debug.log* +*.log + +# Testing +coverage/ +.nyc_output/ + +# Misc +*.pem diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..209e3ef --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +20 diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..8683e95 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,8 @@ +node_modules +.next +dist +build +coverage +*.min.js +pnpm-lock.yaml +package-lock.json diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..3d03824 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,9 @@ +{ + "semi": true, + "singleQuote": false, + "tabWidth": 2, + "trailingComma": "es5", + "printWidth": 100, + "bracketSameLine": false, + "endOfLine": "lf" +} diff --git a/DBIS/.env.example b/DBIS/.env.example new file mode 100644 index 0000000..8e389e0 --- /dev/null +++ b/DBIS/.env.example @@ -0,0 +1,8 @@ +# Next.js +NEXTAUTH_URL=http://localhost:3000 + +# OIDC / OAuth 2.0 (placeholder until identity provider is configured) +# OIDC_ISSUER= +# OIDC_CLIENT_ID= +# OIDC_CLIENT_SECRET= +# OIDC_REDIRECT_URI= diff --git a/DBIS/.eslintrc.cjs b/DBIS/.eslintrc.cjs new file mode 100644 index 0000000..53dff50 --- /dev/null +++ b/DBIS/.eslintrc.cjs @@ -0,0 +1,5 @@ +/** @type { import("eslint").Linter.Config } */ +module.exports = { + root: true, + extends: ["../.eslintrc.cjs", "next/core-web-vitals"], +}; diff --git a/DBIS/README.md b/DBIS/README.md new file mode 100644 index 0000000..2d6b6d2 --- /dev/null +++ b/DBIS/README.md @@ -0,0 +1,29 @@ +# DBIS Portal + +Portal for the **Digital Bank of International Settlements**. + +**Gitea repository:** https://gitea.d-bis.org/Gov_Web_Portals/DBIS.git Next-generation web application following the shared tech stack and policies. + +## Run locally + +```bash +pnpm install +pnpm dev +``` + +Open [http://localhost:3000](http://localhost:3000). + +## Environment + +Copy `.env.example` to `.env.local` and set values. No secrets in repo. + +## Standards + +- [TECH_STACK.md](../TECH_STACK.md) +- [TECH_POLICIES.md](../TECH_POLICIES.md) +- [PORTAL_NAVIGATION.md](../PORTAL_NAVIGATION.md) +- [ORG_STRUCTURE.md](../ORG_STRUCTURE.md) + +## Structure + +Same app structure as other portals: public routes, transparency, workflow (submit/apply/report/request), dashboard, auth. Entity-specific routes: Financial Bulletins, Monetary Operations. diff --git a/DBIS/app/(auth)/login/page.tsx b/DBIS/app/(auth)/login/page.tsx new file mode 100644 index 0000000..48101a9 --- /dev/null +++ b/DBIS/app/(auth)/login/page.tsx @@ -0,0 +1,55 @@ +"use client"; + +import { Suspense } from "react"; +import { useSearchParams } from "next/navigation"; +import Link from "next/link"; + +function LoginForm() { + const searchParams = useSearchParams(); + const returnUrl = searchParams.get("returnUrl") ?? "/dashboard"; + + return ( +
+

Sign in

+

+ Placeholder login. Replace with OIDC/OAuth 2.0 when identity provider is configured. +

+
+ +
+ + +
+ +
+

+ + Return to previous page + +

+
+ ); +} + +export default function LoginPage() { + return ( + Loading...}> + + + ); +} diff --git a/DBIS/app/(auth)/logout/page.tsx b/DBIS/app/(auth)/logout/page.tsx new file mode 100644 index 0000000..fd763a6 --- /dev/null +++ b/DBIS/app/(auth)/logout/page.tsx @@ -0,0 +1,20 @@ +"use client"; + +import { useEffect } from "react"; +import Link from "next/link"; + +export default function LogoutPage() { + useEffect(() => { + document.cookie = "portal-role=; path=/; max-age=0"; + }, []); + + return ( +
+

Signed out

+

You have been signed out.

+ + Return to home + +
+ ); +} diff --git a/DBIS/app/(public)/about/page.tsx b/DBIS/app/(public)/about/page.tsx new file mode 100644 index 0000000..0b87c58 --- /dev/null +++ b/DBIS/app/(public)/about/page.tsx @@ -0,0 +1,8 @@ +export default function AboutPage() { + return ( +
+

Mandate

+

About the Digital Bank of International Settlements.

+
+ ); +} diff --git a/DBIS/app/(public)/accreditation/page.tsx b/DBIS/app/(public)/accreditation/page.tsx new file mode 100644 index 0000000..c5e95d2 --- /dev/null +++ b/DBIS/app/(public)/accreditation/page.tsx @@ -0,0 +1,8 @@ +export default function AccreditationPage() { + return ( +
+

Accreditation

+

Accreditation and credentials.

+
+ ); +} diff --git a/DBIS/app/(public)/contact/page.tsx b/DBIS/app/(public)/contact/page.tsx new file mode 100644 index 0000000..7bb6a85 --- /dev/null +++ b/DBIS/app/(public)/contact/page.tsx @@ -0,0 +1,8 @@ +export default function ContactPage() { + return ( +
+

Contact

+

General contact and enquiries.

+
+ ); +} diff --git a/DBIS/app/(public)/departments/page.tsx b/DBIS/app/(public)/departments/page.tsx new file mode 100644 index 0000000..ed01731 --- /dev/null +++ b/DBIS/app/(public)/departments/page.tsx @@ -0,0 +1,8 @@ +export default function DepartmentsPage() { + return ( +
+

Departments

+

Mission departments and programs.

+
+ ); +} diff --git a/DBIS/app/(public)/documents/page.tsx b/DBIS/app/(public)/documents/page.tsx new file mode 100644 index 0000000..c641e1d --- /dev/null +++ b/DBIS/app/(public)/documents/page.tsx @@ -0,0 +1,8 @@ +export default function DocumentsPage() { + return ( +
+

Documents

+

Library, standards, and directives.

+
+ ); +} diff --git a/DBIS/app/(public)/governance/page.tsx b/DBIS/app/(public)/governance/page.tsx new file mode 100644 index 0000000..8cf0212 --- /dev/null +++ b/DBIS/app/(public)/governance/page.tsx @@ -0,0 +1,8 @@ +export default function GovernancePage() { + return ( +
+

Governance

+

Charters, instruments, and governance.

+
+ ); +} diff --git a/DBIS/app/(public)/leadership/page.tsx b/DBIS/app/(public)/leadership/page.tsx new file mode 100644 index 0000000..ff1f679 --- /dev/null +++ b/DBIS/app/(public)/leadership/page.tsx @@ -0,0 +1,8 @@ +export default function LeadershipPage() { + return ( +
+

Leadership

+

Executive leadership and secretariat.

+
+ ); +} diff --git a/DBIS/app/(public)/membership/page.tsx b/DBIS/app/(public)/membership/page.tsx new file mode 100644 index 0000000..cf191d0 --- /dev/null +++ b/DBIS/app/(public)/membership/page.tsx @@ -0,0 +1,8 @@ +export default function MembershipPage() { + return ( +
+

Membership

+

Member directory and accreditation.

+
+ ); +} diff --git a/DBIS/app/(public)/news/page.tsx b/DBIS/app/(public)/news/page.tsx new file mode 100644 index 0000000..57d0061 --- /dev/null +++ b/DBIS/app/(public)/news/page.tsx @@ -0,0 +1,8 @@ +export default function NewsPage() { + return ( +
+

News

+

News and announcements.

+
+ ); +} diff --git a/DBIS/app/(public)/org-chart/page.tsx b/DBIS/app/(public)/org-chart/page.tsx new file mode 100644 index 0000000..e01d431 --- /dev/null +++ b/DBIS/app/(public)/org-chart/page.tsx @@ -0,0 +1,8 @@ +export default function OrgChartPage() { + return ( +
+

Org Chart

+

Organizational structure.

+
+ ); +} diff --git a/DBIS/app/(public)/programs/page.tsx b/DBIS/app/(public)/programs/page.tsx new file mode 100644 index 0000000..57d0bb0 --- /dev/null +++ b/DBIS/app/(public)/programs/page.tsx @@ -0,0 +1,8 @@ +export default function ProgramsPage() { + return ( +
+

Programs

+

Programs and initiatives.

+
+ ); +} diff --git a/DBIS/app/(public)/publications/page.tsx b/DBIS/app/(public)/publications/page.tsx new file mode 100644 index 0000000..6b329f6 --- /dev/null +++ b/DBIS/app/(public)/publications/page.tsx @@ -0,0 +1,8 @@ +export default function PublicationsPage() { + return ( +
+

Publications

+

Publications and reports.

+
+ ); +} diff --git a/DBIS/app/(public)/regions/page.tsx b/DBIS/app/(public)/regions/page.tsx new file mode 100644 index 0000000..66978cc --- /dev/null +++ b/DBIS/app/(public)/regions/page.tsx @@ -0,0 +1,8 @@ +export default function RegionsPage() { + return ( +
+

Regional Offices

+

Americas, EMEA, APAC delegations and field missions.

+
+ ); +} diff --git a/DBIS/app/(public)/standards/page.tsx b/DBIS/app/(public)/standards/page.tsx new file mode 100644 index 0000000..9327ef0 --- /dev/null +++ b/DBIS/app/(public)/standards/page.tsx @@ -0,0 +1,8 @@ +export default function StandardsPage() { + return ( +
+

Standards

+

Standards and codes.

+
+ ); +} diff --git a/DBIS/app/api/auth/mock-login/route.ts b/DBIS/app/api/auth/mock-login/route.ts new file mode 100644 index 0000000..57f672f --- /dev/null +++ b/DBIS/app/api/auth/mock-login/route.ts @@ -0,0 +1,10 @@ +import { NextRequest, NextResponse } from "next/server"; + +export async function POST(request: NextRequest) { + const form = await request.formData(); + const returnUrl = (form.get("returnUrl") as string) ?? "/dashboard"; + const role = (form.get("role") as string) ?? "member"; + const res = NextResponse.redirect(new URL(returnUrl, request.url)); + res.cookies.set("portal-role", role, { path: "/", httpOnly: true, maxAge: 60 * 60 * 24 }); + return res; +} diff --git a/DBIS/app/apply/page.tsx b/DBIS/app/apply/page.tsx new file mode 100644 index 0000000..7ee15cb --- /dev/null +++ b/DBIS/app/apply/page.tsx @@ -0,0 +1,8 @@ +export default function ApplyPage() { + return ( +
+

Apply

+

Apply for membership or accreditation.

+
+ ); +} diff --git a/DBIS/app/dashboard/layout.tsx b/DBIS/app/dashboard/layout.tsx new file mode 100644 index 0000000..680435b --- /dev/null +++ b/DBIS/app/dashboard/layout.tsx @@ -0,0 +1,17 @@ +import Link from "next/link"; +import type { ReactNode } from "react"; + +export default function DashboardLayout({ children }: { children: ReactNode }) { + return ( +
+ +
{children}
+
+ ); +} diff --git a/DBIS/app/dashboard/page.tsx b/DBIS/app/dashboard/page.tsx new file mode 100644 index 0000000..199cd04 --- /dev/null +++ b/DBIS/app/dashboard/page.tsx @@ -0,0 +1,8 @@ +export default function DashboardPage() { + return ( +
+

Dashboard

+

Role-based dashboard.

+
+ ); +} diff --git a/DBIS/app/dashboard/requests/page.tsx b/DBIS/app/dashboard/requests/page.tsx new file mode 100644 index 0000000..eb94812 --- /dev/null +++ b/DBIS/app/dashboard/requests/page.tsx @@ -0,0 +1,8 @@ +export default function RequestsPage() { + return ( +
+

My requests

+

Track your requests.

+
+ ); +} diff --git a/DBIS/app/dashboard/submissions/page.tsx b/DBIS/app/dashboard/submissions/page.tsx new file mode 100644 index 0000000..dc57c54 --- /dev/null +++ b/DBIS/app/dashboard/submissions/page.tsx @@ -0,0 +1,8 @@ +export default function SubmissionsPage() { + return ( +
+

My submissions

+

Track your submissions and status.

+
+ ); +} diff --git a/DBIS/app/departments/monetary-operations/page.tsx b/DBIS/app/departments/monetary-operations/page.tsx new file mode 100644 index 0000000..b92072a --- /dev/null +++ b/DBIS/app/departments/monetary-operations/page.tsx @@ -0,0 +1,8 @@ +export default function MonetaryOperationsPage() { + return ( +
+

Monetary Operations

+

Digital reserves and monetary operations.

+
+ ); +} diff --git a/DBIS/app/documents/bulletins/page.tsx b/DBIS/app/documents/bulletins/page.tsx new file mode 100644 index 0000000..ce3a40d --- /dev/null +++ b/DBIS/app/documents/bulletins/page.tsx @@ -0,0 +1,8 @@ +export default function BulletinsPage() { + return ( +
+

Financial Bulletins

+

DBIS financial bulletins and reports.

+
+ ); +} diff --git a/DBIS/app/globals.css b/DBIS/app/globals.css new file mode 100644 index 0000000..b5c61c9 --- /dev/null +++ b/DBIS/app/globals.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/DBIS/app/layout.tsx b/DBIS/app/layout.tsx new file mode 100644 index 0000000..b847156 --- /dev/null +++ b/DBIS/app/layout.tsx @@ -0,0 +1,34 @@ +import type { Metadata } from "next"; +import type { ReactNode } from "react"; +import "./globals.css"; +import { Header } from "@/components/layout/Header"; +import { Footer } from "@/components/layout/Footer"; + +export const metadata: Metadata = { + title: "Digital Bank of International Settlements", + description: "Official portal of the Digital Bank of International Settlements", +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: ReactNode; +}>) { + return ( + + + + Skip to main content + +
+
+ {children} +
+