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
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
24
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"seed": "NEXT_PUBLIC_USE_EMULATORS=true npx tsx src/lib/seed.ts"
},
"engines": {
"node": "22.21.x"
"node": "24.x"
},
"dependencies": {
"@silk-hq/components": "^0.10.0",
Expand Down
3 changes: 2 additions & 1 deletion src/app/about/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import Image from 'next/image'
import type { ReactElement } from 'react'
import Footer from '@/components/shared/footer'
import StaticHeader from '@/components/shared/staticHeader'

const About = (): JSX.Element => {
const About = (): ReactElement => {
return (
<div className='min-h-screen flex flex-col max-w-[850pt] w-full mx-auto'>
<StaticHeader />
Expand Down
3 changes: 2 additions & 1 deletion src/app/changelog/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { notFound } from 'next/navigation'
import type { ReactElement } from 'react'
import BlogFooter from '@/components/blog/blogFooter'
import PostFooter from '@/components/blog/postFooter'
import Footer from '@/components/shared/footer'
Expand All @@ -10,7 +11,7 @@ interface PageProps {
}>
}

const ChangelogPost = async ({ params }: PageProps): Promise<JSX.Element> => {
const ChangelogPost = async ({ params }: PageProps): Promise<ReactElement> => {
const { slug } = await params

// For now, redirect to 404 for unknown slugs
Expand Down
3 changes: 2 additions & 1 deletion src/app/changelog/page.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
'use client'

import Image from 'next/image'
import type { ReactElement } from 'react'
import BlogFooter from '@/components/blog/blogFooter'
import PostFooter from '@/components/blog/postFooter'
import Footer from '@/components/shared/footer'
import StaticHeader from '@/components/shared/staticHeader'

const Changelog = (): JSX.Element => {
const Changelog = (): ReactElement => {
return (
<div className='min-h-screen flex flex-col max-w-[850pt] w-full mx-auto'>
<StaticHeader />
Expand Down
4 changes: 2 additions & 2 deletions src/app/emergency/[alertId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

import Link from 'next/link'
import { useParams } from 'next/navigation'
import { useEffect, useState } from 'react'
import { type ReactElement, useEffect, useState } from 'react'
import EmergencyInfo from '@/components/emergency/emergencyInfo'
import Footer from '@/components/shared/footer'
import { useEmergencyUserQuery } from '@/lib/hooks/useEmergencyUserQuery'

const Emergency = (): JSX.Element => {
const Emergency = (): ReactElement => {
const [mounted, setMounted] = useState(false)
const params = useParams()
const alertId = params.alertId as string
Expand Down
3 changes: 2 additions & 1 deletion src/app/emergency/print/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
'use client'

import type { ReactElement } from 'react'
import EmergencyCard from '@/components/home/emergencyCard'
import Logo from '@/components/shared/logo'

export default function Print(): JSX.Element {
export default function Print(): ReactElement {
// TODO(michael) Could improve this by determining the user on the server side
// and redirecting before hitting this page. Similar to how Lee Robinson explains
// it here https://www.youtube.com/watch?v=NSR_Y_rm_zU
Expand Down
4 changes: 3 additions & 1 deletion src/app/head.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import type { ReactElement } from 'react'

const googleRichResultsSchema = {
'@context': 'https://schema.org',
'@type': 'Organization',
url: 'https://hemolog.com',
logo: 'https://hemolog.com/images/hemolog-logo.png',
}

export default function Head(): JSX.Element {
export default function Head(): ReactElement {
return (
<script
type='application/ld+json'
Expand Down
14 changes: 7 additions & 7 deletions src/app/home/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client'

import { usePathname } from 'next/navigation'
import { useEffect } from 'react'
import { type ReactElement, useEffect } from 'react'
import FeedbackPage from '@/components/home/feedbackPage'

import Header from '@/components/home/header'
Expand All @@ -13,7 +13,7 @@ import { withAuth } from '@/components/shared/withAuth'
import { ProtectRoute, useAuth } from '@/lib/auth'
import { track } from '@/lib/helpers'

const Home = (): JSX.Element => {
const Home = (): ReactElement => {
// TODO(michael) add welcome message by checking to see if this is the users
// first time logging in. Still not sure how to accomplish this.
//
Expand Down Expand Up @@ -58,19 +58,19 @@ const Home = (): JSX.Element => {
return (
<ProtectRoute>
<div className='h-full flex flex-col max-w-[80rem] w-full mx-auto'>
<header className='p-6'>
<header className='p-4 sm:p-6'>
<Header version={version} />
</header>
<main className='px-6'>
<main className='px-4 sm:px-6'>
<Tabs initialValue={pathname}>
<TabsItem label='home' value='/home'>
<section className='pt-10'>
<section className='pt-6 sm:pt-10'>
<HomePage />
</section>
</TabsItem>

<TabsItem label='Profile' value='/profile'>
<section className='pt-10'>
<section className='pt-6 sm:pt-10'>
<ProfilePage />
</section>
</TabsItem>
Expand All @@ -82,7 +82,7 @@ const Home = (): JSX.Element => {

{user?.isAdmin && (
<TabsItem label='feedback' value='/feedback'>
<section className='pt-10'>
<section className='pt-6 sm:pt-10'>
<FeedbackPage />
</section>
</TabsItem>
Expand Down
4 changes: 2 additions & 2 deletions src/app/not-found.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
'use client'

import { useRouter } from 'next/navigation'
import { useEffect } from 'react'
import { type ReactElement, useEffect } from 'react'
import LoadingScreen from '@/components/shared/loadingScreen'
import { withAuth } from '@/components/shared/withAuth'
import { useAuth } from '@/lib/auth'

function Custom404(): JSX.Element {
function Custom404(): ReactElement {
const router = useRouter()
const { user, loading } = useAuth()

Expand Down
3 changes: 2 additions & 1 deletion src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import Image from 'next/image'
import Link from 'next/link'
import type { ReactElement } from 'react'
import DescriptionCards from '@/components/landing/descriptionCards'
import Footer from '@/components/shared/footer'
import StaticHeader from '@/components/shared/staticHeader'

export default function Landing(): JSX.Element {
export default function Landing(): ReactElement {
return (
<div className='min-h-screen flex flex-col max-w-[850pt] w-full mx-auto relative'>
<StaticHeader />
Expand Down
4 changes: 2 additions & 2 deletions src/components/blog/blogFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

import Image from 'next/image'
import { useRouter } from 'next/navigation'
import { useEffect, useState } from 'react'
import { type ReactElement, useEffect, useState } from 'react'

import { useAuth } from '@/lib/auth'

export default function BlogFooter(): JSX.Element {
export default function BlogFooter(): ReactElement {
const { user, loading } = useAuth()
const router = useRouter()
const [mounted, setMounted] = useState(false)
Expand Down
2 changes: 1 addition & 1 deletion src/components/emergency/emergencyInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ interface Props {
person: Person
}

export default function EmergencyInfo(props: Props): JSX.Element {
export default function EmergencyInfo(props: Props): React.ReactElement {
const { person } = props
const { user } = useAuth()
const [smallerThanSmall, setSmallerThanSmall] = React.useState(false)
Expand Down
10 changes: 5 additions & 5 deletions src/components/home/Tabs.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from 'react'
import React, { type ReactElement, useState } from 'react'

export interface TabsProps {
initialValue?: string
Expand All @@ -14,7 +14,7 @@ export interface TabsItemProps {
children: React.ReactNode
}

export function TabsItem({ children }: TabsItemProps): JSX.Element {
export function TabsItem({ children }: TabsItemProps): ReactElement {
return <>{children}</>
}

Expand All @@ -24,7 +24,7 @@ export function Tabs({
onChange,
children,
className = '',
}: TabsProps): JSX.Element {
}: TabsProps): ReactElement {
const [activeTab, setActiveTab] = useState<string>(initialValue || '')

const currentValue = value !== undefined ? value : activeTab
Expand Down Expand Up @@ -64,7 +64,7 @@ export function Tabs({
<div
className={`border-b border-gray-200 dark:border-gray-700 ${className}`}
>
<nav className='flex space-x-8'>
<nav className='flex gap-4 sm:gap-8 overflow-x-auto pb-px -mb-px'>
{tabItems.map((item) => {
const isActive = item.value === currentValue

Expand Down Expand Up @@ -103,6 +103,6 @@ export interface TabsContentProps {
export function TabsContent({
children,
className = '',
}: TabsContentProps): JSX.Element {
}: TabsContentProps): ReactElement {
return <div className={`py-6 ${className}`}>{children}</div>
}
3 changes: 2 additions & 1 deletion src/components/home/chart.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { ReactElement } from 'react'
import {
Bar,
BarChart,
Expand All @@ -22,7 +23,7 @@ interface ChartProps {
filterYear: string
}

export default function Chart(props: ChartProps): JSX.Element | null {
export default function Chart(props: ChartProps): ReactElement | null {
const { filterYear } = props
const { data } = useTreatmentsQuery()

Expand Down
4 changes: 2 additions & 2 deletions src/components/home/emergencyCard.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client'
import Link from 'next/link'
import React from 'react'
import React, { type ReactElement } from 'react'
import QRCode from 'react-qr-code'

import { useAuth } from '@/lib/auth'
Expand All @@ -10,7 +10,7 @@ interface Props {
forPrint?: boolean
}

export default function EmergencyCard({ forPrint }: Props): JSX.Element {
export default function EmergencyCard({ forPrint }: Props): ReactElement {
const { user } = useAuth()
const { person } = useUserQuery(user?.uid)

Expand Down
3 changes: 2 additions & 1 deletion src/components/home/feedbackModal.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Sheet } from '@silk-hq/components'
import { useFormik } from 'formik'
import type React from 'react'
import toast from 'react-hot-toast'

import { useAuth } from '@/lib/auth'
Expand All @@ -18,7 +19,7 @@ interface FeedbackModalProps {

export default function FeedbackModal(
props: FeedbackModalProps
): JSX.Element | null {
): React.ReactElement | null {
const { visible, setVisible } = props
const { user } = useAuth()

Expand Down
6 changes: 3 additions & 3 deletions src/components/home/header.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client'

import React from 'react'
import React, { type ReactElement } from 'react'
import Logo from '@/components/shared/logo'
import { useAuth } from '@/lib/auth'
import { useTreatmentSheet } from '@/lib/hooks/useTreatmentSheet'
Expand All @@ -10,7 +10,7 @@ interface Props {
version?: string
}

const Header = (props: Props): JSX.Element | null => {
const Header = (props: Props): ReactElement | null => {
const { version } = props
const { user, signout } = useAuth()
const { data: treatments } = useTreatmentsQuery()
Expand Down Expand Up @@ -51,7 +51,7 @@ const Header = (props: Props): JSX.Element | null => {
<button
type='button'
onClick={handleOpenSheet}
className='bg-green-100 hover:bg-green-200 text-green-800 px-3 py-1.5 rounded text-sm font-medium transition-colors'
className='bg-primary-500 hover:bg-primary-600 text-white px-4 py-2 rounded-lg text-sm font-semibold shadow-sm transition-colors active:scale-[0.98]'
>
New treatment
</button>
Expand Down
15 changes: 9 additions & 6 deletions src/components/home/homePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { IconFilter } from '@tabler/icons-react'
import { getYear } from 'date-fns'
import dynamic from 'next/dynamic'
import type { ReactElement } from 'react'
import React, { useState } from 'react'
import Stats from '@/components/home/stats'
import TreatmentTable from '@/components/home/treatmentTable'
Expand All @@ -13,7 +14,7 @@ const Chart = dynamic(() => import('@/components/home/chart'), {
ssr: false,
})

const HomePage = (): JSX.Element => {
const HomePage = (): ReactElement => {
const [smallerThanSmall, setSmallerThanSmall] = useState(false)

React.useEffect(() => {
Expand Down Expand Up @@ -95,8 +96,8 @@ const HomePage = (): JSX.Element => {
</>
)} */}

<div className='flex justify-between items-center pb-4'>
<h4 className='text-xl font-semibold m-0'>Insights</h4>
<div className='flex flex-col sm:flex-row sm:justify-between sm:items-center gap-3 pb-4'>
<h4 className='text-lg sm:text-xl font-semibold m-0'>Insights</h4>
<div className='flex items-center gap-2'>
<IconFilter size={16} className='text-gray-500' />
<select
Expand All @@ -122,15 +123,17 @@ const HomePage = (): JSX.Element => {
<Stats filterYear={filterYear} />
<div className='h-12' />

<h4 className='text-xl font-semibold'>Annual overview ({filterYear})</h4>
<h4 className='text-lg sm:text-xl font-semibold'>
Annual overview ({filterYear})
</h4>
<p className='text-sm text-gray-600 mt-1'>
Treatments are stacked by type (bleed, preventative, or prophy)
</p>
<Chart filterYear={filterYear} />

<div className='h-12' />
<div className='flex justify-between items-center'>
<h4 className='text-xl font-semibold'>Treatments</h4>
<div className='flex flex-col sm:flex-row sm:justify-between sm:items-center gap-1'>
<h4 className='text-lg sm:text-xl font-semibold'>Treatments</h4>
<span className='text-sm text-gray-600' suppressHydrationWarning>
{smallerThanSmall && 'Swipe →'}
</span>
Expand Down
4 changes: 2 additions & 2 deletions src/components/home/profilePage.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client'

import { useRouter } from 'next/navigation'
import { useCallback, useEffect, useState } from 'react'
import { type ReactElement, useCallback, useEffect, useState } from 'react'
import toast from 'react-hot-toast'
import EmergencyCard from '@/components/home/emergencyCard'
import SettingsForm from '@/components/home/settingsForm'
Expand All @@ -11,7 +11,7 @@ import { generateUniqueString, track } from '@/lib/helpers'
import { useUserMutations } from '@/lib/hooks/useUserMutations'
import { useUserQuery } from '@/lib/hooks/useUserQuery'

const ProfilePage = (): JSX.Element => {
const ProfilePage = (): ReactElement => {
const { user, signout } = useAuth()
const { person } = useUserQuery(user?.uid)
const { updateUser } = useUserMutations()
Expand Down
4 changes: 2 additions & 2 deletions src/components/home/settingsForm.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { useFormik } from 'formik'
import { useState } from 'react'
import { type ReactElement, useState } from 'react'

import { useAuth } from '@/lib/auth'
import { track } from '@/lib/helpers'
import { useUserMutations } from '@/lib/hooks/useUserMutations'
import { useUserQuery } from '@/lib/hooks/useUserQuery'

const SettingsForm = (): JSX.Element => {
const SettingsForm = (): ReactElement => {
const { user } = useAuth()
const { person } = useUserQuery(user?.uid)
const { updateUser } = useUserMutations()
Expand Down
Loading