mirror of
https://github.com/marcogll/TaxHacker_s23.git
synced 2026-01-13 13:25:18 +00:00
feat: move currency converter to server
This commit is contained in:
66
app/api/currency/route.ts
Normal file
66
app/api/currency/route.ts
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import { format } from "date-fns"
|
||||||
|
import { NextRequest, NextResponse } from "next/server"
|
||||||
|
|
||||||
|
type HistoricRate = {
|
||||||
|
currency: string
|
||||||
|
rate: number
|
||||||
|
inverse: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const searchParams = request.nextUrl.searchParams
|
||||||
|
const fromCurrency = searchParams.get("from")
|
||||||
|
const toCurrency = searchParams.get("to")
|
||||||
|
const dateParam = searchParams.get("date")
|
||||||
|
|
||||||
|
if (!fromCurrency || !toCurrency || !dateParam) {
|
||||||
|
return NextResponse.json({ error: "Missing required parameters: from, to, date" }, { status: 400 })
|
||||||
|
}
|
||||||
|
|
||||||
|
const date = new Date(dateParam)
|
||||||
|
if (isNaN(date.getTime())) {
|
||||||
|
return NextResponse.json({ error: "Invalid date format" }, { status: 400 })
|
||||||
|
}
|
||||||
|
|
||||||
|
const formattedDate = format(date, "yyyy-MM-dd")
|
||||||
|
const url = `https://www.xe.com/currencytables/?from=${fromCurrency}&date=${formattedDate}`
|
||||||
|
|
||||||
|
const response = await fetch(url)
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: `Failed to fetch currency data: ${response.status}` },
|
||||||
|
{ status: response.status }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const html = await response.text()
|
||||||
|
|
||||||
|
// Extract the JSON data from the __NEXT_DATA__ script tag
|
||||||
|
const scriptTagRegex = /<script id="__NEXT_DATA__" type="application\/json">([\s\S]*?)<\/script>/
|
||||||
|
const match = html.match(scriptTagRegex)
|
||||||
|
|
||||||
|
if (!match || !match[1]) {
|
||||||
|
return NextResponse.json({ error: "Could not find currency data in the page" }, { status: 500 })
|
||||||
|
}
|
||||||
|
|
||||||
|
const jsonData = JSON.parse(match[1])
|
||||||
|
const historicRates = jsonData.props.pageProps.historicRates as HistoricRate[]
|
||||||
|
|
||||||
|
if (!historicRates || historicRates.length === 0) {
|
||||||
|
return NextResponse.json({ error: "No currency rates found for the specified date" }, { status: 404 })
|
||||||
|
}
|
||||||
|
|
||||||
|
const rate = historicRates.find((rate) => rate.currency === toCurrency)
|
||||||
|
|
||||||
|
if (!rate) {
|
||||||
|
return NextResponse.json({ error: `Currency rate not found for ${toCurrency}` }, { status: 404 })
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ rate: rate.rate })
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Currency API error:", error)
|
||||||
|
return NextResponse.json({ error: "Internal server error" }, { status: 500 })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
import { getCurrencyRate } from "@/lib/currency-scraper"
|
|
||||||
import { formatCurrency } from "@/lib/utils"
|
import { formatCurrency } from "@/lib/utils"
|
||||||
import { format, startOfDay } from "date-fns"
|
import { format, startOfDay } from "date-fns"
|
||||||
import { Loader2 } from "lucide-react"
|
import { Loader2 } from "lucide-react"
|
||||||
@@ -75,3 +74,24 @@ export const FormConvertCurrency = ({
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getCurrencyRate(currencyCodeFrom: string, currencyCodeTo: string, date: Date): Promise<number> {
|
||||||
|
try {
|
||||||
|
const formattedDate = format(date, "yyyy-MM-dd")
|
||||||
|
const url = `/api/currency?from=${currencyCodeFrom}&to=${currencyCodeTo}&date=${formattedDate}`
|
||||||
|
|
||||||
|
const response = await fetch(url)
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const errorData = await response.json()
|
||||||
|
console.error("Currency API error:", errorData.error)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json()
|
||||||
|
return data.rate
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching currency rate:", error)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,57 +0,0 @@
|
|||||||
import { format } from "date-fns"
|
|
||||||
|
|
||||||
type HistoricRate = {
|
|
||||||
currency: string
|
|
||||||
rate: number
|
|
||||||
inverse: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getCurrencyRate(currencyCodeFrom: string, currencyCodeTo: string, date: Date): Promise<number> {
|
|
||||||
const rates = await fetchHistoricalCurrencyRates(currencyCodeFrom, date)
|
|
||||||
|
|
||||||
if (!rates || rates.length === 0) {
|
|
||||||
console.log("Could not fetch currency rates", currencyCodeFrom, currencyCodeTo, date)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
const rate = rates.find((rate) => rate.currency === currencyCodeTo)
|
|
||||||
|
|
||||||
if (!rate) {
|
|
||||||
console.log("Could not find currency rate", currencyCodeFrom, currencyCodeTo, date)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return rate.rate
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function fetchHistoricalCurrencyRates(currency: string = "USD", date: Date): Promise<HistoricRate[]> {
|
|
||||||
const formattedDate = format(date, "yyyy-MM-dd")
|
|
||||||
|
|
||||||
const url = `https://corsproxy.io/?url=${encodeURIComponent(
|
|
||||||
`https://www.xe.com/currencytables/?from=${currency}&date=${formattedDate}`
|
|
||||||
)}`
|
|
||||||
|
|
||||||
const response = await fetch(url)
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`HTTP error! Status: ${response.status}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
const html = await response.text()
|
|
||||||
|
|
||||||
// Extract the JSON data from the __NEXT_DATA__ script tag
|
|
||||||
const scriptTagRegex = /<script id="__NEXT_DATA__" type="application\/json">([\s\S]*?)<\/script>/
|
|
||||||
const match = html.match(scriptTagRegex)
|
|
||||||
|
|
||||||
if (!match || !match[1]) {
|
|
||||||
throw new Error("Could not find currency data in the page")
|
|
||||||
}
|
|
||||||
|
|
||||||
const jsonData = JSON.parse(match[1])
|
|
||||||
|
|
||||||
const historicRates = jsonData.props.pageProps.historicRates as HistoricRate[]
|
|
||||||
|
|
||||||
console.log("Historic Rates for this date", historicRates)
|
|
||||||
|
|
||||||
return historicRates
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user