gui: work in progress

This commit is contained in:
Carl-Gerhard Lindesvärd
2023-10-17 21:47:37 +02:00
parent b9fe6127ff
commit 206ae54dea
53 changed files with 2632 additions and 88 deletions

View File

@@ -1,6 +1,8 @@
import { type Session } from "next-auth";
import { SessionProvider } from "next-auth/react";
import { type AppType } from "next/app";
import store from "@/redux";
import { Provider as ReduxProvider } from "react-redux";
import { api } from "@/utils/api";
@@ -12,7 +14,9 @@ const MyApp: AppType<{ session: Session | null }> = ({
}) => {
return (
<SessionProvider session={session}>
<Component {...pageProps} />
<ReduxProvider store={store}>
<Component {...pageProps} />
</ReduxProvider>
</SessionProvider>
);
};

View File

@@ -1,7 +1,7 @@
import { validateSdkRequest } from '@/server/auth'
import { db } from '@/server/db'
import { createError, handleError } from '@/server/exceptions'
import { EventPayload } from '@mixan/types'
import { type EventPayload } from '@mixan/types'
import type { NextApiRequest, NextApiResponse } from 'next'
interface Request extends NextApiRequest {

View File

@@ -1,8 +1,7 @@
import { validateSdkRequest } from "@/server/auth";
import { db } from "@/server/db";
import { createError, handleError } from "@/server/exceptions";
import { tickProfileProperty } from "@/services/profile.service";
import { ProfileIncrementPayload, ProfilePayload } from "@mixan/types";
import { type ProfileIncrementPayload } from "@mixan/types";
import type { NextApiRequest, NextApiResponse } from "next";
interface Request extends NextApiRequest {

View File

@@ -1,8 +1,7 @@
import { validateSdkRequest } from "@/server/auth";
import { db } from "@/server/db";
import { createError, handleError } from "@/server/exceptions";
import { tickProfileProperty } from "@/services/profile.service";
import { ProfileIncrementPayload, ProfilePayload } from "@mixan/types";
import { type ProfileIncrementPayload } from "@mixan/types";
import type { NextApiRequest, NextApiResponse } from "next";
interface Request extends NextApiRequest {

View File

@@ -2,7 +2,7 @@ import { validateSdkRequest } from "@/server/auth";
import { db } from "@/server/db";
import { createError, handleError } from "@/server/exceptions";
import { getProfile } from "@/services/profile.service";
import { ProfilePayload } from "@mixan/types";
import { type ProfilePayload } from "@mixan/types";
import type { NextApiRequest, NextApiResponse } from "next";
interface Request extends NextApiRequest {
@@ -34,9 +34,9 @@ export default async function handler(req: Request, res: NextApiResponse) {
avatar: body.avatar,
properties: {
...(typeof profile.properties === "object"
? profile.properties || {}
? profile.properties ?? {}
: {}),
...(body.properties || {}),
...(body.properties ?? {}),
},
},
});

View File

@@ -33,7 +33,7 @@ export default async function handler(
last_name: null,
avatar: null,
properties: {
...(properties || {}),
...(properties ?? {}),
},
project_id: projectId,
},

View File

@@ -2,9 +2,9 @@ import { db } from "@/server/db";
import { handleError } from "@/server/exceptions";
import { hashPassword } from "@/services/hash.service";
import { randomUUID } from "crypto";
import { NextApiRequest, NextApiResponse } from "next";
import { type NextApiRequest, type NextApiResponse } from "next";
export default async function (req: NextApiRequest, res: NextApiResponse) {
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
const counts = await db.$transaction([
db.organization.count(),

View File

@@ -1,11 +1,21 @@
import { signIn, signOut, useSession } from "next-auth/react";
import Head from "next/head";
import Link from "next/link";
import { api } from "@/utils/api";
import { useEffect, useState } from "react";
import { ReportSidebar } from "@/components/report/sidebar/ReportSidebar";
import { ReportLineChart } from "@/components/report/chart/ReportLineChart";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { Combobox } from "@/components/ui/combobox";
import { useDispatch, useSelector } from "@/redux";
import { changeInterval } from "@/components/report/reportSlice";
import { type IInterval } from "@/types";
export default function Home() {
const hello = api.example.hello.useQuery({ text: "from tRPC" });
const dispatch = useDispatch();
const interval = useSelector((state) => state.report.interval);
const events = useSelector((state) => state.report.events);
const breakdowns = useSelector((state) => state.report.breakdowns);
const startDate = useSelector((state) => state.report.startDate);
const endDate = useSelector((state) => state.report.endDate);
return (
<>
@@ -14,67 +24,56 @@ export default function Home() {
<meta name="description" content="Generated by create-t3-app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className=" flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c]">
<div className="container flex flex-col items-center justify-center gap-12 px-4 py-16 ">
<h1 className="text-5xl font-extrabold tracking-tight text-white sm:text-[5rem]">
Create <span className="text-[hsl(280,100%,70%)]">T3</span> App
</h1>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 md:gap-8">
<Link
className="flex max-w-xs flex-col gap-4 rounded-xl bg-white/10 p-4 text-white hover:bg-white/20"
href="https://create.t3.gg/en/usage/first-steps"
target="_blank"
>
<h3 className="text-2xl font-bold">First Steps </h3>
<div className="text-lg">
Just the basics - Everything you need to know to set up your
database and authentication.
</div>
</Link>
<Link
className="flex max-w-xs flex-col gap-4 rounded-xl bg-white/10 p-4 text-white hover:bg-white/20"
href="https://create.t3.gg/en/introduction"
target="_blank"
>
<h3 className="text-2xl font-bold">Documentation </h3>
<div className="text-lg">
Learn more about Create T3 App, the libraries it uses, and how
to deploy it.
</div>
</Link>
</div>
<div className="flex flex-col items-center gap-2">
<p className="text-2xl text-white">
{hello.data ? hello.data.greeting : "Loading tRPC query..."}
</p>
<AuthShowcase />
<main className="grid min-h-screen grid-cols-[400px_minmax(0,1fr)] divide-x">
<div>
<ReportSidebar />
</div>
<div className="flex flex-col gap-4 p-4">
<div className="flex gap-4">
<RadioGroup>
<RadioGroupItem>7 days</RadioGroupItem>
<RadioGroupItem>14 days</RadioGroupItem>
<RadioGroupItem>1 month</RadioGroupItem>
<RadioGroupItem>3 month</RadioGroupItem>
<RadioGroupItem>6 month</RadioGroupItem>
<RadioGroupItem>1 year</RadioGroupItem>
</RadioGroup>
<div className="w-full max-w-[200px]">
<Combobox
placeholder="Interval"
onChange={(value) => {
dispatch(changeInterval(value as IInterval));
}}
value={interval}
items={[
{
label: "Hour",
value: "hour",
},
{
label: "Day",
value: "day",
},
{
label: "Month",
value: "month",
},
]}
></Combobox>
</div>
</div>
{startDate && endDate && (
<ReportLineChart
startDate={startDate}
endDate={endDate}
events={events}
breakdowns={breakdowns}
interval={interval}
/>
)}
</div>
</main>
</>
);
}
function AuthShowcase() {
const { data: sessionData } = useSession();
const { data: secretMessage } = api.example.getSecretMessage.useQuery(
undefined, // no input
{ enabled: sessionData?.user !== undefined }
);
return (
<div className="flex flex-col items-center justify-center gap-4">
<p className="text-center text-2xl text-white">
{sessionData && <span>Logged in as {sessionData.user?.name}</span>}
{secretMessage && <span> - {secretMessage}</span>}
</p>
<button
className="rounded-full bg-white/10 px-10 py-3 font-semibold text-white no-underline transition hover:bg-white/20"
onClick={sessionData ? () => void signOut() : () => void signIn()}
>
{sessionData ? "Sign out" : "Sign in"}
</button>
</div>
);
}