Improve dashboard layout

This commit is contained in:
Fergal Moran
2024-01-08 16:17:09 +00:00
parent c52df88f10
commit bcabbd4dba
6 changed files with 104 additions and 79 deletions

View File

@@ -2,7 +2,7 @@ import React from 'react';
import { api } from '@/trpc/server';
import ChildrenFilter from '@/components/children/children-filter';
import dynamic from 'next/dynamic';
import ChildModel from '@/lib/models/child';
import { MapViewTypeSelector } from '@/components/maps/map-viewtype-selector';
const Dashboard = async () => {
const kids = await api.child.mine.query();
@@ -10,10 +10,11 @@ const Dashboard = async () => {
ssr: false,
});
return <div>
<div className="z-10">
<div className="flex flex-row justify-between">
<ChildrenFilter kids={kids} />
<MapViewTypeSelector />
</div>
<div className="z-0 mt-4">
<div className="mt-4">
<Map kids={kids} />
</div>
</div>;

View File

@@ -1,24 +1,25 @@
import "@/styles/globals.css";
import '@/styles/globals.css';
import { Inter } from "next/font/google";
import { cookies } from "next/headers";
import { ABeeZee as TheFont } from 'next/font/google';
import { cookies } from 'next/headers';
import { TRPCReactProvider } from "@/trpc/react";
import { ThemeProvider } from "@/components/providers/theme-provider";
import { type Metadata } from "next";
import NextAuthProvider from "@/lib/services/auth/provider";
import { TRPCReactProvider } from '@/trpc/react';
import { ThemeProvider } from '@/components/providers/theme-provider';
import { type Metadata } from 'next';
import NextAuthProvider from '@/lib/services/auth/provider';
const inter = Inter({
subsets: ["latin"],
variable: "--font-sans",
const inter = TheFont({
weight: '400',
subsets: ['latin'],
variable: '--font-sans',
});
export const metadata: Metadata = {
title: "ParentGrine Falcon",
description: "Laser focused on your kids",
manifest: "/site.webmanifest",
title: 'ParentGrine Falcon',
description: 'Laser focused on your kids',
manifest: '/site.webmanifest',
icons: {
icon: "/favicon.ico",
icon: '/favicon.ico',
},
};
@@ -29,15 +30,15 @@ export default function RootLayout({
}) {
return (
<html lang="en" suppressHydrationWarning={true}>
<body className={`font-sans ${inter.variable}`}>
<NextAuthProvider>
<TRPCReactProvider cookies={cookies().toString()}>
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
{children}
</ThemeProvider>
</TRPCReactProvider>
</NextAuthProvider>
</body>
<body className={`font-sans ${inter.variable}`}>
<NextAuthProvider>
<TRPCReactProvider cookies={cookies().toString()}>
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
{children}
</ThemeProvider>
</TRPCReactProvider>
</NextAuthProvider>
</body>
</html>
);
}

View File

@@ -19,7 +19,7 @@ import {
Copy,
Cable,
Edit,
Edit2, Radar, PhoneCall, Smartphone,
Edit2, Radar, PhoneCall, Smartphone, Waypoints, LocateFixed,
} from 'lucide-react';
export type Icon = LucideIcon;
@@ -34,12 +34,14 @@ export const Icons = {
device: Smartphone,
edit: Edit,
sun: SunMedium,
location: LocateFixed,
login: LogIn,
message: MessageCircleMore,
mobile: TabletSmartphone,
moon: Moon,
presence: Radar,
rocket: Rocket,
route: Waypoints,
save: Save,
spinner: Loader2,
twitter: Twitter,

View File

@@ -41,46 +41,46 @@ const MapMarker: React.FC<MapMarkerProps> = (
setPosition([ping.location.latitude, ping.location.longitude]);
},
});
return <Marker
position={position}
icon={_getIcon(avatar)}
>
<Popup>
<Card className="w-full max-w-md grid gap-4">
<CardHeader>
<div className="flex items-center gap-4">
<Avatar className="h-12 w-12">
<AvatarImage src={_getAvatarImage(avatar)} alt={childName} />
<AvatarFallback>{getInitials(childName)}</AvatarFallback>
</Avatar>
<div className="grid gap-1">
<div className="text-lg font-bold">{childName}</div>
<div className="text-sm text-gray-500 dark:text-gray-400">
<div className="flex flex-row items-center px-2 space-x-3">
<Icons.device /> {deviceName}
return <div className="animate-spin">
<Marker
position={position}
icon={_getIcon(avatar)}
>
<Popup>
<Card className="w-full max-w-md grid gap-4">
<CardHeader>
<div className="flex items-center gap-4">
<Avatar className="h-12 w-12">
<AvatarImage src={_getAvatarImage(avatar)} alt={childName} />
<AvatarFallback>{getInitials(childName)}</AvatarFallback>
</Avatar>
<div className="grid gap-1">
<div className="text-lg font-bold">{childName}</div>
<div className="text-sm text-gray-500 dark:text-gray-400">
<div className="flex flex-row items-center px-2 space-x-3">
<Icons.device /> {deviceName}
</div>
</div>
</div>
</div>
</div>
</CardHeader>
<CardContent>
<div className="text-sm text-gray-500 dark:text-gray-400">
Last seen - {timestamp.toLocaleDateString() + ' ' + timestamp.toLocaleTimeString()}
</div>
</CardContent>
<CardFooter className="flex justify-end gap-4">
<Link className="text-primary" href="#">
<Icons.message className="h-6 w-6" />
</Link>
<Link className="text-primary" href="#">
<Icons.call className="h-6 w-6" />
</Link>
</CardFooter>
</Card>
</Popup>;
</Marker>;
;
</CardHeader>
<CardContent>
<div className="text-sm text-gray-500 dark:text-gray-400">
Last seen - {timestamp.toLocaleDateString() + ' ' + timestamp.toLocaleTimeString()}
</div>
</CardContent>
<CardFooter className="flex justify-end gap-4">
<Link className="text-primary" href="#">
<Icons.message className="h-6 w-6" />
</Link>
<Link className="text-primary" href="#">
<Icons.call className="h-6 w-6" />
</Link>
</CardFooter>
</Card>
</Popup>
</Marker>
</div>;
};
export default MapMarker;

