Test-app/app/routes/app._index.jsx
2026-03-04 13:27:19 +05:30

129 lines
3.8 KiB
JavaScript

import { useLoaderData, Link } from "react-router";
import { boundary } from "@shopify/shopify-app-react-router/server";
import { authenticate } from "../shopify.server";
import { getQRCodes } from "../models/QRCode.server";
export async function loader({ request }) {
const { admin, session } = await authenticate.admin(request);
const qrCodes = await getQRCodes(session.shop, admin.graphql);
return {
qrCodes,
};
}
const EmptyQRCodeState = () => (
<s-section accessibilityLabel="Empty state section">
<s-grid gap="base" justifyItems="center" paddingBlock="large-400">
<s-box maxInlineSize="200px" maxBlockSize="200px">
<s-image
aspectRatio="1/0.5"
src="https://cdn.shopify.com/s/files/1/0262/4071/2726/files/emptystate-files.png"
alt="A stylized graphic of a document"
/>
</s-box>
<s-grid justifyItems="center" maxBlockSize="450px" maxInlineSize="450px">
<s-heading>Create unique QR codes for your products</s-heading>
<s-paragraph>
Allow customers to scan codes and buy products using their phones.
</s-paragraph>
<s-stack
gap="small-200"
justifyContent="center"
padding="base"
paddingBlockEnd="none"
direction="inline"
>
<s-button href="/app/qrcodes/new" variant="primary">
Create QR code
</s-button>
</s-stack>
</s-grid>
</s-grid>
</s-section>
);
function truncate(str, { length = 25 } = {}) {
if (!str) return "";
if (str.length <= length) return str;
return str.slice(0, length) + "…";
}
const QRTable = ({ qrCodes }) => (
<s-section padding="none" accessibilityLabel="QRCode table">
<s-table>
<s-table-header-row>
<s-table-header listSlot="primary">Title</s-table-header>
<s-table-header>Product</s-table-header>
<s-table-header>Date created</s-table-header>
<s-table-header>Scans</s-table-header>
</s-table-header-row>
<s-table-body>
{qrCodes.map((qrCode) => (
<QRTableRow key={qrCode.id} qrCode={qrCode} />
))}
</s-table-body>
</s-table>
</s-section>
);
const QRTableRow = ({ qrCode }) => (
<s-table-row id={qrCode.id} position={qrCode.id}>
<s-table-cell>
<s-stack direction="inline" gap="small" alignItems="center">
<s-clickable
href={`/app/qrcodes/${qrCode.id}`}
accessibilityLabel={`Go to the product page for ${qrCode.productTitle}`}
border="base"
borderRadius="base"
overflow="hidden"
inlineSize="20px"
blockSize="20px"
>
{qrCode.productImage ? (
<s-image objectFit="cover" src={qrCode.productImage}></s-image>
) : (
<s-icon size="large" type="image" />
)}
</s-clickable>
<s-link href={`/app/qrcodes/${qrCode.id}`}>
{truncate(qrCode.title)}
</s-link>
</s-stack>
</s-table-cell>
<s-table-cell>
{qrCode.productDeleted ? (
<s-badge icon="alert-diamond" tone="critical">
Product has been deleted
</s-badge>
) : (
truncate(qrCode.productTitle)
)}
</s-table-cell>
<s-table-cell>{new Date(qrCode.createdAt).toDateString()}</s-table-cell>
<s-table-cell>{qrCode.scans}</s-table-cell>
</s-table-row>
);
export default function Index() {
const { qrCodes } = useLoaderData();
return (
<s-page heading="QR codes">
<s-link slot="secondary-actions" href="/app/qrcodes/new">
Create QR code
</s-link>
{qrCodes.length === 0 ? (
<EmptyQRCodeState />
) : (
<QRTable qrCodes={qrCodes} />
)}
</s-page>
);
}
export const headers = (headersArgs) => {
return boundary.headers(headersArgs);
};