aboutsummaryrefslogtreecommitdiff
path: root/examples/ssr/src/pages
diff options
context:
space:
mode:
Diffstat (limited to 'examples/ssr/src/pages')
-rw-r--r--examples/ssr/src/pages/api/cart.ts38
-rw-r--r--examples/ssr/src/pages/api/products.ts5
-rw-r--r--examples/ssr/src/pages/api/products/[id].ts16
-rw-r--r--examples/ssr/src/pages/cart.astro51
-rw-r--r--examples/ssr/src/pages/index.astro33
-rw-r--r--examples/ssr/src/pages/login.astro58
-rw-r--r--examples/ssr/src/pages/login.form.async.ts14
-rw-r--r--examples/ssr/src/pages/login.form.ts16
-rw-r--r--examples/ssr/src/pages/products/[id].astro45
9 files changed, 276 insertions, 0 deletions
diff --git a/examples/ssr/src/pages/api/cart.ts b/examples/ssr/src/pages/api/cart.ts
new file mode 100644
index 000000000..8d64ec7d8
--- /dev/null
+++ b/examples/ssr/src/pages/api/cart.ts
@@ -0,0 +1,38 @@
+import type { APIContext } from 'astro';
+import { userCartItems } from '../../models/session';
+
+export function GET({ cookies }: APIContext) {
+ let userId = cookies.get('user-id')?.value;
+
+ if (!userId || !userCartItems.has(userId)) {
+ return Response.json({ items: [] });
+ }
+ let items = userCartItems.get(userId);
+ let array = Array.from(items.values());
+
+ return Response.json({ items: array });
+}
+
+interface AddToCartItem {
+ id: number;
+ name: string;
+}
+
+export async function POST({ cookies, request }: APIContext) {
+ const item: AddToCartItem = await request.json();
+
+ let userId = cookies.get('user-id')?.value;
+
+ if (!userCartItems.has(userId)) {
+ userCartItems.set(userId, new Map());
+ }
+
+ let cart = userCartItems.get(userId);
+ if (cart.has(item.id)) {
+ cart.get(item.id).count++;
+ } else {
+ cart.set(item.id, { id: item.id, name: item.name, count: 1 });
+ }
+
+ return Response.json({ ok: true });
+}
diff --git a/examples/ssr/src/pages/api/products.ts b/examples/ssr/src/pages/api/products.ts
new file mode 100644
index 000000000..8bf02a03d
--- /dev/null
+++ b/examples/ssr/src/pages/api/products.ts
@@ -0,0 +1,5 @@
+import { products } from '../../models/db';
+
+export function GET() {
+ return new Response(JSON.stringify(products));
+}
diff --git a/examples/ssr/src/pages/api/products/[id].ts b/examples/ssr/src/pages/api/products/[id].ts
new file mode 100644
index 000000000..f0f6fa89f
--- /dev/null
+++ b/examples/ssr/src/pages/api/products/[id].ts
@@ -0,0 +1,16 @@
+import { productMap } from '../../../models/db';
+import type { APIContext } from 'astro';
+
+export function GET({ params }: APIContext) {
+ const id = Number(params.id);
+ if (productMap.has(id)) {
+ const product = productMap.get(id);
+
+ return new Response(JSON.stringify(product));
+ } else {
+ return new Response(null, {
+ status: 400,
+ statusText: 'Not found',
+ });
+ }
+}
diff --git a/examples/ssr/src/pages/cart.astro b/examples/ssr/src/pages/cart.astro
new file mode 100644
index 000000000..40e5cf126
--- /dev/null
+++ b/examples/ssr/src/pages/cart.astro
@@ -0,0 +1,51 @@
+---
+import Header from '../components/Header.astro';
+import Container from '../components/Container.astro';
+import { getCart } from '../api';
+
+if (!Astro.cookies.get('user-id')) {
+ return Astro.redirect('/');
+}
+
+// They must be logged in.
+
+const user = { name: 'test' }; // getUser?
+const cart = await getCart(Astro.request);
+---
+
+<html lang="en">
+ <head>
+ <title>Cart | Online Store</title>
+ <style>
+ h1 {
+ font-size: 36px;
+ }
+ </style>
+ </head>
+ <body>
+ <Header />
+
+ <Container tag="main">
+ <h1>Cart</h1>
+ <p>Hi {user.name}! Here are your cart items:</p>
+ <table>
+ <thead>
+ <tr>
+ <th>Item</th>
+ <th>Count</th>
+ </tr>
+ </thead>
+ <tbody>
+ {
+ cart.items.map((item) => (
+ <tr>
+ <td>{item.name}</td>
+ <td>{item.count}</td>
+ </tr>
+ ))
+ }
+ </tbody>
+ </table>
+ </Container>
+ </body>
+</html>
diff --git a/examples/ssr/src/pages/index.astro b/examples/ssr/src/pages/index.astro
new file mode 100644
index 000000000..1ce70bc81
--- /dev/null
+++ b/examples/ssr/src/pages/index.astro
@@ -0,0 +1,33 @@
+---
+import Header from '../components/Header.astro';
+import Container from '../components/Container.astro';
+import ProductListing from '../components/ProductListing.astro';
+import { getProducts } from '../api';
+import '../styles/common.css';
+
+const products = await getProducts(Astro.request);
+---
+
+<html lang="en">
+ <head>
+ <title>Online Store</title>
+ <style>
+ h1 {
+ font-size: 36px;
+ }
+
+ .product-listing-title {
+ text-align: center;
+ }
+ </style>
+ </head>
+ <body>
+ <Header />
+
+ <Container tag="main">
+ <ProductListing products={products}>
+ <h2 class="product-listing-title" slot="title">Product Listing</h2>
+ </ProductListing>
+ </Container>
+ </body>
+</html>
diff --git a/examples/ssr/src/pages/login.astro b/examples/ssr/src/pages/login.astro
new file mode 100644
index 000000000..030838a64
--- /dev/null
+++ b/examples/ssr/src/pages/login.astro
@@ -0,0 +1,58 @@
+---
+import Header from '../components/Header.astro';
+import Container from '../components/Container.astro';
+---
+
+<html lang="en">
+ <head>
+ <title>Online Store</title>
+ <style>
+ h1 {
+ font-size: 36px;
+ }
+ </style>
+
+ <script type="module" is:inline>
+ document.addEventListener('DOMContentLoaded', () => {
+ const form = document.querySelector('form');
+ if (!form) throw new Error('Form not found');
+ form.addEventListener('submit', (e) => {
+ e.preventDefault();
+ const formData = new FormData(form);
+ const data = Object.fromEntries(formData);
+
+ fetch('/login.form.async', {
+ method: 'POST',
+ body: JSON.stringify(data),
+ })
+ .then((res) => res.json())
+ .then(() => {
+ const result = document.querySelector('#result');
+ if (result) {
+ result.innerHTML =
+ 'Progressive login was successful! you will be redirected to the store in 3 seconds';
+ setTimeout(() => (location.href = '/'), 3000);
+ }
+ });
+ });
+ });
+ </script>
+ </head>
+ <body>
+ <Header />
+
+ <Container tag="main">
+ <h1>Login</h1>
+ <form action="/login.form" method="POST">
+ <label for="name">Name</label>
+ <input type="text" name="name" />
+
+ <label for="password">Password</label>
+ <input type="password" name="password" />
+
+ <input type="submit" value="Submit" />
+ </form>
+ <div id="result"></div>
+ </Container>
+ </body>
+</html>
diff --git a/examples/ssr/src/pages/login.form.async.ts b/examples/ssr/src/pages/login.form.async.ts
new file mode 100644
index 000000000..94020d9c9
--- /dev/null
+++ b/examples/ssr/src/pages/login.form.async.ts
@@ -0,0 +1,14 @@
+import type { APIContext, APIRoute } from 'astro';
+
+export const POST: APIRoute = ({ cookies }: APIContext) => {
+ // add a new cookie
+ cookies.set('user-id', '1', {
+ path: '/',
+ maxAge: 2592000,
+ });
+
+ return Response.json({
+ ok: true,
+ user: 1,
+ });
+};
diff --git a/examples/ssr/src/pages/login.form.ts b/examples/ssr/src/pages/login.form.ts
new file mode 100644
index 000000000..f3cd50db4
--- /dev/null
+++ b/examples/ssr/src/pages/login.form.ts
@@ -0,0 +1,16 @@
+import type { APIContext } from 'astro';
+
+export function POST({ cookies }: APIContext) {
+ // add a new cookie
+ cookies.set('user-id', '1', {
+ path: '/',
+ maxAge: 2592000,
+ });
+
+ return new Response(null, {
+ status: 301,
+ headers: {
+ Location: '/',
+ },
+ });
+}
diff --git a/examples/ssr/src/pages/products/[id].astro b/examples/ssr/src/pages/products/[id].astro
new file mode 100644
index 000000000..e90900e45
--- /dev/null
+++ b/examples/ssr/src/pages/products/[id].astro
@@ -0,0 +1,45 @@
+---
+import Header from '../../components/Header.astro';
+import Container from '../../components/Container.astro';
+import AddToCart from '../../components/AddToCart.svelte';
+import { getProduct } from '../../api';
+import '../../styles/common.css';
+
+const id = Number(Astro.params.id);
+const product = await getProduct(Astro.request, id);
+---
+
+<html lang="en">
+ <head>
+ <title>{product.name} | Online Store</title>
+ <style>
+ h2 {
+ text-align: center;
+ font-size: 3.5rem;
+ }
+
+ figure {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ }
+
+ img {
+ width: 400px;
+ }
+ </style>
+ </head>
+ <body>
+ <Header />
+
+ <Container tag="article">
+ <h2>{product.name}</h2>
+ <figure>
+ <img src={product.image} />
+ <figcaption>
+ <AddToCart client:idle id={id} name={product.name} />
+ <p>Description here...</p>
+ </figcaption>
+ </figure>
+ </Container>
+ </body>
+</html>