Current prices are {Math.round((averagePrice - currentPrice) / averagePrice * 100)}% below the average for this route.
+
+
+ )}
+ {recommendation === 'wait' && (
+
+
+
+
Consider waiting for prices to drop
+
Current prices are {Math.round((currentPrice - averagePrice) / averagePrice * 100)}% above the average for this route.
+
+
+ )}
+ {recommendation === 'neutral' && (
+
+
+
+
Prices are stable
+
Current prices are close to the average for this route.
+
+
+ )}
+
+
+
+ );
+};
+
+export default PriceHistoryWidget;
\ No newline at end of file
diff --git a/README.md b/README.md
index 0b8e1c8..f0f8280 100644
--- a/README.md
+++ b/README.md
@@ -1,22 +1,54 @@
-This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
+# Flight Price History Component
-## Getting Started
+This is a prototype of a price history feature for a flight search website. The component displays price trends and recommendations at a glance, with the ability to expand into a full interactive graph view.
-First, run the development server:
+## Features
-```bash
-npm run dev
-# or
-yarn dev
-# or
-pnpm dev
-# or
-bun dev
+- Compact view showing current price, price trend, and quick recommendation
+- Expandable detailed view with price history graph
+- Visual indicators for price changes (up/down)
+- Recommendations based on price analysis
+- Responsive design using Tailwind CSS
+
+## How to Use
+
+Import the component in your Next.js/React application:
+
+```jsx
+import PriceHistoryWidget from './components/PriceHistoryWidget';
+
+// Then use it in your component
+function FlightDetails() {
+ return (
+
+
Flight Details
+
+
+ );
+}
```
-Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
+## Data Structure
+
+The component expects price history data in the following format:
-You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
+```typescript
+type PriceHistoryData = {
+ currency: string;
+ currentPrice: number;
+ averagePrice: number;
+ lowestPrice: number;
+ highestPrice: number;
+ recommendation: "buy" | "wait" | "neutral";
+ priceChangePercentage: number;
+ history: PriceDataPoint[];
+};
-This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
+type PriceDataPoint = {
+ date: string; // ISO date string
+ price: number;
+ isLowestPrice?: boolean;
+};
+```
+For this prototype, mock data is generated internally. In a real application, you would connect this to your actual price history API.
\ No newline at end of file
diff --git a/index.tsx b/index.tsx
new file mode 100644
index 0000000..cb7bcb0
--- /dev/null
+++ b/index.tsx
@@ -0,0 +1,37 @@
+import React from 'react';
+import PriceHistoryWidget from './PriceHistoryWidget';
+
+const Home: React.FC = () => {
+ return (
+
+
+
+ Flight Price History Feature
+
+
+
+
+
+
+ New York to London
+
+
+ Dec 15 - Dec 22 • Economy • 1 Adult
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default Home;
\ No newline at end of file
diff --git a/mockPriceData.ts b/mockPriceData.ts
new file mode 100644
index 0000000..20ce8c6
--- /dev/null
+++ b/mockPriceData.ts
@@ -0,0 +1,81 @@
+// Mock data for the price history component
+export type PriceDataPoint = {
+ date: string; // ISO date string
+ price: number;
+ isLowestPrice?: boolean;
+};
+
+export type PriceHistoryData = {
+ currency: string;
+ currentPrice: number;
+ averagePrice: number;
+ lowestPrice: number;
+ highestPrice: number;
+ recommendation: "buy" | "wait" | "neutral";
+ priceChangePercentage: number; // negative means price dropped
+ history: PriceDataPoint[];
+};
+
+// Generate mock data for the last 30 days
+const generateMockData = (): PriceHistoryData => {
+ const today = new Date();
+ const history: PriceDataPoint[] = [];
+ let lowestPrice = Infinity;
+ let highestPrice = 0;
+ let lowestPriceIndex = 0;
+
+ // Generate price points for the last 30 days
+ for (let i = 29; i >= 0; i--) {
+ const date = new Date(today);
+ date.setDate(date.getDate() - i);
+
+ // Base price with some randomness
+ const basePrice = 350;
+ const randomFactor = Math.sin(i / 5) * 50 + Math.random() * 30 - 15;
+ const price = Math.round(basePrice + randomFactor);
+
+ history.push({
+ date: date.toISOString().split('T')[0],
+ price
+ });
+
+ if (price < lowestPrice) {
+ lowestPrice = price;
+ lowestPriceIndex = history.length - 1;
+ }
+
+ if (price > highestPrice) {
+ highestPrice = price;
+ }
+ }
+
+ // Mark the lowest price
+ history[lowestPriceIndex].isLowestPrice = true;
+
+ const currentPrice = history[history.length - 1].price;
+ const sum = history.reduce((acc, item) => acc + item.price, 0);
+ const averagePrice = Math.round(sum / history.length);
+
+ // Determine recommendation based on current price vs average
+ let recommendation: "buy" | "wait" | "neutral" = "neutral";
+ if (currentPrice < averagePrice * 0.95) {
+ recommendation = "buy";
+ } else if (currentPrice > averagePrice * 1.05) {
+ recommendation = "wait";
+ }
+
+ const priceChangePercentage = Math.round(((currentPrice - history[0].price) / history[0].price) * 100);
+
+ return {
+ currency: "USD",
+ currentPrice,
+ averagePrice,
+ lowestPrice,
+ highestPrice,
+ recommendation,
+ priceChangePercentage,
+ history
+ };
+};
+
+export const mockPriceData = generateMockData();
\ No newline at end of file