Define a dashboard summary mockup #71
| @ -1,12 +1,15 @@ | |||||||
| /* Copyright (C) 2024 Manuel Bustillo*/ | /* Copyright (C) 2024 Manuel Bustillo*/ | ||||||
| 
 | 
 | ||||||
| import { lusitana } from '@/app/ui/fonts'; | import { lusitana } from '@/app/ui/fonts'; | ||||||
|  | import ExpenseSummary from '@/app/ui/expenses/summary'; | ||||||
|   |   | ||||||
| export default  function Page () { | export default  function Page () { | ||||||
|   return ( |   return ( | ||||||
|     <div className="w-full"> |     <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> |         <h1 className={`${lusitana.className} text-2xl`}>Expenses</h1> | ||||||
|  |         <h2 className={`${lusitana.className} text-xl`}>Summary</h2> | ||||||
|  |         <ExpenseSummary /> | ||||||
|       </div> |       </div> | ||||||
|     </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