diff --git a/.dockerignore b/.dockerignore
index d07ece8..9fd447f 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,3 +1,9 @@
- node_modules/
- .env
- .git
\ No newline at end of file
+node_modules
+.next
+out
+build
+.git
+.gitignore
+.env*
+.local
+README.md
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..1a8b547
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,43 @@
+# Stage 1: Base image
+FROM node:22-alpine AS base
+WORKDIR /app
+ENV NEXT_TELEMETRY_DISABLED=1
+ARG NEXT_SERVER_ACTIONS_ENCRYPTION_KEY
+ENV NEXT_SERVER_ACTIONS_ENCRYPTION_KEY=$NEXT_SERVER_ACTIONS_ENCRYPTION_KEY
+
+# Stage 2: Install dependencies
+FROM base AS deps
+# Check if libc6-compat is needed for Alpine
+RUN apk add --no-cache libc6-compat
+COPY package.json package-lock.json ./
+# Clean install exact production and dev dependencies required for the build
+RUN npm ci
+
+# Stage 3: Build the application
+FROM base AS builder
+# Copy node_modules from the deps stage
+COPY --from=deps /app/node_modules ./node_modules
+# Copy all project source code ( Tailwind v4 scans these files )
+COPY . .
+# Execute the production Next.js build
+RUN npm run build
+
+# Stage 4: Production runner
+FROM base AS runner
+ENV NODE_ENV=production
+ENV PORT=3001
+ENV HOSTNAME="0.0.0.0"
+
+# Create a non-root system user for security
+RUN addgroup -g 1001 -S nodejs
+RUN adduser -S nextjs -u 1001
+
+# Copy standalone build assets and public files
+COPY --from=builder /app/public ./public
+COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
+COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
+
+USER nextjs
+EXPOSE 3001
+
+CMD ["node", "server.js"]
diff --git a/docker-compose.yml b/docker-compose.yml
index 2be35d1..df1f331 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -3,9 +3,14 @@ services:
build:
context: .
dockerfile: Dockerfile.dev
+ # dockerfile: Dockerfile
ports:
- "3001:3001"
+ env_file:
+ - .env
environment:
+ - NODE_ENV=development
+ # - NODE_ENV=production
- BE_API_SERVER_HOST=web_api
- BE_API_SERVER_PORT=3005
volumes:
diff --git a/next.config.ts b/next.config.ts
index b339dfc..b4213ed 100644
--- a/next.config.ts
+++ b/next.config.ts
@@ -1,14 +1,7 @@
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
- // async rewrites() {
- // return [
- // {
- // source: '/api-backend/:path*',
- // destination: `http://web_api:3005`, // The external api URL
- // },
- // ];
- // },
+ output: 'standalone',
outputFileTracingIncludes: {
'/api/**/*': ['./node_modules/jose/**/*'],
},
diff --git a/src/app/(informational)/brokers/page.tsx b/src/app/(informational)/brokers/page.tsx
index 19371da..8b40835 100644
--- a/src/app/(informational)/brokers/page.tsx
+++ b/src/app/(informational)/brokers/page.tsx
@@ -1,6 +1,5 @@
import { Schibsted_Grotesk } from 'next/font/google'
import classnames from 'classnames';
-import InlineLink from "@/components/InlineLink";
import QuickAccessLinks, { QuickLink } from '@/components/QuickAccessLinks';
import LandingPageHeader from '@/components/LandingPageHeader';
@@ -8,8 +7,8 @@ const font = Schibsted_Grotesk({ subsets: ['latin'] })
const quickLinks: QuickLink[] = [
{
- display: "Member Login/Registration",
- url: "/"
+ display: "Broker SignIn",
+ url: "/account/signin"
},
{
display: "Link to Thing 1",
@@ -36,17 +35,17 @@ export default function Brokers() {
Partner with Britton Benefit Services to Grow Your Business and Serve Your Clients
- In the ever-changing health care market, finding cost-effective plans to help your clients save money is a serious challenge. At Britton Benefit Services, LLC we have a proven ourselves as leaders in Third-Party Benefits Administration through our performance in finding employers the right self-funded plans that work for them. Whether you need to review a plan document, manage information reports, review provider directories, or you are looking for access to marketing materials, you’ve come to the right place.
+ In the ever-changing health care market, finding cost-effective plans to help your clients save money is a serious challenge. At Britton Benefit Services, LLC we have a proven ourselves as leaders in Third-Party Benefits Administration through our performance in finding employers the right self-funded plans that work for them. Whether you need to review a plan document, manage information reports, review provider directories, or you are looking for access to marketing materials, you've come to the right place.
Broker Services from Britton Benefit Services
-
+
- Discuss your client’s needs and provide additional insight
+ Discuss your client's needs and provide additional insight
Learn more about our company and self-funding
diff --git a/src/app/(informational)/employers/index.tsx b/src/app/(informational)/employers/index.tsx
deleted file mode 100644
index 8d2b34f..0000000
--- a/src/app/(informational)/employers/index.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import LandingPage from '../../../components/LandingPage';
-import InlineLink from "../../../components/InlineLink";
-// import TextImage50 from "../../components/TextImage50-50";
-
-export default function Members() {
- return (
-
-
- At Britton Benefit Services, LLC we are leading the third-party benefits industry by working hard to make employee benefits more affordable for you and your employees. As a third-party administrator, we negotiate with leading PPOs and other organizations to help you find the best program for your employees without sacrificing the bottom line. This creates a major cost savings that you can pass on to your employees.
-
-
- In addition to the generous cost savings for you and your employees, we also offer a wide range of online services to help streamline and automate the benefit process for you and your employees. This means easier access to the benefit information you need and faster action on individual claims. By logging in to any of the services we provide, you can do the following:
-
-
- Look up in-network providers through our list of PPOs
- • File insurance claims and review a claim’s status
- • Research which type of plan is best for you
- • Control your health care costs by selecting a PPO that’s actively competing for your business.
-
-
- Request a free, no-obligation quote today, and learn how our completely customizable benefits solutions can work for you. To learn more about our company and to discover the benefits of third-party benefits administration, review our services or contact us today.
-
-
- )
-}
\ No newline at end of file
diff --git a/src/app/(informational)/employers/page.tsx b/src/app/(informational)/employers/page.tsx
index 387630e..1e1fc48 100644
--- a/src/app/(informational)/employers/page.tsx
+++ b/src/app/(informational)/employers/page.tsx
@@ -1,6 +1,5 @@
import { Schibsted_Grotesk } from 'next/font/google'
import classnames from 'classnames';
-import InlineLink from "@/components/InlineLink";
import QuickAccessLinks, { QuickLink } from '@/components/QuickAccessLinks';
import LandingPageHeader from '@/components/LandingPageHeader';
@@ -8,8 +7,8 @@ const font = Schibsted_Grotesk({ subsets: ['latin'] })
const quickLinks: QuickLink[] = [
{
- display: "Employer Login/Registration",
- url: "/"
+ display: "Employer SignIn",
+ url: "/account/signin"
},
{
display: "Link to Thing 1",
@@ -35,7 +34,7 @@ export default function Employers() {
Making Your Benefits Work for You and Your Employees
@@ -46,9 +45,9 @@ export default function Employers() {
Look up in-network providers through our list of PPOs
- • File insurance claims and review a claim’s status
+ • File insurance claims and review a claim's status
• Research which type of plan is best for you
- • Control your health care costs by selecting a PPO that’s actively competing for your business.
+ • Control your health care costs by selecting a PPO that's actively competing for your business.
Request a free, no-obligation quote today, and learn how our completely customizable benefits solutions can work for you. To learn more about our company and to discover the benefits of third-party benefits administration, review our services or contact us today.
diff --git a/src/app/(informational)/layout.tsx b/src/app/(informational)/layout.tsx
index 0bce36c..40755f4 100644
--- a/src/app/(informational)/layout.tsx
+++ b/src/app/(informational)/layout.tsx
@@ -1,14 +1,9 @@
-import { headers } from "next/headers";
import classnames from 'classnames';
import Navbar from '@/components/Navbar';
import Footer from '@/components/Footer';
export default async function LandingPageLayout({ children }: { children: React.ReactNode }) {
- const headersList = await headers();
- const pathname = headersList.get("x-current-path");
- const landingPageType = pathname?.split('/').pop() || "";
- const headerText = landingPageType.charAt(0).toUpperCase() + landingPageType.slice(1);
return (
<>
@@ -23,30 +18,7 @@ export default async function LandingPageLayout({ children }: { children: React.
- {/*
-
-
-
-
-
-
-
-
- {headerText}
-
-
-
-
-
*/}
-
+
{children}
diff --git a/src/app/(informational)/members/indexold.tsx b/src/app/(informational)/members/indexold.tsx
deleted file mode 100644
index 31d6ffc..0000000
--- a/src/app/(informational)/members/indexold.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import LandingPage from '../../../components/LandingPage';
-import InlineLink from "../../../components/InlineLink";
-// import TextImage50 from "../../components/TextImage50-50";
-
-export default function Members() {
- return (
-
-
- At Britton Benefit Services, LLC we're making employee benefits more affordable. In addition to the cost savings you receive when your employer chooses Britton Benefit Services, LLC we also make sure the important information you need is at your fingertips.
-
-
- That's why our member portal offers you 24/7 access to things like in-network provider lists, claim forms and prescription medication information. Select from any of the links below to get access to the benefit information and forms you need to file a claim, search for a provider or learn more about your benefits plan.
-
-
- At Britton Benefit Services, LLC we're making employee benefits more affordable. In addition to the cost savings you receive when your employer chooses Britton Benefit Services, LLC we also make sure the important information you need is at your fingertips.
-
-
- That's why our member portal offers you 24/7 access to things like in-network provider lists, claim forms and prescription medication information. Select from any of the links below to get access to the benefit information and forms you need to file a claim, search for a provider or learn more about your benefits plan.
-
-
- )
-}
\ No newline at end of file
diff --git a/src/app/(informational)/members/page.tsx b/src/app/(informational)/members/page.tsx
index c767c93..a325b6e 100644
--- a/src/app/(informational)/members/page.tsx
+++ b/src/app/(informational)/members/page.tsx
@@ -1,6 +1,5 @@
import { Schibsted_Grotesk } from 'next/font/google'
import classnames from 'classnames';
-import InlineLink from "@/components/InlineLink";
import QuickAccessLinks, { QuickLink } from '@/components/QuickAccessLinks';
import LandingPageHeader from '@/components/LandingPageHeader';
@@ -9,19 +8,19 @@ const font = Schibsted_Grotesk({ subsets: ['latin'] })
const quickLinks: QuickLink[] = [
{
display: "Member Login/Registration",
- url: "/"
+ url: "/account/signin"
},
{
- display: "Link to Thing 1",
- url: "/"
+ display: "Find a MedCost Medical Provider",
+ url: "http://medcost.com/"
},
{
- display: "Link to Thing 2",
- url: "/"
+ display: "Find a Cigna Medical Provider",
+ url: "http://cigna.com/"
},
{
- display: "Link to another Thing",
- url: "/"
+ display: "Obtain Rx Information",
+ url: "https://www.fairosrx.com/"
}
]
@@ -36,20 +35,20 @@ export default function Members() {
Member Tagline will go here when we come up with the wording
- At Britton Benefit Services, LLC we're making employee benefits more affordable. In addition to the cost savings you receive when your employer chooses Britton Benefit Services, LLC we also make sure the important information you need is at your fingertips.
+ At Britton Benefit Services, LLC we're making employee benefits more affordable. In addition to the cost savings you receive when your employer chooses Britton Benefit Services, LLC we also make sure the important information you need is at your fingertips.
- That's why our member portal offers you 24/7 access to things like in-network provider lists, claim forms and prescription medication information. Select from any of the links below to get access to the benefit information and forms you need to file a claim, search for a provider or learn more about your benefits plan.
+ That's why our member portal offers you 24/7 access to things like in-network provider lists, claim forms and prescription medication information. Select from any of the links below to get access to the benefit information and forms you need to file a claim, search for a provider or learn more about your benefits plan.
- At Britton Benefit Services, LLC we're making employee benefits more affordable. In addition to the cost savings you receive when your employer chooses Britton Benefit Services, LLC we also make sure the important information you need is at your fingertips.
+ At Britton Benefit Services, LLC we're making employee benefits more affordable. In addition to the cost savings you receive when your employer chooses Britton Benefit Services, LLC we also make sure the important information you need is at your fingertips.
- That's why our member portal offers you 24/7 access to things like in-network provider lists, claim forms and prescription medication information. Select from any of the links below to get access to the benefit information and forms you need to file a claim, search for a provider or learn more about your benefits plan.
+ That's why our member portal offers you 24/7 access to things like in-network provider lists, claim forms and prescription medication information. Select from any of the links below to get access to the benefit information and forms you need to file a claim, search for a provider or learn more about your benefits plan.
diff --git a/src/app/(informational)/providers/page.tsx b/src/app/(informational)/providers/page.tsx
index 1f1f696..8523104 100644
--- a/src/app/(informational)/providers/page.tsx
+++ b/src/app/(informational)/providers/page.tsx
@@ -1,6 +1,5 @@
import { Schibsted_Grotesk } from 'next/font/google'
import classnames from 'classnames';
-import InlineLink from "@/components/InlineLink";
import QuickAccessLinks, { QuickLink } from '@/components/QuickAccessLinks';
import LandingPageHeader from '@/components/LandingPageHeader';
@@ -8,12 +7,12 @@ const font = Schibsted_Grotesk({ subsets: ['latin'] })
const quickLinks: QuickLink[] = [
{
- display: "Member Login/Registration",
- url: "/"
+ display: "Provider SignIn/Registration",
+ url: "/account/signin"
},
{
- display: "Link to Thing 1",
- url: "/"
+ display: "Eligibility & Benefits Lookup",
+ url: "/public/eligibility-lookup"
},
{
display: "Link to Thing 2",
@@ -36,11 +35,11 @@ export default function Providers() {
Easy Access to HIPAA Compliant Patient Information and Much More
- You know that as a provider, you have a responsibility to your patients to respond promptly and accurately. At Britton Benefit Services, LLC it’s our goal to provide you with the prompt response to your inquiry and easy access to the information you need to care for your patients. In addition to 24/7 online support and access to HIPAA compliant patient information, you can find the information you need to verify eligibility, confirm benefits and check claim statuses. Simply select the navigation above to access the forms and information you need.
+ You know that as a provider, you have a responsibility to your patients to respond promptly and accurately. At Britton Benefit Services, LLC it's our goal to provide you with the prompt response to your inquiry and easy access to the information you need to care for your patients. In addition to 24/7 online support and access to HIPAA compliant patient information, you can find the information you need to verify eligibility, confirm benefits and check claim statuses. Simply select the navigation above to access the forms and information you need.
diff --git a/src/app/account/forgot-password/page.tsx b/src/app/account/forgot-password/page.tsx
new file mode 100644
index 0000000..cef7b42
--- /dev/null
+++ b/src/app/account/forgot-password/page.tsx
@@ -0,0 +1,81 @@
+// /app/login/page.tsx
+'use test' // Marks this component as a client component
+'use client'
+
+import classnames from 'classnames';
+
+import { useEffect, useState } from 'react'
+
+import { Schibsted_Grotesk } from 'next/font/google'
+const font = Schibsted_Grotesk({ subsets: ['latin'] })
+
+export default function ForgotPasswordPage() {
+ const [email, setEmail] = useState('');
+ const [message, setMessage] = useState('');
+ const [apiUrl, setapiUrl] = useState("");
+
+ useEffect(() => {
+ fetch("/api/backendApiUrl")
+ .then((res) => res.json())
+ .then((data) => {
+ setapiUrl(data.apiUrl)
+ });
+ }, []);
+
+ const handleSubmit = async (e: React.SubmitEvent) => {
+ e.preventDefault();
+ const res = await fetch(`http://${apiUrl}/forgot_password`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json' ,
+ },
+ body: JSON.stringify({ user: { email } }),
+ });
+
+ const data = await res.json();
+ if (res.ok || data.errors[0] == 'Email not found') {
+ setMessage('If there is an account with this address, a reset link will be sent to your email shortly.');
+ } else {
+ setMessage(data.errors?.join(', ') || 'An error occurred.');
+ }
+ };
+
+
+ return (
+
+
+ Britton Benefits
+
+
+
+ Forgot Password
+
+
+ {message &&
{message}
}
+
+
+ )
+}
diff --git a/src/app/account/layout.tsx b/src/app/account/layout.tsx
index 211bf53..58080c7 100644
--- a/src/app/account/layout.tsx
+++ b/src/app/account/layout.tsx
@@ -1,20 +1,12 @@
"user client"
-import { sideNavItems } from '@/lib/dashboard';
-import { headers } from "next/headers";
-import Script from 'next/script';
-
-import AccountDropdown from '../../components/AccountDropdown';
-import SideNav from "@/components/SideNav";
import Image from 'next/image';
import classnames from 'classnames';
+import Footer from '@/components/Footer';
+import Link from 'next/link';
export default async function DashboardLayout({ children }: { children: React.ReactNode }) {
- const headersList = await headers();
- const pathname = headersList.get("x-current-path");
- const dashboardType = pathname?.split('/').pop() || "";
- const pageNavItems = sideNavItems[dashboardType];
return (
@@ -30,25 +22,28 @@ export default async function DashboardLayout({ children }: { children: React.Re
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec placerat non dolor ut luctus. Suspendisse dictum accumsan dolor. Fusce facilisis ante non dolor cursus, sit amet placerat lectus maximus. Pellentesque rutrum nibh ipsum, quis dignissim massa ornare accumsan. Duis consectetur, mauris sit amet faucibus tempus, neque felis lobortis enim, nec commodo eros neque sed ante. Proin dictum congue risus, ac volutpat neque sagittis vitae. Nam mollis elit ut est hendrerit, at iaculis tellus varius. Proin vitae mi sit amet dolor auctor maximus sit amet in sem. Ut tellus ipsum, mollis sed mi nec, ultrices imperdiet tortor. In sed nisi neque. Donec orci urna, porttitor sit amet auctor non, mattis vitae quam. Donec bibendum est non faucibus vulputate. Quisque sagittis dolor ligula, vitae finibus tortor varius id.
-
-
- Fusce volutpat vitae eros ac ullamcorper. Nulla facilisi. Suspendisse sit amet faucibus orci. Donec blandit mollis placerat. Nullam sed dui turpis. Phasellus laoreet libero non risus ultricies dictum. Pellentesque at bibendum neque. Curabitur eu nisl a massa viverra commodo. Quisque ac arcu vitae mauris dapibus dignissim in porta magna. Etiam feugiat tellus eget enim commodo, nec viverra purus dictum. Curabitur maximus consequat mauris, eu egestas risus tincidunt eget. Donec ipsum est, imperdiet a accumsan in, interdum id tellus. Proin id consequat risus. Donec sit amet augue in lorem venenatis iaculis.
-
-
- Thing 2
-
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec placerat non dolor ut luctus. Suspendisse dictum accumsan dolor. Fusce facilisis ante non dolor cursus, sit amet placerat lectus maximus. Pellentesque rutrum nibh ipsum, quis dignissim massa ornare accumsan. Duis consectetur, mauris sit amet faucibus tempus, neque felis lobortis enim, nec commodo eros neque sed ante. Proin dictum congue risus, ac volutpat neque sagittis vitae. Nam mollis elit ut est hendrerit, at iaculis tellus varius. Proin vitae mi sit amet dolor auctor maximus sit amet in sem. Ut tellus ipsum, mollis sed mi nec, ultrices imperdiet tortor. In sed nisi neque. Donec orci urna, porttitor sit amet auctor non, mattis vitae quam. Donec bibendum est non faucibus vulputate. Quisque sagittis dolor ligula, vitae finibus tortor varius id.
-
-
- Fusce volutpat vitae eros ac ullamcorper. Nulla facilisi. Suspendisse sit amet faucibus orci. Donec blandit mollis placerat. Nullam sed dui turpis. Phasellus laoreet libero non risus ultricies dictum. Pellentesque at bibendum neque. Curabitur eu nisl a massa viverra commodo. Quisque ac arcu vitae mauris dapibus dignissim in porta magna. Etiam feugiat tellus eget enim commodo, nec viverra purus dictum. Curabitur maximus consequat mauris, eu egestas risus tincidunt eget. Donec ipsum est, imperdiet a accumsan in, interdum id tellus. Proin id consequat risus. Donec sit amet augue in lorem venenatis iaculis.
-
-
- Thing 3
-
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec placerat non dolor ut luctus. Suspendisse dictum accumsan dolor. Fusce facilisis ante non dolor cursus, sit amet placerat lectus maximus. Pellentesque rutrum nibh ipsum, quis dignissim massa ornare accumsan. Duis consectetur, mauris sit amet faucibus tempus, neque felis lobortis enim, nec commodo eros neque sed ante. Proin dictum congue risus, ac volutpat neque sagittis vitae. Nam mollis elit ut est hendrerit, at iaculis tellus varius. Proin vitae mi sit amet dolor auctor maximus sit amet in sem. Ut tellus ipsum, mollis sed mi nec, ultrices imperdiet tortor. In sed nisi neque. Donec orci urna, porttitor sit amet auctor non, mattis vitae quam. Donec bibendum est non faucibus vulputate. Quisque sagittis dolor ligula, vitae finibus tortor varius id.
-
-
- Fusce volutpat vitae eros ac ullamcorper. Nulla facilisi. Suspendisse sit amet faucibus orci. Donec blandit mollis placerat. Nullam sed dui turpis. Phasellus laoreet libero non risus ultricies dictum. Pellentesque at bibendum neque. Curabitur eu nisl a massa viverra commodo. Quisque ac arcu vitae mauris dapibus dignissim in porta magna. Etiam feugiat tellus eget enim commodo, nec viverra purus dictum. Curabitur maximus consequat mauris, eu egestas risus tincidunt eget. Donec ipsum est, imperdiet a accumsan in, interdum id tellus. Proin id consequat risus. Donec sit amet augue in lorem venenatis iaculis.
-
-
-
-
-
-
-
-
-
- )
-}
\ No newline at end of file
diff --git a/src/app/dashboard/broker/page.tsx b/src/app/dashboard/broker/page.tsx
new file mode 100644
index 0000000..2d93861
--- /dev/null
+++ b/src/app/dashboard/broker/page.tsx
@@ -0,0 +1,87 @@
+import classnames from 'classnames';
+
+import DashboardHeader from "@/components/DashboardHeader";
+import { cookies } from "next/headers";
+import { JWTPayload, jwtVerify } from "jose";
+import { notFound, redirect } from 'next/navigation';
+import ArrowText from '@/components/ArrowText';
+
+// Ensure your secret key matches exactly what you used to sign the token
+const SECRET_KEY = new TextEncoder().encode(process.env.JWT_SECRET_KEY);
+
+ interface UserJwtPayload extends JWTPayload {
+ user: UserData;
+ }
+
+ interface UserData {
+ id: string;
+ email: string;
+ name: string;
+ role: string;
+ roleId: string;
+ }
+
+export default async function Broker() {
+ const cookieStore = await cookies();
+ const sessionCookie = cookieStore.get("session");
+
+ if (!sessionCookie) {
+ redirect('/account/signin')
+ }
+
+ try {
+ // 2. Extract the raw string token from the cookie object
+ const token = sessionCookie.value;
+
+ // 3. Verify and decode the JWT using jose
+ const { payload } = await jwtVerify(token, SECRET_KEY)
+
+ // 3. Cast the payload to your custom interface
+ const data = payload as UserJwtPayload;
+
+ // const userData = {
+ // name: "Tom McSwain",
+ // role: 'broker',
+ // roleId: '1'
+ // }
+
+ const userData = {
+ role: data.user.role,
+ role_id: data.user.roleId,
+ name: data.user.name
+ }
+
+ if (!data || userData.role !== 'broker') {
+ notFound();
+ }
+
+
+ return (
+
+
+
+
+
+ Generate Temporary Member or Employer ID Cards.
+
+
+ Search Eligibility and Benefits by Member.
+
+
+ Search Coverage by Employer.
+
+
+
+
+ );
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } catch (error: any) {
+ if (error.message === 'NEXT_REDIRECT') throw error;
+
+ if (error.message === 'Unauthenticated') {
+ redirect('/account/signin');
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/app/dashboard/carrier/claims/page.tsx b/src/app/dashboard/carrier/claims/page.tsx
new file mode 100644
index 0000000..bd63b94
--- /dev/null
+++ b/src/app/dashboard/carrier/claims/page.tsx
@@ -0,0 +1,90 @@
+import classnames from 'classnames';
+import { cookies } from "next/headers";
+import { JWTPayload, jwtVerify } from "jose";
+
+import DashboardHeader from "@/components/DashboardHeader";
+import { Schibsted_Grotesk } from 'next/font/google'
+import { notFound, redirect } from 'next/navigation';
+import ClaimsSelector from '@/components/ClaimsSelectorNew';
+
+const font = Schibsted_Grotesk({ subsets: ['latin'] })
+const SECRET_KEY = new TextEncoder().encode(process.env.JWT_SECRET_KEY);
+
+ interface UserJwtPayload extends JWTPayload {
+ user: UserData;
+ }
+
+ interface UserData {
+ id: string;
+ email: string;
+ name: string;
+ role: string;
+ roleId: string;
+ }
+
+export default async function CarrierClaims() {
+ const cookieStore = await cookies();
+ const sessionCookie = cookieStore.get("session");
+
+ if (!sessionCookie) {
+ redirect('/account/signin')
+ }
+
+ try {
+ // 2. Extract the raw string token from the cookie object
+ const token = sessionCookie.value;
+
+ // 3. Verify and decode the JWT using jose
+ const { payload } = await jwtVerify(token, SECRET_KEY)
+
+ // 3. Cast the payload to your custom interface
+ const data = payload as UserJwtPayload;
+
+ // const userData = {
+ // name: "Acentria",
+ // role: 'carrier',
+ // roleId: '1'
+ // }
+
+ const userData = {
+ name: data.user.name,
+ role: data.user.role,
+ roleId: data.user.roleId
+ }
+
+ if (!data || userData.role !== 'carrier') {
+ notFound();
+ }
+
+ return (
+ <>
+
+
+
+
+
+
Claims Search
+
+
+
+
+
+
+
+ >
+ );
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } catch (error: any) {
+ if (error.message === 'NEXT_REDIRECT') throw error;
+
+ if (error.message === 'Unauthenticated') {
+ redirect('/account/signin');
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/app/dashboard/carrier/eligibility/page.tsx b/src/app/dashboard/carrier/eligibility/page.tsx
new file mode 100644
index 0000000..c0eeadb
--- /dev/null
+++ b/src/app/dashboard/carrier/eligibility/page.tsx
@@ -0,0 +1,90 @@
+import classnames from 'classnames';
+import { cookies } from "next/headers";
+import { JWTPayload, jwtVerify } from "jose";
+
+import DashboardHeader from "@/components/DashboardHeader";
+import { Schibsted_Grotesk } from 'next/font/google'
+import { notFound, redirect } from 'next/navigation';
+import EligibilitySelector from '@/components/EligibilitySelector';
+
+const font = Schibsted_Grotesk({ subsets: ['latin'] })
+const SECRET_KEY = new TextEncoder().encode(process.env.JWT_SECRET_KEY);
+
+ interface UserJwtPayload extends JWTPayload {
+ user: UserData;
+ }
+
+ interface UserData {
+ id: string;
+ email: string;
+ name: string;
+ role: string;
+ roleId: string;
+ }
+
+export default async function CarrierEligibility() {
+ const cookieStore = await cookies();
+ const sessionCookie = cookieStore.get("session");
+
+ if (!sessionCookie) {
+ redirect('/account/signin')
+ }
+
+ try {
+ // 2. Extract the raw string token from the cookie object
+ const token = sessionCookie.value;
+
+ // 3. Verify and decode the JWT using jose
+ const { payload } = await jwtVerify(token, SECRET_KEY)
+
+ // 3. Cast the payload to your custom interface
+ const data = payload as UserJwtPayload;
+
+ // const userData = {
+ // name: "Acentria",
+ // role: 'carrier',
+ // roleId: '1'
+ // }
+
+ const userData = {
+ name: data.user.name,
+ role: data.user.role,
+ roleId: data.user.roleId
+ }
+
+ if (!data || userData.role !== 'carrier') {
+ notFound();
+ }
+
+ return (
+ <>
+
+
+
+
+
+
Eligibility Search
+
+
+
+
+
+
+
+ >
+ );
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } catch (error: any) {
+ if (error.message === 'NEXT_REDIRECT') throw error;
+
+ if (error.message === 'Unauthenticated') {
+ redirect('/account/signin');
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/app/dashboard/carrier/employer-coverage/page.tsx b/src/app/dashboard/carrier/employer-coverage/page.tsx
new file mode 100644
index 0000000..6ebe404
--- /dev/null
+++ b/src/app/dashboard/carrier/employer-coverage/page.tsx
@@ -0,0 +1,89 @@
+import classnames from 'classnames';
+import { cookies } from "next/headers";
+import { JWTPayload, jwtVerify } from "jose";
+
+import DashboardHeader from "@/components/DashboardHeader";
+import { Schibsted_Grotesk } from 'next/font/google'
+import { notFound, redirect } from 'next/navigation';
+import CoverageSelector from '@/components/CoverageSelector';
+
+const font = Schibsted_Grotesk({ subsets: ['latin'] })
+const SECRET_KEY = new TextEncoder().encode(process.env.JWT_SECRET_KEY);
+
+ interface UserJwtPayload extends JWTPayload {
+ user: UserData;
+ }
+
+ interface UserData {
+ id: string;
+ email: string;
+ name: string;
+ role: string;
+ roleId: string;
+ }
+
+export default async function CarrierEmployerCoverage() {
+ const cookieStore = await cookies();
+ const sessionCookie = cookieStore.get("session");
+
+ if (!sessionCookie) {
+ redirect('/account/signin')
+ }
+
+ try {
+ // 2. Extract the raw string token from the cookie object
+ const token = sessionCookie.value;
+
+ // 3. Verify and decode the JWT using jose
+ const { payload } = await jwtVerify(token, SECRET_KEY)
+
+ // 3. Cast the payload to your custom interface
+ const data = payload as UserJwtPayload;
+
+ // const userData = {
+ // name: "Acentria",
+ // role: 'carrier',
+ // roleId: '1'
+ // }
+
+ const userData = {
+ name: data.user.name,
+ role: data.user.role,
+ roleId: data.user.roleId
+ }
+
+ if (!data || userData.role !== 'carrier') {
+ notFound();
+ }
+
+ return (
+ <>
+
+
+
+
+
+
Employer Coverage Search
+
+
+
+
+
+
+
+ >
+ );
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } catch (error: any) {
+ if (error.message === 'NEXT_REDIRECT') throw error;
+
+ if (error.message === 'Unauthenticated') {
+ redirect('/account/signin');
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/app/dashboard/carrier/id-cards/page.tsx b/src/app/dashboard/carrier/id-cards/page.tsx
new file mode 100644
index 0000000..85164a9
--- /dev/null
+++ b/src/app/dashboard/carrier/id-cards/page.tsx
@@ -0,0 +1,90 @@
+import classnames from 'classnames';
+import { cookies } from "next/headers";
+import { JWTPayload, jwtVerify } from "jose";
+
+import DashboardHeader from "@/components/DashboardHeader";
+import { Schibsted_Grotesk } from 'next/font/google'
+import { notFound, redirect } from 'next/navigation';
+import IdCardSelector from '@/components/IdCardSelector';
+
+const font = Schibsted_Grotesk({ subsets: ['latin'] })
+const SECRET_KEY = new TextEncoder().encode(process.env.JWT_SECRET_KEY);
+
+interface UserJwtPayload extends JWTPayload {
+ user: UserData;
+}
+
+interface UserData {
+ id: string;
+ email: string;
+ name: string;
+ role: string;
+ roleId: string;
+}
+
+export default async function CarrierIdCards() {
+ const cookieStore = await cookies();
+ const sessionCookie = cookieStore.get("session");
+
+ if (!sessionCookie) {
+ redirect('/account/signin')
+ }
+
+ try {
+ // 2. Extract the raw string token from the cookie object
+ const token = sessionCookie.value;
+
+ // 3. Verify and decode the JWT using jose
+ const { payload } = await jwtVerify(token, SECRET_KEY)
+
+ // 3. Cast the payload to your custom interface
+ const data = payload as UserJwtPayload;
+
+ // const userData = {
+ // name: "Acentria",
+ // role: 'carrier',
+ // roleId: '1'
+ // }
+
+ const userData = {
+ name: data.user.name,
+ role: data.user.role,
+ roleId: data.user.roleId
+ }
+
+ if (!data || userData.role !== 'carrier') {
+ notFound();
+ }
+
+ return (
+ <>
+
+
+
+
+
+
ID Card Search
+
+
+
+
+
+
+
+ >
+ );
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } catch (error: any) {
+ if (error.message === 'NEXT_REDIRECT') throw error;
+
+ if (error.message === 'Unauthenticated') {
+ redirect('/account/signin');
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/app/dashboard/carrier/page.tsx b/src/app/dashboard/carrier/page.tsx
new file mode 100644
index 0000000..212a09f
--- /dev/null
+++ b/src/app/dashboard/carrier/page.tsx
@@ -0,0 +1,94 @@
+import classnames from 'classnames';
+
+import DashboardHeader from "@/components/DashboardHeader";
+import { cookies } from "next/headers";
+import { JWTPayload, jwtVerify } from "jose";
+import { notFound, redirect } from 'next/navigation';
+import ArrowText from '@/components/ArrowText';
+
+// Ensure your secret key matches exactly what you used to sign the token
+const SECRET_KEY = new TextEncoder().encode(process.env.JWT_SECRET_KEY);
+
+ interface UserJwtPayload extends JWTPayload {
+ user: UserData;
+ }
+
+ interface UserData {
+ id: string;
+ email: string;
+ name: string;
+ role: string;
+ roleId: string;
+ }
+
+export default async function Carrier() {
+ const cookieStore = await cookies();
+ const sessionCookie = cookieStore.get("session"); // Replace with your cookie name
+
+ if (!sessionCookie) {
+ redirect('/account/signin')
+ }
+
+ try {
+ // 2. Extract the raw string token from the cookie object
+ const token = sessionCookie.value;
+
+ // 3. Verify and decode the JWT using jose
+ const { payload } = await jwtVerify(token, SECRET_KEY)
+
+ // 3. Cast the payload to your custom interface
+ const data = payload as UserJwtPayload;
+
+ // const userData = {
+ // name: "Acentria",
+ // role: 'carrier',
+ // roleId: '1'
+ // }
+
+ const userData = {
+ name: data.user.name,
+ role: data.user.role,
+ roleId: data.user.roleId
+ }
+
+ if (!data || userData.role !== 'carrier') {
+ notFound();
+ }
+
+ return (
+
+
+
+
+
+ Generate Temporary Member or Employer ID Cards.
+
+
+ Search Claims by Member.
+
+
+ Search Eligibility and Benefits by Member.
+
+
+ Search Coverage by Employer.
+
+
;
-// }
}
\ No newline at end of file
diff --git a/src/app/dashboard/provider/claim-search/page.tsx b/src/app/dashboard/provider/claim-search/page.tsx
new file mode 100644
index 0000000..f478285
--- /dev/null
+++ b/src/app/dashboard/provider/claim-search/page.tsx
@@ -0,0 +1,86 @@
+import classnames from 'classnames';
+import { cookies } from "next/headers";
+import { JWTPayload, jwtVerify } from "jose";
+
+import DashboardHeader from "@/components/DashboardHeader";
+import { Schibsted_Grotesk } from 'next/font/google'
+import { notFound, redirect } from 'next/navigation';
+import ProviderClaimSearch from '@/components/ProviderClaimSearch';
+
+const font = Schibsted_Grotesk({ subsets: ['latin'] })
+const SECRET_KEY = new TextEncoder().encode(process.env.JWT_SECRET_KEY);
+
+ interface UserJwtPayload extends JWTPayload {
+ user: UserData;
+ }
+
+ interface UserData {
+ id: string;
+ email: string;
+ name: string;
+ role: string;
+ roleId: string;
+ }
+
+export default async function ClaimSearch() {
+ const cookieStore = await cookies();
+ const sessionCookie = cookieStore.get("session");
+
+ if (!sessionCookie) {
+ redirect('/account/signin')
+ }
+
+ try {
+ // 2. Extract the raw string token from the cookie object
+ const token = sessionCookie.value;
+
+ // 3. Verify and decode the JWT using jose
+ const { payload } = await jwtVerify(token, SECRET_KEY)
+
+ // 3. Cast the payload to your custom interface
+ const data = payload as UserJwtPayload;
+
+ // const userData = {
+ // name: "Kenneth Johnson",
+ // role: 'provider',
+ // roleId: '1457336760'
+ // }
+
+ const userData = {
+ name: data.user.name,
+ role: data.user.role,
+ roleId: data.user.roleId
+ }
+
+ if (!data || userData.role !== 'provider') {
+ notFound();
+ }
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } catch (error: any) {
+ if (error.message === 'NEXT_REDIRECT') throw error;
+
+ if (error.message === 'Unauthenticated') {
+ redirect('/account/signin');
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/app/dashboard/provider/eligibility-lookup/page.tsx b/src/app/dashboard/provider/eligibility-lookup/page.tsx
new file mode 100644
index 0000000..f904bff
--- /dev/null
+++ b/src/app/dashboard/provider/eligibility-lookup/page.tsx
@@ -0,0 +1,85 @@
+import classnames from 'classnames';
+import { cookies } from "next/headers";
+import { JWTPayload, jwtVerify } from "jose";
+
+import DashboardHeader from "@/components/DashboardHeader";
+import { Schibsted_Grotesk } from 'next/font/google'
+import EligibilitySearch from '@/components/EligibilitySearch';
+import { notFound, redirect } from 'next/navigation';
+
+const font = Schibsted_Grotesk({ subsets: ['latin'] })
+const SECRET_KEY = new TextEncoder().encode(process.env.JWT_SECRET_KEY);
+
+ interface UserJwtPayload extends JWTPayload {
+ user: UserData;
+ }
+
+ interface UserData {
+ id: string;
+ email: string;
+ name: string;
+ role: string;
+ roleId: string;
+ }
+
+export default async function ProviderEligibilityLookup() {
+ const cookieStore = await cookies();
+ const sessionCookie = cookieStore.get("session"); // Replace with your cookie name
+
+ if (!sessionCookie) {
+ redirect('/account/signin')
+ }
+
+ try {
+ // 2. Extract the raw string token from the cookie object
+ const token = sessionCookie.value;
+
+ // 3. Verify and decode the JWT using jose
+ const { payload } = await jwtVerify(token, SECRET_KEY)
+
+ // 3. Cast the payload to your custom interface
+ const data = payload as UserJwtPayload;
+
+ // const userData = {
+ // name: "Kenneth Johnson",
+ // role: 'provider',
+ // roleId: '1457336760'
+ // }
+
+ const userData = {
+ name: data.user.name,
+ role: data.user.role,
+ roleId: data.user.roleId
+ }
+
+ if (!data || userData.role !== 'provider') {
+ notFound();
+ }
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } catch (error: any) {
+ if (error.message === 'NEXT_REDIRECT') throw error;
+
+ if (error.message === 'Unauthenticated') {
+ redirect('/account/signin');
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/app/dashboard/provider/page.tsx b/src/app/dashboard/provider/page.tsx
new file mode 100644
index 0000000..f9024cc
--- /dev/null
+++ b/src/app/dashboard/provider/page.tsx
@@ -0,0 +1,83 @@
+import classnames from 'classnames';
+
+import DashboardHeader from "@/components/DashboardHeader";
+import { cookies } from "next/headers";
+import { JWTPayload, jwtVerify } from "jose";
+import { notFound, redirect } from 'next/navigation';
+import ArrowText from '@/components/ArrowText';
+
+// Ensure your secret key matches exactly what you used to sign the token
+const SECRET_KEY = new TextEncoder().encode(process.env.JWT_SECRET_KEY);
+
+ interface UserJwtPayload extends JWTPayload {
+ user: UserData;
+ }
+
+ interface UserData {
+ id: string;
+ email: string;
+ name: string;
+ role: string;
+ roleId: string;
+ }
+
+export default async function Provider() {
+ const cookieStore = await cookies();
+ const sessionCookie = cookieStore.get("session"); // Replace with your cookie name
+
+ if (!sessionCookie) {
+ redirect('/account/signin')
+ }
+
+ try {
+ // 2. Extract the raw string token from the cookie object
+ const token = sessionCookie.value;
+
+ // 3. Verify and decode the JWT using jose
+ const { payload } = await jwtVerify(token, SECRET_KEY)
+
+ // 3. Cast the payload to your custom interface
+ const data = payload as UserJwtPayload;
+
+ // const userData = {
+ // name: "Kenneth Johnson",
+ // role: 'provider',
+ // roleId: '1457336760'
+ // }
+
+ const userData = {
+ name: data.user.name,
+ role: data.user.role,
+ roleId: data.user.roleId
+ }
+
+ if (!data || userData.role !== 'provider') {
+ notFound();
+ }
+
+ return (
+
+
+
+
+
+ Search Claims by Member Number.
+
+
+ Search Eligibility and Benefits by Member Number.
+
+
+
+
+ );
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } catch (error: any) {
+ if (error.message === 'NEXT_REDIRECT') throw error;
+
+ if (error.message === 'Unauthenticated') {
+ redirect('/account/signin');
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index fe52d38..cdf4adc 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,8 +1,5 @@
import '../styles/globals.css';
-import type { Metadata } from 'next';
import { Fraunces } from 'next/font/google'
-import Navbar from '../components/Navbar';
-import Footer from '../components/Footer';
import classNames from 'classnames';
const font = Fraunces({ subsets: ['latin'] })
diff --git a/src/app/page.tsx b/src/app/page.tsx
index a081cca..bdbe2c4 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -1,6 +1,5 @@
import InfoCard from '../components/InfoCard';
import Tagline from "../components/Tagline";
-import InlineLink from "../components/InlineLink";
import Navbar from '@/components/Navbar';
import Footer from '@/components/Footer';
@@ -25,7 +24,7 @@ export default async function Home() {
learnMoreUrl="/members"
imageUrl="/images/member-image.jpg"
>
- What we do for members
+ At Britton Benefit Services, LLC we're making employee benefits more affordable. In addition to the cost savings you receive when your employer chooses Britton Benefit Services, LLC we also make sure the important information you need is at your fingertips.
@@ -35,7 +34,7 @@ export default async function Home() {
imageUrl='/images/employer-image.jpg'
invert
>
- What we do for employers
+ At Britton Benefit Services, LLC we are leading the third-party benefits industry by working hard to make employee benefits more affordable for you and your employees. As a third-party administrator, we negotiate with leading PPOs and other organizations to help you find the best program for your employees without sacrificing the bottom line. This creates a major cost savings that you can pass on to your employees.
@@ -44,7 +43,7 @@ export default async function Home() {
learnMoreUrl="/providers"
imageUrl="/images/provider-image.png"
>
- What we do for providers
+ At Britton Benefit Services, LLC it’s our goal to provide you with the prompt response to your inquiry and easy access to the information you need to care for your patients. In addition to 24/7 online support and access to HIPAA compliant patient information, you can find the information you need to verify eligibility, confirm benefits and check claim statuses. Simply select the navigation above to access the forms and information you need.
@@ -54,7 +53,7 @@ export default async function Home() {
imageUrl="/images/broker-image.jpg"
invert
>
- What we do for brokers
+ At Britton Benefit Services, LLC we have a proven ourselves as leaders in Third-Party Benefits Administration through our performance in finding employers the right self-funded plans that work for them. Whether you need to review a plan document, manage information reports, review provider directories, or you are looking for access to marketing materials, you’ve come to the right place.
diff --git a/src/app/public/eligibility-lookup/page.tsx b/src/app/public/eligibility-lookup/page.tsx
new file mode 100644
index 0000000..9488479
--- /dev/null
+++ b/src/app/public/eligibility-lookup/page.tsx
@@ -0,0 +1,27 @@
+import classnames from 'classnames';
+
+import DashboardHeader from "@/components/DashboardHeader";
+import { Schibsted_Grotesk } from 'next/font/google'
+import EligibilitySearch from '@/components/EligibilitySearch';
+
+const font = Schibsted_Grotesk({ subsets: ['latin'] })
+
+export default async function EmployerIdCards() {
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+}
\ No newline at end of file
diff --git a/src/app/public/layout.tsx b/src/app/public/layout.tsx
new file mode 100644
index 0000000..76e9070
--- /dev/null
+++ b/src/app/public/layout.tsx
@@ -0,0 +1,49 @@
+"user client"
+
+import Image from 'next/image';
+import classnames from 'classnames';
+import Footer from '@/components/Footer';
+import Link from 'next/link';
+
+
+export default async function PublicLayout({ children }: { children: React.ReactNode }) {
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {children}
+
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/components/AccountDropdown.tsx b/src/components/AccountDropdown.tsx
index 2fda480..7f4c8a0 100644
--- a/src/components/AccountDropdown.tsx
+++ b/src/components/AccountDropdown.tsx
@@ -4,9 +4,10 @@ import React, { useState } from 'react'
import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/react'
import { CgProfile } from "react-icons/cg";
import classnames from 'classnames';
+import SignOutButton from './SignOut';
interface DropdownProps {
- userRole: "member" | "employer";
+ userRole: string;
}
const AccountDropdown: React.FC = ({userRole}) => {
@@ -28,14 +29,12 @@ const AccountDropdown: React.FC = ({userRole}) => {
diff --git a/src/components/ArrowText.tsx b/src/components/ArrowText.tsx
new file mode 100644
index 0000000..c6fec7f
--- /dev/null
+++ b/src/components/ArrowText.tsx
@@ -0,0 +1,26 @@
+"use client";
+
+import React from 'react'
+import DynamicIcon from './DynamicIcon';
+
+
+
+type ArrowTextProps = {
+ children: React.ReactNode;
+};
+
+// interface ArrowTextProps {
+// iconName: string;
+// };
+
+const ArrowText: React.FC = ({ children }) => {
+
+ return (
+