View File

@@ -0,0 +1,21 @@
'use client';
import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group';
import { Icons } from '@/components/icons';
import React from 'react';
export const MapViewTypeSelector = () => {
const [currentView, setCurrentView] = React.useState('location');
return (
<ToggleGroup type="single" value={currentView}
onValueChange={(value) => setCurrentView(value)}>
<ToggleGroupItem value="location">
<Icons.location className="w-4 h-4 mr-1" />
Location
</ToggleGroupItem>
<ToggleGroupItem value="route">
<Icons.route className="w-4 h-4 mr-1" />
Route
</ToggleGroupItem>
</ToggleGroup>);
};

View File

@@ -1,10 +1,10 @@
"use client"
'use client';
import * as React from "react"
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"
import { Circle } from "lucide-react"
import * as React from 'react';
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
import { Circle } from 'lucide-react';
import { cn } from "@/lib/utils"
import { cn } from '@/lib/utils';
const RadioGroup = React.forwardRef<
React.ElementRef<typeof RadioGroupPrimitive.Root>,
@@ -12,13 +12,13 @@ const RadioGroup = React.forwardRef<
>(({ className, ...props }, ref) => {
return (
<RadioGroupPrimitive.Root
className={cn("grid gap-2", className)}
className={cn('grid gap-2', className)}
{...props}
ref={ref}
/>
)
})
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName
);
});
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
const RadioGroupItem = React.forwardRef<
React.ElementRef<typeof RadioGroupPrimitive.Item>,
@@ -28,8 +28,8 @@ const RadioGroupItem = React.forwardRef<
<RadioGroupPrimitive.Item
ref={ref}
className={cn(
"aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
className
'aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
className,
)}
{...props}
>
@@ -37,8 +37,8 @@ const RadioGroupItem = React.forwardRef<
<Circle className="h-2.5 w-2.5 fill-current text-current" />
</RadioGroupPrimitive.Indicator>
</RadioGroupPrimitive.Item>
)
})
RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName
);
});
RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;
export { RadioGroup, RadioGroupItem }
export { RadioGroup, RadioGroupItem };