-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Migrate to next app router * Run next/font codemod * Add month navigation with own pages to persist route * Added user avatar handling, update user salary with dialog and many other UI changes * Add work day detail editing * Add yearly economic overview
- Loading branch information
1 parent
2e822b5
commit 5ebd581
Showing
188 changed files
with
5,605 additions
and
8,120 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"$schema": "https://json.schemastore.org/eslintrc", | ||
"root": true, | ||
"extends": [ | ||
"next/core-web-vitals", | ||
"prettier", | ||
"plugin:tailwindcss/recommended" | ||
], | ||
"plugins": ["tailwindcss"], | ||
"rules": { | ||
"tailwindcss/no-custom-classname": "off", | ||
"tailwindcss/classnames-order": "error" | ||
}, | ||
"settings": { | ||
"tailwindcss": { | ||
"callees": ["cn"] | ||
}, | ||
"next": { | ||
"rootDir": ["apps/*/"] | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,9 @@ | ||
.next | ||
.vercel | ||
.vercel | ||
cache | ||
.cache | ||
package.json | ||
package-lock.json | ||
public | ||
CHANGELOG.md | ||
.yarn |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,14 @@ | ||
{ | ||
"files.exclude": { | ||
"**/.git": true, | ||
"**/.svn": true, | ||
"**/.hg": true, | ||
"**/CVS": true, | ||
"**/.DS_Store": true, | ||
"**/*.bk": true, | ||
"**/node_modules": true, | ||
"**/target": true | ||
}, | ||
"editor.formatOnSave": true, | ||
"editor.codeActionsOnSave": { | ||
"source.organizeImports": true | ||
}, | ||
"editor.wordWrapColumn": 100, | ||
"javascript.updateImportsOnFileMove.enabled": "always", | ||
"typescript.updateImportsOnFileMove.enabled": "always", | ||
"javascript.preferences.importModuleSpecifier": "non-relative", | ||
"typescript.tsdk": "node_modules/.pnpm/[email protected]/node_modules/typescript/lib", | ||
"typescript.enablePromptUseWorkspaceTsdk": true, | ||
"typescript.suggest.autoImports": true, | ||
"typescript.format.enable": true, | ||
"[typescriptreact]": { | ||
"editor.formatOnSave": true, | ||
"editor.defaultFormatter": "esbenp.prettier-vscode" | ||
"editor.formatOnSave": true | ||
}, | ||
"typescript.tsdk": "node_modules/typescript/lib" | ||
"tailwindCSS.experimental.classRegex": [["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"]] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
interface AuthLayoutProps { | ||
children: React.ReactNode | ||
} | ||
|
||
export default function AuthLayout({ children }: AuthLayoutProps) { | ||
return <div className="min-h-screen">{children}</div> | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { LoginButton } from "@/components/auth/login-button"; | ||
import { Icons } from "@/components/icons"; | ||
import { Metadata } from "next"; | ||
|
||
export const metadata: Metadata = { | ||
title: "Login", | ||
description: "Login to your account" | ||
}; | ||
|
||
export default function LoginPage() { | ||
return ( | ||
<div className="container flex h-screen w-screen flex-col items-center justify-center"> | ||
<div className="mx-auto flex w-full flex-col justify-center space-y-6 sm:w-[350px]"> | ||
<div className="flex flex-col space-y-2 text-center"> | ||
<Icons.Logo className="mx-auto" /> | ||
<h1 className="text-2xl font-semibold tracking-tight">Welcome back</h1> | ||
<p className="mb-8 text-sm text-neutral-500 dark:text-neutral-400"> | ||
Click to login with your Knowit AD account. | ||
</p> | ||
</div> | ||
<div className=""></div> | ||
<LoginButton /> | ||
</div> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { Skeleton } from "@/components/ui/skeleton"; | ||
import { UserAvatar } from "@/components/user/user-avatar"; | ||
import { getCurrentUser } from "@/lib/session"; | ||
import { getUserAvatar } from "@/lib/user"; | ||
|
||
export default async function Avatar() { | ||
const user = await getCurrentUser(); | ||
|
||
if (!user) { | ||
return <div>Not logged in</div>; | ||
} | ||
|
||
const userAvatar = await getUserAvatar(user?.activeDirectoryId); | ||
|
||
return <UserAvatar name={user.name} src={userAvatar} />; | ||
} | ||
|
||
function AvatarSkeleton() { | ||
return <Skeleton className="h-12 w-12 rounded-full p-0"></Skeleton>; | ||
} | ||
|
||
export { AvatarSkeleton }; |
99 changes: 99 additions & 0 deletions
99
app/(dashboard)/dashboard/_components/calendar-month-with-salary.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
import { MonthSelect } from "@/components/calendar/month-select"; | ||
import { Icons } from "@/components/icons"; | ||
import { SalaryDetailsCard } from "@/components/salary/salary-details-card"; | ||
import { buttonVariants } from "@/components/ui/button"; | ||
import { Card } from "@/components/ui/card"; | ||
import { Show } from "@/components/ui/show"; | ||
import { UserEditSalaryDetailsDialog } from "@/components/user/user-edit-salary-details-dialog"; | ||
import { UserEarningsDetails, type CalendarMonth as CalendarMonthType } from "@/types"; | ||
import { Session } from "next-auth"; | ||
import Link from "next/link"; | ||
import { CalendarMonth } from "./calendar-month"; | ||
|
||
export default function CalendarMonthWithSalary({ | ||
user, | ||
calendarMonth, | ||
userEarnings | ||
}: { | ||
user: Session["user"]; | ||
calendarMonth: CalendarMonthType; | ||
userEarnings?: UserEarningsDetails; | ||
}) { | ||
return ( | ||
<div className="flex flex-col gap-12 lg:flex-row"> | ||
<div className="flex max-w-[380px] flex-col gap-3 lg:min-w-[380px]"> | ||
<h2 className="font-bold"> | ||
Salary details for {calendarMonth.month} {calendarMonth.year} | ||
</h2> | ||
<div className="grid grid-cols-2 gap-3"> | ||
<SalaryDetailsCard heading="Work days"> | ||
{userEarnings?.activeCalendarMonthStatistics.workDays.length.toString()} | ||
</SalaryDetailsCard> | ||
<SalaryDetailsCard heading="Work hours"> | ||
{userEarnings?.activeCalendarMonthStatistics.workHours.toString()} | ||
</SalaryDetailsCard> | ||
<SalaryDetailsCard heading="Gross salary"> | ||
{userEarnings?.activeCalendarMonthStatistics.grossFormatted} | ||
</SalaryDetailsCard> | ||
<SalaryDetailsCard heading="Net salary"> | ||
{userEarnings?.activeCalendarMonthStatistics.netFormatted} | ||
</SalaryDetailsCard> | ||
</div> | ||
<Show when={calendarMonth.halfTax}> | ||
<Card className="flex items-center"> | ||
<Card.Content className="flex items-center gap-3 p-4"> | ||
<div className="flex h-6 w-6 min-w-[1.5rem] items-center justify-center rounded-full border border-emerald-500 text-emerald-500"> | ||
<Icons.Check /> | ||
</div> | ||
<span className="text-emerald-500"> | ||
Salary for {calendarMonth.month} paid with{" "} | ||
<span className="underline">half tax</span> at{" "} | ||
{userEarnings?.nextMonthStatistics?.payDay} | ||
</span> | ||
</Card.Content> | ||
</Card> | ||
</Show> | ||
<UserEditSalaryDetailsDialog user={user} /> | ||
</div> | ||
<div className="grow"> | ||
<div className="flex items-start justify-between"> | ||
<div className=""> | ||
<h2 className="text-xs">{calendarMonth.year}</h2> | ||
<MonthSelect | ||
className="max-w-[110px]" | ||
year={calendarMonth.year} | ||
month={calendarMonth.monthNumber} | ||
/> | ||
</div> | ||
<div className="flex items-center gap-2"> | ||
{/* Go to previous month if month.MonthNumber is 0, go to previous year and month 11 */} | ||
<Link | ||
className={buttonVariants({ variant: "outline" })} | ||
href={`/dashboard/year/${ | ||
calendarMonth.monthNumber === 0 ? calendarMonth.year - 1 : calendarMonth.year | ||
}/month/${calendarMonth.monthNumber === 0 ? 11 : calendarMonth.monthNumber - 1}`} | ||
> | ||
<span className="sr-only">Forrige måned</span> | ||
<Icons.ChevronLeft /> | ||
</Link> | ||
{/* Go to current month */} | ||
<Link className={buttonVariants({ variant: "outline" })} href="/dashboard"> | ||
<span className="">I dag</span> | ||
</Link> | ||
{/* Go to next month if month.MonthNumber is 11, go to next year and month 0 */} | ||
<Link | ||
className={buttonVariants({ variant: "outline" })} | ||
href={`/dashboard/year/${ | ||
calendarMonth.monthNumber === 11 ? calendarMonth.year + 1 : calendarMonth.year | ||
}/month/${calendarMonth.monthNumber === 11 ? 0 : calendarMonth.monthNumber + 1}`} | ||
> | ||
<span className="sr-only">Neste måned</span> | ||
<Icons.ChevronRight /> | ||
</Link> | ||
</div> | ||
</div> | ||
<CalendarMonth month={calendarMonth} workDayDetails={userEarnings?.workDayDetails} /> | ||
</div> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import { CalendarDay } from "@/components/calendar/calendar-day"; | ||
import { Show } from "@/components/ui/show"; | ||
import { UserEditWorkDayDetailDialog } from "@/components/user/user-edit-work-day-detail-dialog"; | ||
import { getRequestDateNow } from "@/lib/date"; | ||
import { cn } from "@/lib/utils"; | ||
import { CalendarMonth, UserWorkDayDetail } from "@/types"; | ||
import { getCalendarMonthEntries } from "@/utils/calendar-utils"; | ||
import * as React from "react"; | ||
|
||
const CalendarMonth: React.FC<{ | ||
month: CalendarMonth; | ||
big?: boolean; | ||
workDayDetails?: UserWorkDayDetail[]; | ||
}> = ({ month, big = false, workDayDetails = [], ...other }) => { | ||
const currentDate = getRequestDateNow(); | ||
const showWeeks = true && !big; | ||
const holidayInfos = month.days.filter(day => day.holidayInformation); | ||
|
||
const calendarEntries = getCalendarMonthEntries(month, currentDate, showWeeks, workDayDetails); | ||
|
||
return ( | ||
<div className="min-h-[240px] lg:min-h-[410px]"> | ||
<div className="flex items-center justify-center gap-3"> | ||
<div className="flex items-center justify-center gap-1"> | ||
<div className="h-2 w-2 rounded-full border-neutral-50 bg-neutral-50" /> | ||
<span className="text-xs">Off work</span> | ||
</div> | ||
<div className="flex items-center justify-center gap-1"> | ||
<div className="h-2 w-2 rounded-full border-emerald-500 bg-emerald-500" /> | ||
<span className="text-xs">Work</span> | ||
</div> | ||
<div className="flex items-center justify-center gap-1"> | ||
<div className="h-2 w-2 rounded-full border-red-500 bg-red-500" /> | ||
<span className="text-xs">Non commissioned</span> | ||
</div> | ||
</div> | ||
<div | ||
className={cn("grid", { | ||
"grid-cols-8": showWeeks, | ||
"grid-cols-7": !showWeeks | ||
})} | ||
> | ||
{calendarEntries.map((calendarDay, index) => { | ||
switch (calendarDay.type) { | ||
case "day": | ||
return ( | ||
<UserEditWorkDayDetailDialog | ||
key={`calendar-day-${index}`} | ||
calendarDay={calendarDay} | ||
big={big} | ||
holidayInfos={holidayInfos} | ||
/> | ||
); | ||
default: | ||
return ( | ||
<CalendarDay | ||
key={`calendar-day-${index}`} | ||
calendarDay={calendarDay} | ||
big={big} | ||
holidayInfos={holidayInfos} | ||
/> | ||
); | ||
} | ||
})} | ||
</div> | ||
<Show when={holidayInfos.length > 0}> | ||
<div className="mt-4"> | ||
{holidayInfos.map((day, index) => ( | ||
<div | ||
key={`holiday-info-${index}`} | ||
className="mr-1 inline-flex text-xs leading-tight dark:text-zinc-400" | ||
> | ||
{`${day.date.getDate()}.${day.date.getMonth() + 1}: ${day.holidayInformation?.name}${ | ||
holidayInfos.length === index + 1 ? "" : "," | ||
}`} | ||
</div> | ||
))} | ||
</div> | ||
</Show> | ||
</div> | ||
); | ||
}; | ||
|
||
export { CalendarMonth }; |
Oops, something went wrong.