Skip to content

Commit 2ad66c3

Browse files
committed
feat: add prop documentation field
Adding prop documentation field in componentPage schema ISSUES CLOSED: #4598
1 parent 785bd8d commit 2ad66c3

File tree

8 files changed

+134
-2
lines changed

8 files changed

+134
-2
lines changed

ny-portal/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"@portabletext/react": "^3.2.1",
3030
"@sanity/client": "^6.28.1",
3131
"@sanity/image-url": "^1.1.0",
32+
"@sanity/ui": "^2.14.3",
3233
"@sanity/vision": "^3.76.3",
3334
"@types/mdx": "^2.0.13",
3435
"clsx": "^2.1.1",

ny-portal/src/app/(frontend)/komponenter/[slug]/page.tsx

+5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import PortableTextRenderer from "@/components/portable-text";
2+
import { PropDocumentation } from "@/components/prop-documentation/PropDocumentation";
23
import { client } from "@/sanity/client";
34
import { componentPageBySlugQuery } from "@/sanity/queries/componentPage";
45

@@ -18,6 +19,10 @@ export default async function Page({
1819
{data?.lede && <PortableTextRenderer value={data.lede} />}
1920

2021
{data?.content && <PortableTextRenderer value={data.content} />}
22+
23+
{data?.component_folder && (
24+
<PropDocumentation component={data.component_folder} />
25+
)}
2126
</>
2227
);
2328
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import fs from "fs";
2+
import path from "path";
3+
import { NextResponse } from "next/server";
4+
import glob from "tiny-glob";
5+
6+
const packageRoot = path.resolve(
7+
process.cwd(),
8+
"..",
9+
"packages",
10+
"jokul",
11+
"src",
12+
"components",
13+
);
14+
15+
export async function GET() {
16+
try {
17+
const paths = (await glob("*", { cwd: packageRoot })).filter(
18+
(component) =>
19+
fs.statSync(path.resolve(packageRoot, component)).isDirectory(),
20+
);
21+
22+
const formattedOptions = paths.sort().map((component) => ({
23+
title: component,
24+
value: component,
25+
}));
26+
27+
return NextResponse.json(formattedOptions);
28+
} catch (error) {
29+
console.error("Error reading component folders:", error);
30+
return NextResponse.json(
31+
{ error: "Failed to read component folders" },
32+
{ status: 500 },
33+
);
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { Select } from "@sanity/ui";
2+
import React, { useEffect, useState } from "react";
3+
import { set, unset } from "sanity";
4+
import type { StringInputProps } from "sanity";
5+
6+
type ComponentFolderOption = {
7+
title: string;
8+
value: string;
9+
};
10+
11+
export function ComponentFolderInput(props: StringInputProps) {
12+
const { value, onChange } = props;
13+
const [options, setOptions] = useState<ComponentFolderOption[]>([]);
14+
const [loading, setLoading] = useState<boolean>(true);
15+
16+
const handleChange = React.useCallback(
17+
(event: React.FormEvent<HTMLSelectElement> | undefined) => {
18+
const value = event?.currentTarget.value;
19+
20+
// If the selected option has a value,
21+
// it will be written to the document
22+
// otherwise the field will be cleared
23+
onChange(value ? set(value) : unset());
24+
},
25+
[onChange],
26+
);
27+
28+
useEffect(() => {
29+
async function fetchData() {
30+
try {
31+
const componentsResult = await fetch("/api/component-folders", {
32+
cache: "no-store",
33+
});
34+
35+
const components: ComponentFolderOption[] =
36+
await componentsResult.json();
37+
38+
const formattedOptions: ComponentFolderOption[] =
39+
components.map(({ title, value }) => ({
40+
title,
41+
value,
42+
}));
43+
44+
setOptions(formattedOptions);
45+
} catch (error) {
46+
console.error("Failed to fetch component folders:", error);
47+
} finally {
48+
setLoading(false);
49+
}
50+
}
51+
52+
fetchData();
53+
}, []);
54+
55+
return (
56+
<Select
57+
onChange={handleChange}
58+
disabled={loading || options.length === 0}
59+
value={value}
60+
>
61+
<option value="">-- Velg komponent --</option>
62+
{options.map((option) => (
63+
<option key={option.value} value={option.value}>
64+
{option.title}
65+
</option>
66+
))}
67+
</Select>
68+
);
69+
}

ny-portal/src/sanity/extract.json

+7
Original file line numberDiff line numberDiff line change
@@ -1069,6 +1069,13 @@
10691069
}
10701070
},
10711071
"optional": true
1072+
},
1073+
"component_folder": {
1074+
"type": "objectAttribute",
1075+
"value": {
1076+
"type": "string"
1077+
},
1078+
"optional": true
10721079
}
10731080
}
10741081
},

ny-portal/src/sanity/schemas/componentPage.ts

+10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { defineField, defineType } from "sanity";
2+
import { ComponentFolderInput } from "../components/ComponentFolderInput";
23

34
const MAX_LENGTH = 70;
45

@@ -36,5 +37,14 @@ export const componentPage = defineType({
3637
type: "array",
3738
of: [{ type: "block" }],
3839
}),
40+
defineField({
41+
name: "component_folder",
42+
title: "Komponentmappe",
43+
type: "string",
44+
components: {
45+
input: ComponentFolderInput,
46+
},
47+
validation: (Rule) => Rule.required(),
48+
}),
3949
],
4050
});

ny-portal/src/sanity/types.ts

+2
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ export type Jokul_componentPage = {
185185
_type: "block";
186186
_key: string;
187187
}>;
188+
component_folder?: string;
188189
};
189190

190191
export type Slug = {
@@ -276,6 +277,7 @@ export type ComponentPageBySlugQueryResult = {
276277
_type: "block";
277278
_key: string;
278279
}>;
280+
component_folder?: string;
279281
} | null;
280282

281283
// Query TypeMap

pnpm-lock.yaml

+5-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)