Define a dashboard summary mockup #71
| @ -1,12 +1,15 @@ | ||||
| /* Copyright (C) 2024 Manuel Bustillo*/ | ||||
| 
 | ||||
| import { lusitana } from '@/app/ui/fonts'; | ||||
| import ExpenseSummary from '@/app/ui/expenses/summary'; | ||||
|   | ||||
| export default  function Page () { | ||||
|   return ( | ||||
|     <div className="w-full"> | ||||
|       <div className="flex w-full items-center justify-between"> | ||||
|       <div className="w-full items-center justify-between"> | ||||
|         <h1 className={`${lusitana.className} text-2xl`}>Expenses</h1> | ||||
|         <h2 className={`${lusitana.className} text-xl`}>Summary</h2> | ||||
|         <ExpenseSummary /> | ||||
|       </div> | ||||
|     </div> | ||||
|   ); | ||||
|  | ||||
							
								
								
									
										11
									
								
								app/types.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								app/types.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| import * as HeroIcon from '@heroicons/react/24/outline' | ||||
| import { ComponentProps } from 'react' | ||||
| 
 | ||||
| type Props = { | ||||
|   name: keyof typeof HeroIcon | ||||
| } & ComponentProps<typeof HeroIcon.AcademicCapIcon> | ||||
| 
 | ||||
| export const Icon = ({ name, ...props }: Props) => { | ||||
|   const IconComponent = HeroIcon[name] | ||||
|   return <IconComponent {...props} /> | ||||
| } | ||||
							
								
								
									
										51
									
								
								app/ui/components/dashboard-cards.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								app/ui/components/dashboard-cards.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | ||||
| import clsx from "clsx" | ||||
| import { Icon } from "../../types"; | ||||
| import * as HeroIcon from '@heroicons/react/24/outline' | ||||
| 
 | ||||
| type Style = "green" | "blue" | "red" | "orange" | "gray" | ||||
| 
 | ||||
| const colorClasses = (style: Style) => { | ||||
|     switch (style) { | ||||
|         case "green": | ||||
|             return "bg-green-700 hover:bg-green-800" | ||||
|         case "blue": | ||||
|             return "bg-blue-500 hover:bg-blue-700" | ||||
|         case "red": | ||||
|             return "bg-red-600 hover:bg-red-700" | ||||
|         case "orange": | ||||
|             return "bg-orange-600 hover:bg-orange-700" | ||||
|         case "gray": | ||||
|             return "bg-gray-600 hover:bg-gray-700" | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export async function MainCard({ amount, title, subtitle, style, iconName }: | ||||
|     { | ||||
|         amount: string, | ||||
|         title: string, | ||||
|         subtitle?: string, | ||||
|         style: Style, | ||||
|         iconName: keyof typeof HeroIcon | ||||
|     }) { | ||||
| 
 | ||||
|     return ( | ||||
|         <div className={`w-80 m-1 py-2 px-6 text-white flex flex-row items-center ${colorClasses(style)}`}> | ||||
|             <Icon className="m-3 h-14 w-14" name={iconName} /> | ||||
|             <div className="flex flex-col justify-evenly"> | ||||
|                 <div className="text-4xl font-medium">{amount}</div> | ||||
|                 <div className="text-xl">{title}</div> | ||||
|                 <div className="text-sm">{subtitle || 'ㅤ'}</div> | ||||
|             </div> | ||||
|         </div> | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
| export async function SecondaryCard({ amount, title, iconName, style }: { amount: string, title: string, iconName: keyof typeof HeroIcon, style: Style }) { | ||||
|     return ( | ||||
|         <div className={`h-12 w-80 m-1 p-2 text-white flex flex-row items-center ${colorClasses(style)}`}> | ||||
|             <Icon className="m-3 h-7 w-7" name={iconName} /> | ||||
|             <span className="text-2xl font-medium mx-1">{amount}</span> | ||||
|             <span className="text-l mx-1">{title}</span> | ||||
|         </div> | ||||
|     ); | ||||
| } | ||||
							
								
								
									
										43
									
								
								app/ui/expenses/summary.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								app/ui/expenses/summary.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | ||||
| import { MainCard, SecondaryCard } from '../components/dashboard-cards'; | ||||
| 
 | ||||
| export default async function ExpenseSummary() { | ||||
|     return ( | ||||
|         <div className="my-4"> | ||||
| 
 | ||||
|             <div className="flex flex-row w-full my-2"> | ||||
|                 <MainCard style="green" amount="65000€" title="Projected" subtitle="150 guests" iconName="ArrowTrendingUpIcon" /> | ||||
| 
 | ||||
|                 <div className="flex flex-col"> | ||||
|                     <MainCard amount="10000€" title="Paid already" iconName="Square3Stack3DIcon" style='blue' /> | ||||
|                     <MainCard amount="198€" title="/ guest" iconName="UserIcon" style='blue' /> | ||||
|                 </div> | ||||
|                 <div className="flex flex-col"> | ||||
|                     <MainCard amount="78000€" title="Max." subtitle='200 guests' iconName="ChevronDoubleUpIcon" style="orange" /> | ||||
|                     <MainCard amount="45000€" title="Min." subtitle="125 guests" iconName="ChevronDoubleDownIcon" style="green" /> | ||||
|                 </div> | ||||
| 
 | ||||
|             </div> | ||||
| 
 | ||||
|             <div className="flex flex-row w-full my-2"> | ||||
|                 <MainCard style="blue" amount="150" title="Invites sent" iconName="UsersIcon" /> | ||||
| 
 | ||||
|                 <div className="flex flex-col"> | ||||
|                     <SecondaryCard amount="31%" title="confirmed (27 guests)" iconName="CheckIcon" style='green' /> | ||||
|                     <SecondaryCard amount="5%" title="declined (8 guests)" iconName="XMarkIcon" style='red' /> | ||||
|                 </div> | ||||
| 
 | ||||
|                 <div className="flex flex-col"> | ||||
|                 <SecondaryCard amount="17%" title="tentative (14 guests)" iconName="QuestionMarkCircleIcon" style='orange' /> | ||||
|                     <SecondaryCard amount="65%" title="awaiting (72 guests)" iconName="EllipsisHorizontalIcon" style='gray' /> | ||||
| 
 | ||||
|                 </div> | ||||
|             </div> | ||||
| 
 | ||||
|             <div className="flex flex-row w-full my-2"> | ||||
|                 <MainCard style="blue" amount="5" title="Table simulations" iconName="ServerStackIcon" /> | ||||
|                 <MainCard style="blue" amount="9" title="Bus simulations" iconName="TruckIcon" /> | ||||
|                 <MainCard style="blue" amount="98" title="QR codes" iconName="QrCodeIcon" /> | ||||
|             </div> | ||||
|         </div> | ||||
|     ); | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user