diff --git a/app/(app)/globals.css b/app/(app)/globals.css
index 6084d22..d657139 100644
--- a/app/(app)/globals.css
+++ b/app/(app)/globals.css
@@ -11,62 +11,78 @@
@layer base {
:root {
--background: 0 0% 100%;
- --foreground: 222.2 84% 4.9%;
+ --foreground: 240 10% 3.9%;
--card: 0 0% 100%;
- --card-foreground: 222.2 84% 4.9%;
+ --card-foreground: 240 10% 3.9%;
--popover: 0 0% 100%;
- --popover-foreground: 222.2 84% 4.9%;
- --primary: 222.2 47.4% 11.2%;
- --primary-foreground: 210 40% 98%;
- --secondary: 210 40% 96.1%;
- --secondary-foreground: 222.2 47.4% 11.2%;
- --muted: 210 40% 96.1%;
- --muted-foreground: 215.4 16.3% 46.9%;
- --accent: 210 40% 96.1%;
- --accent-foreground: 222.2 47.4% 11.2%;
- --destructive: 0 84.2% 60.2%;
- --destructive-foreground: 210 40% 98%;
- --border: 214.3 31.8% 91.4%;
- --input: 214.3 31.8% 91.4%;
- --ring: 222.2 84% 4.9%;
+ --popover-foreground: 240 10% 3.9%;
+ --primary: 240 5.9% 10%;
+ --primary-foreground: 0 0% 98%;
+ --secondary: 240 4.8% 95.9%;
+ --secondary-foreground: 240 5.9% 10%;
+ --muted: 240 4.8% 95.9%;
+ --muted-foreground: 240 3.8% 46.1%;
+ --accent: 240 4.8% 95.9%;
+ --accent-foreground: 240 5.9% 10%;
+ --destructive: 0 72.22% 50.59%;
+ --destructive-foreground: 0 0% 98%;
+ --border: 240 5.9% 90%;
+ --input: 240 5.9% 90%;
+ --ring: 240 5% 64.9%;
+
--chart-1: 12 76% 61%;
--chart-2: 173 58% 39%;
--chart-3: 197 37% 24%;
--chart-4: 43 74% 66%;
--chart-5: 27 87% 67%;
+
--passed: 141.7 76.6% 73.1%;
--failed: 0 84.2% 60.2%;
--skipped: 50.4 97.8% 63.5%;
+
--radius: 0.5rem;
+
+ --color-1: 0 100% 63%;
+ --color-2: 270 100% 63%;
+ --color-3: 210 100% 63%;
+ --color-4: 195 100% 63%;
+ --color-5: 90 100% 63%;
}
.dark {
- --background: 222.2 84% 4.9%;
- --foreground: 210 40% 98%;
- --card: 222.2 84% 4.9%;
- --card-foreground: 210 40% 98%;
- --popover: 222.2 84% 4.9%;
- --popover-foreground: 210 40% 98%;
- --primary: 210 40% 98%;
- --primary-foreground: 222.2 47.4% 11.2%;
- --secondary: 217.2 32.6% 17.5%;
- --secondary-foreground: 210 40% 98%;
- --muted: 217.2 32.6% 17.5%;
- --muted-foreground: 215 20.2% 65.1%;
- --accent: 217.2 32.6% 17.5%;
- --accent-foreground: 210 40% 98%;
+ --background: 240 10% 3.9%;
+ --foreground: 0 0% 98%;
+ --card: 240 10% 3.9%;
+ --card-foreground: 0 0% 98%;
+ --popover: 240 10% 3.9%;
+ --popover-foreground: 0 0% 98%;
+ --primary: 0 0% 98%;
+ --primary-foreground: 240 5.9% 10%;
+ --secondary: 240 3.7% 15.9%;
+ --secondary-foreground: 0 0% 98%;
+ --muted: 240 3.7% 15.9%;
+ --muted-foreground: 240 5% 64.9%;
+ --accent: 240 3.7% 15.9%;
+ --accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
- --destructive-foreground: 210 40% 98%;
- --border: 217.2 32.6% 17.5%;
- --input: 217.2 32.6% 17.5%;
- --ring: 212.7 26.8% 83.9%;
+ --destructive-foreground: 0 85.7% 97.3%;
+ --border: 240 3.7% 15.9%;
+ --input: 240 3.7% 15.9%;
+ --ring: 240 4.9% 83.9%;
+
--chart-1: 220 70% 50%;
--chart-2: 160 60% 45%;
--chart-3: 30 80% 55%;
--chart-4: 280 65% 60%;
--chart-5: 340 75% 55%;
+
--passed: 141.7 76.6% 73.1%;
--failed: 0 84.2% 60.2%;
--skipped: 50.4 97.8% 63.5%;
+ --color-1: 0 100% 63%;
+ --color-2: 270 100% 63%;
+ --color-3: 210 100% 63%;
+ --color-4: 195 100% 63%;
+ --color-5: 90 100% 63%;
}
}
@@ -78,3 +94,22 @@
@apply bg-background text-foreground;
}
}
+
+.gradient-text {
+ background: linear-gradient(45deg, #f31890, #0574f3, #04f85d, #f41a51);
+ -webkit-background-clip: text;
+ background-clip: text;
+ color: transparent;
+ background-size: 300% 300%;
+ animation: gradient-shift 5s ease-in-out infinite;
+}
+
+@keyframes gradient-shift {
+ 0%,
+ 100% {
+ background-position: 0% 50%;
+ }
+ 50% {
+ background-position: 100% 50%;
+ }
+}
diff --git a/app/(app)/layout.tsx b/app/(app)/layout.tsx
index a241f4b..b3e1983 100644
--- a/app/(app)/layout.tsx
+++ b/app/(app)/layout.tsx
@@ -1,19 +1,7 @@
import type { Metadata } from 'next';
-// import localFont from 'next/font/local';
import './globals.css';
import { DetailedHTMLProps, HtmlHTMLAttributes } from 'react';
-// import { ThemeProvider } from '@/components/theme-provider';
-
-// const geistSans = localFont({
-// src: './fonts/GeistVF.woff',
-// variable: '--font-geist-sans',
-// weight: '100 900',
-// });
-// const geistMono = localFont({
-// src: './fonts/GeistMonoVF.woff',
-// variable: '--font-geist-mono',
-// weight: '100 900',
-// });
+import { Footer } from '@/components/home/footer';
export const metadata: Metadata = {
title: 'Ultra Reporter',
@@ -33,15 +21,9 @@ const RootLayout = ({
-
- {/* */}
+
{children}
- {/* */}
+
);
diff --git a/app/(app)/page.tsx b/app/(app)/page.tsx
index 7f75a62..56716f6 100644
--- a/app/(app)/page.tsx
+++ b/app/(app)/page.tsx
@@ -1,34 +1,36 @@
-import Image from 'next/image';
import { FileUpload } from '@/components/utils/file-upload';
+import { OpenSource } from '@/components/home/open-source';
+import { NavBar } from '@/components/home/nav-bar';
+import { Features } from '@/components/home/feature';
+import Link from 'next/link';
+import { StarIcon } from 'lucide-react';
+import { RainbowButton } from '@/components/ui/rainbow-button';
const LandingPage = (): JSX.Element => {
return (
-
-
-
-
-
Ultra Reporter
-
- Upload your Test result XML file and let our advanced reporter
- system analyze and display the data for you.
-
+ <>
+
+
+
+
+
+ Star us on
+ GitHub
+
+
+
+ Convert your Test results to
+
+ Beautiful Report
+
+ in one click
+
-
-
Key Features
-
- - Display TestNG results in beautiful dashboard
- - See the Tests insights charts
-
-
+
+
-
+ >
);
};
diff --git a/app/(app)/results/page.tsx b/app/(app)/results/page.tsx
index 6611e68..998c838 100644
--- a/app/(app)/results/page.tsx
+++ b/app/(app)/results/page.tsx
@@ -1,7 +1,6 @@
'use client';
import { useState, useEffect } from 'react';
-import Link from 'next/link';
import { TestResult } from '@/types/types';
import {
ColumnFiltersState,
@@ -13,7 +12,6 @@ import {
Card,
CardContent,
CardDescription,
- CardFooter,
CardHeader,
CardTitle,
} from '@/components/ui/card';
@@ -23,6 +21,7 @@ import { getData, TestResultData } from '@/components/data-table/data';
import { columns } from '@/components/data-table/columns';
import { PieComponent } from '@/components/charts/pie-chart';
import { formatDate, round } from '@/lib/formatting';
+import { NavBar } from '@/components/home/nav-bar';
const chartConfig: ChartConfig = {
total: {
@@ -99,90 +98,84 @@ const ResultsPage = (): JSX.Element => {
];
return (
-
-
- Ultra Report for {date}
-
-
-
-
- Test Statistics
- Overall Test execution statistics
-
-
-
-
- Total Tests
- {passed + failed + skipped}
-
-
- Passed
- {passed}
-
-
- Failed
- {failed}
-
-
- Skipped
- {skipped}
-
-
-
-
-
-
- {result ? (
-
-
- Test Details
-
- List of all the executed test cases
-
-
-
-
+
+
+
+
+
+
+ Test Statistics
+
+ Overall Test execution statistics
+
+
+
+
+
+ Total Tests
+ {passed + failed + skipped}
+
+
+ Passed
+ {passed}
+
+
+ Failed
+ {failed}
+
+
+ Skipped
+ {skipped}
+
+
+
+
+
+
+
-
-
-
-
- Process Another XML File
-
-
-
-
- ) : (
-
No data available
- )}
-
+
+
+ {result ? (
+
+
+ Test Details
+
+ List of all the executed test cases
+
+
+
+
+
+
+ ) : (
+ No data available
+ )}
+
+
+
);
};
diff --git a/components/home/feature.tsx b/components/home/feature.tsx
new file mode 100644
index 0000000..0f2ede7
--- /dev/null
+++ b/components/home/feature.tsx
@@ -0,0 +1,57 @@
+import { MagnifyingGlassIcon } from '@radix-ui/react-icons';
+import {
+ BarChartIcon,
+ CircleAlert,
+ MousePointerClick,
+ Table,
+} from 'lucide-react';
+
+const features = [
+ {
+ title: 'One Click',
+ description: 'Generate your Test execution report in one click',
+ icon: MousePointerClick,
+ },
+ {
+ title: 'Test Visualization',
+ description: 'Generate insightful charts and graphs from your data',
+ icon: BarChartIcon,
+ },
+ {
+ title: 'Detailed Results',
+ description:
+ 'Dive deep into your test results with comprehensive details in the Table',
+ icon: Table,
+ },
+ {
+ title: 'View Attachments',
+ description: 'View your tests attachments like Screenshots and Texts',
+ icon: MagnifyingGlassIcon,
+ },
+ {
+ title: 'View Exceptions',
+ description: 'View your tests exceptions and Errors',
+ icon: CircleAlert,
+ },
+];
+
+export const Features = (): JSX.Element => {
+ return (
+
+
+ Features
+
+
+ {features.map((feature, index) => (
+
+
+
+ {feature.title}
+
+
{feature.description}
+
+ ))}
+
+
+ );
+};
diff --git a/components/home/footer.tsx b/components/home/footer.tsx
new file mode 100644
index 0000000..edcb4df
--- /dev/null
+++ b/components/home/footer.tsx
@@ -0,0 +1,67 @@
+import Image from 'next/image';
+import Link from 'next/link';
+import { UserCard } from './user-card';
+import { GitHub } from '@/components/icons/github';
+import { LinkedIn } from '@/components/icons/linkedin';
+import { X } from '@/components/icons/x';
+import { YouTube } from '@/components/icons/youtube';
+import { Sponsor } from '@/components/icons/sponsor';
+
+export const Footer = (): JSX.Element => {
+ return (
+
+ );
+};
diff --git a/components/home/nav-bar.tsx b/components/home/nav-bar.tsx
new file mode 100644
index 0000000..f265196
--- /dev/null
+++ b/components/home/nav-bar.tsx
@@ -0,0 +1,75 @@
+'use client';
+
+import { useState, useEffect } from 'react';
+import Link from 'next/link';
+import { Button } from '@/components/ui/button';
+import Image from 'next/image';
+import { GitHub } from '@/components/icons/github';
+import { Sponsor } from '@/components/icons/sponsor';
+
+interface NavBarProps {
+ suffix?: string;
+ cta?: string;
+}
+
+export const NavBar = ({ suffix, cta }: NavBarProps): JSX.Element => {
+ const [isScrolled, setIsScrolled] = useState(false);
+
+ useEffect(() => {
+ const handleScroll = (): void => {
+ setIsScrolled(window.scrollY > 10);
+ };
+ window.addEventListener('scroll', handleScroll);
+ return () => window.removeEventListener('scroll', handleScroll);
+ }, []);
+
+ return (
+
+ );
+};
diff --git a/components/home/open-source.tsx b/components/home/open-source.tsx
new file mode 100644
index 0000000..7fdb95c
--- /dev/null
+++ b/components/home/open-source.tsx
@@ -0,0 +1,21 @@
+import Link from 'next/link';
+import { CodeIcon } from 'lucide-react';
+import { RainbowButton } from '@/components/ui/rainbow-button';
+
+export const OpenSource = (): JSX.Element => {
+ return (
+
+
+ We are proudly Open Source ❤️
+
+
+ Our code is open source and available on GitHub
+
+
+
+ View on GitHub
+
+
+
+ );
+};
diff --git a/components/home/user-card.tsx b/components/home/user-card.tsx
new file mode 100644
index 0000000..07bd6df
--- /dev/null
+++ b/components/home/user-card.tsx
@@ -0,0 +1,42 @@
+import { CalendarIcon } from '@radix-ui/react-icons';
+
+import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
+import { Button } from '@/components/ui/button';
+import {
+ HoverCard,
+ HoverCardContent,
+ HoverCardTrigger,
+} from '@/components/ui/hover-card';
+import Link from 'next/link';
+
+export const UserCard = (): JSX.Element => {
+ return (
+
+
+
+
+
+
+
+
+
+
+ WB
+
+
+
@WasiqB
+
+ Ultra Reporter - Created and maintained by Wasiq Bhamla
+
+
+ {' '}
+
+ Created September, 21st 2024
+
+
+
+
+
+
+ );
+};
diff --git a/components/icons/github.tsx b/components/icons/github.tsx
new file mode 100644
index 0000000..7e317ff
--- /dev/null
+++ b/components/icons/github.tsx
@@ -0,0 +1,15 @@
+export const GitHub = (): JSX.Element => {
+ return (
+
+ );
+};
diff --git a/components/icons/linkedin.tsx b/components/icons/linkedin.tsx
new file mode 100644
index 0000000..f453297
--- /dev/null
+++ b/components/icons/linkedin.tsx
@@ -0,0 +1,15 @@
+export const LinkedIn = (): JSX.Element => {
+ return (
+
+ );
+};
diff --git a/components/icons/sponsor.tsx b/components/icons/sponsor.tsx
new file mode 100644
index 0000000..94504ba
--- /dev/null
+++ b/components/icons/sponsor.tsx
@@ -0,0 +1,15 @@
+export const Sponsor = (): JSX.Element => {
+ return (
+
+ );
+};
diff --git a/components/icons/x.tsx b/components/icons/x.tsx
new file mode 100644
index 0000000..4b03885
--- /dev/null
+++ b/components/icons/x.tsx
@@ -0,0 +1,15 @@
+export const X = (): JSX.Element => {
+ return (
+
+ );
+};
diff --git a/components/icons/youtube.tsx b/components/icons/youtube.tsx
new file mode 100644
index 0000000..c65881a
--- /dev/null
+++ b/components/icons/youtube.tsx
@@ -0,0 +1,15 @@
+export const YouTube = (): JSX.Element => {
+ return (
+
+ );
+};
diff --git a/components/ui/avatar.tsx b/components/ui/avatar.tsx
new file mode 100644
index 0000000..1346957
--- /dev/null
+++ b/components/ui/avatar.tsx
@@ -0,0 +1,50 @@
+'use client';
+
+import * as React from 'react';
+import * as AvatarPrimitive from '@radix-ui/react-avatar';
+
+import { cn } from '@/lib/utils';
+
+const Avatar = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+Avatar.displayName = AvatarPrimitive.Root.displayName;
+
+const AvatarImage = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+AvatarImage.displayName = AvatarPrimitive.Image.displayName;
+
+const AvatarFallback = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
+
+export { Avatar, AvatarImage, AvatarFallback };
diff --git a/components/ui/hover-card.tsx b/components/ui/hover-card.tsx
new file mode 100644
index 0000000..1c9816e
--- /dev/null
+++ b/components/ui/hover-card.tsx
@@ -0,0 +1,29 @@
+'use client';
+
+import * as React from 'react';
+import * as HoverCardPrimitive from '@radix-ui/react-hover-card';
+
+import { cn } from '@/lib/utils';
+
+const HoverCard = HoverCardPrimitive.Root;
+
+const HoverCardTrigger = HoverCardPrimitive.Trigger;
+
+const HoverCardContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (
+
+));
+HoverCardContent.displayName = HoverCardPrimitive.Content.displayName;
+
+export { HoverCard, HoverCardTrigger, HoverCardContent };
diff --git a/components/ui/rainbow-button.tsx b/components/ui/rainbow-button.tsx
new file mode 100644
index 0000000..c8c2f6b
--- /dev/null
+++ b/components/ui/rainbow-button.tsx
@@ -0,0 +1,28 @@
+import React from 'react';
+
+import { cn } from '@/lib/utils';
+
+interface RainbowButtonProps
+ extends React.ButtonHTMLAttributes {}
+
+export function RainbowButton({ children, ...props }: RainbowButtonProps) {
+ return (
+
+ );
+}
diff --git a/components/utils/file-upload.tsx b/components/utils/file-upload.tsx
index a8a1037..31b22db 100644
--- a/components/utils/file-upload.tsx
+++ b/components/utils/file-upload.tsx
@@ -5,6 +5,7 @@ import { useRouter } from 'next/navigation';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
+import { UploadIcon } from 'lucide-react';
export const FileUpload = (): JSX.Element => {
const [file, setFile] = useState(null);
@@ -56,7 +57,8 @@ export const FileUpload = (): JSX.Element => {
return (