-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
625ed09
commit 4295e7e
Showing
13 changed files
with
219 additions
and
218 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,4 +15,4 @@ jobs: | |
with: | ||
version: latest | ||
- name: Run Biome | ||
run: biome ci . | ||
run: biome ci ./src |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
#!/usr/bin/env node --no-warnings | ||
|
||
import '../dist/cli.js'; | ||
import "../dist/cli.js"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -72,4 +72,4 @@ export async function POST(request: NextRequest) { | |
} | ||
|
||
return NextResponse.json({ received: true }); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,64 +1,69 @@ | ||
import Link from "next/link"; | ||
import { polar } from "../../polar"; | ||
import type { Product } from "@polar-sh/sdk/models/components"; | ||
import Link from "next/link"; | ||
import { useMemo } from "react"; | ||
import { polar } from "../../polar"; | ||
|
||
interface ProductCardProps { | ||
product: Product | ||
product: Product; | ||
} | ||
|
||
export const ProductCard = ({ product }: ProductCardProps) => { | ||
// Handling just a single price for now | ||
// Remember to handle multiple prices for products if you support monthly & yearly pricing plans | ||
const firstPrice = product.prices[0] | ||
// Handling just a single price for now | ||
// Remember to handle multiple prices for products if you support monthly & yearly pricing plans | ||
const firstPrice = product.prices[0]; | ||
|
||
const price = useMemo(() => { | ||
switch(firstPrice.amountType) { | ||
case 'fixed': | ||
// The Polar API returns prices in cents - Convert to dollars for display | ||
return `$${firstPrice.priceAmount / 100}` | ||
case 'free': | ||
return 'Free' | ||
default: | ||
return 'Pay what you want' | ||
} | ||
}, [firstPrice]) | ||
const price = useMemo(() => { | ||
switch (firstPrice.amountType) { | ||
case "fixed": | ||
// The Polar API returns prices in cents - Convert to dollars for display | ||
return `$${firstPrice.priceAmount / 100}`; | ||
case "free": | ||
return "Free"; | ||
default: | ||
return "Pay what you want"; | ||
} | ||
}, [firstPrice]); | ||
|
||
return ( | ||
<div className="flex flex-col gap-y-24 justify-between p-12 rounded-3xl bg-neutral-950 h-full border border-neutral-900"> | ||
<div className="flex flex-col gap-y-8"> | ||
<h1 className="text-3xl">{product.name}</h1> | ||
<p className="text-neutral-400">{product.description}</p> | ||
<ul> | ||
{product.benefits.map((benefit) => ( | ||
<li key={benefit.id} className="flex flex-row gap-x-2 items-center"> | ||
{benefit.description} | ||
</li> | ||
))} | ||
</ul> | ||
</div> | ||
<div className="flex flex-row gap-x-4 justify-between items-center"> | ||
<Link className="h-8 flex flex-row items-center justify-center rounded-full bg-white text-black font-medium px-4" href={`/checkout?priceId=${firstPrice.id}`}>Buy</Link> | ||
<span className="text-neutral-500">{price}</span> | ||
</div> | ||
</div> | ||
) | ||
} | ||
return ( | ||
<div className="flex flex-col gap-y-24 justify-between p-12 rounded-3xl bg-neutral-950 h-full border border-neutral-900"> | ||
<div className="flex flex-col gap-y-8"> | ||
<h1 className="text-3xl">{product.name}</h1> | ||
<p className="text-neutral-400">{product.description}</p> | ||
<ul> | ||
{product.benefits.map((benefit) => ( | ||
<li key={benefit.id} className="flex flex-row gap-x-2 items-center"> | ||
{benefit.description} | ||
</li> | ||
))} | ||
</ul> | ||
</div> | ||
<div className="flex flex-row gap-x-4 justify-between items-center"> | ||
<Link | ||
className="h-8 flex flex-row items-center justify-center rounded-full bg-white text-black font-medium px-4" | ||
href={`/checkout?priceId=${firstPrice.id}`} | ||
> | ||
Buy | ||
</Link> | ||
<span className="text-neutral-500">{price}</span> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default async function Page() { | ||
const { result } = await polar.products.list({ | ||
organizationId: process.env.POLAR_ORGANIZATION_ID!, | ||
isArchived: false // Only fetch products which are published | ||
}) | ||
const { result } = await polar.products.list({ | ||
organizationId: process.env.POLAR_ORGANIZATION_ID!, | ||
isArchived: false, // Only fetch products which are published | ||
}); | ||
|
||
return ( | ||
<div className="flex flex-col gap-y-32"> | ||
<h1 className="text-5xl">Products</h1> | ||
<div className="grid grid-cols-4 gap-12"> | ||
{result.items.map((product) => ( | ||
<ProductCard key={product.id} product={product} /> | ||
))} | ||
</div> | ||
</div> | ||
); | ||
} | ||
return ( | ||
<div className="flex flex-col gap-y-32"> | ||
<h1 className="text-5xl">Products</h1> | ||
<div className="grid grid-cols-4 gap-12"> | ||
{result.items.map((product) => ( | ||
<ProductCard key={product.id} product={product} /> | ||
))} | ||
</div> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,12 @@ | ||
import { Polar } from '@polar-sh/sdk' | ||
import type { ServerList } from '@polar-sh/sdk/src/lib/config' | ||
import { Polar } from "@polar-sh/sdk"; | ||
import type { ServerList } from "@polar-sh/sdk/src/lib/config"; | ||
|
||
export const usePolar = (accessToken: string, server: keyof typeof ServerList) => { | ||
return new Polar({ | ||
accessToken, | ||
server, | ||
}) | ||
} | ||
export const usePolar = ( | ||
accessToken: string, | ||
server: keyof typeof ServerList, | ||
) => { | ||
return new Polar({ | ||
accessToken, | ||
server, | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,36 @@ | ||
import { defineEventHandler, sendRedirect } from 'h3' | ||
import type { ServerList } from '@polar-sh/sdk/src/lib/config' | ||
import { usePolar } from '~/utils/polar' | ||
import type { ServerList } from "@polar-sh/sdk/src/lib/config"; | ||
import { defineEventHandler, sendRedirect } from "h3"; | ||
import { usePolar } from "~/utils/polar"; | ||
|
||
export default defineEventHandler(async (event) => { | ||
const { priceId } = getQuery(event) | ||
if (!priceId) throw Error('MISSING_PRICE_ID_QUERY_PARAM') | ||
const productPriceId = priceId.toString() | ||
const { priceId } = getQuery(event); | ||
if (!priceId) throw Error("MISSING_PRICE_ID_QUERY_PARAM"); | ||
const productPriceId = priceId.toString(); | ||
|
||
const url = getRequestURL(event) | ||
url.pathname = '/checkout/confirmation?checkout_id={CHECKOUT_ID}' | ||
const successUrl = url.toString() | ||
const url = getRequestURL(event); | ||
url.pathname = "/checkout/confirmation?checkout_id={CHECKOUT_ID}"; | ||
const successUrl = url.toString(); | ||
|
||
const { | ||
polarAccessToken, polarServer, | ||
} = useRuntimeConfig(event) | ||
const { polarAccessToken, polarServer } = useRuntimeConfig(event); | ||
|
||
const polar = usePolar(polarAccessToken, polarServer as keyof typeof ServerList) | ||
const polar = usePolar( | ||
polarAccessToken, | ||
polarServer as keyof typeof ServerList, | ||
); | ||
|
||
try { | ||
const result = await polar.checkouts.custom.create({ | ||
productPriceId, | ||
successUrl, | ||
}) | ||
try { | ||
const result = await polar.checkouts.custom.create({ | ||
productPriceId, | ||
successUrl, | ||
}); | ||
|
||
return sendRedirect(event, result.url) | ||
} catch (error) { | ||
console.error(error) | ||
throw createError({ | ||
statusCode: 500, | ||
statusMessage: 'Internal Server Error', | ||
fatal: true, | ||
}) | ||
} | ||
}) | ||
return sendRedirect(event, result.url); | ||
} catch (error) { | ||
console.error(error); | ||
throw createError({ | ||
statusCode: 500, | ||
statusMessage: "Internal Server Error", | ||
fatal: true, | ||
}); | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,20 @@ | ||
import type { ServerList } from '@polar-sh/sdk/src/lib/config' | ||
import { usePolar } from '~/utils/polar' | ||
import type { ServerList } from "@polar-sh/sdk/src/lib/config"; | ||
import { usePolar } from "~/utils/polar"; | ||
|
||
export default defineEventHandler({ | ||
handler: async (event) => { | ||
const { | ||
polarAccessToken, polarServer, polarOrganizationId, | ||
} = useRuntimeConfig(event) | ||
handler: async (event) => { | ||
const { polarAccessToken, polarServer, polarOrganizationId } = | ||
useRuntimeConfig(event); | ||
|
||
const polar = usePolar(polarAccessToken, polarServer as keyof typeof ServerList) | ||
const polar = usePolar( | ||
polarAccessToken, | ||
polarServer as keyof typeof ServerList, | ||
); | ||
|
||
const { result } = await polar.products.list({ | ||
organizationId: polarOrganizationId, | ||
isArchived: false, // Only fetch products which are published | ||
}) | ||
return result.items | ||
}, | ||
}) | ||
const { result } = await polar.products.list({ | ||
organizationId: polarOrganizationId, | ||
isArchived: false, // Only fetch products which are published | ||
}); | ||
return result.items; | ||
}, | ||
}); |
Oops, something went wrong.