Skip to content

Commit e574daf

Browse files
Add saving to the prompt engineering exercise
1 parent 0b95427 commit e574daf

File tree

10 files changed

+516
-40
lines changed

10 files changed

+516
-40
lines changed

workshop-ui/package-lock.json

Lines changed: 58 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

workshop-ui/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"react-dom": "^19.1.1",
2929
"react-highlight": "^0.15.0",
3030
"react-markdown": "^10.1.0",
31+
"react-qr-code": "^2.0.18",
3132
"remark-gfm": "^4.0.1",
3233
"zod": "^3.25.76"
3334
},
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { NextRequest, NextResponse } from 'next/server';
2+
import { getAppSessionFromRequest, validateAppSession } from '@/lib/session';
3+
import { readPrompt } from '@/lib/promptService';
4+
5+
/**
6+
* @route GET /api/system-prompts/[id]
7+
* @desc Get a system prompt by ID
8+
* @response 200 { message: string, url: string } or 400 { error: string } or 401 { error: string } or 501 { error: string }
9+
* @access Protected (any authenticated user/workshop)
10+
*/
11+
export async function GET(
12+
request: NextRequest,
13+
{ params }: { params: Promise<{ id: string }> }
14+
) {
15+
try {
16+
// Validate authentication
17+
const nextResponse = NextResponse.next();
18+
const appSession = await getAppSessionFromRequest(request, nextResponse);
19+
if (!await validateAppSession(appSession)) {
20+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
21+
}
22+
23+
const { id } = await params;
24+
if (!id) {
25+
return NextResponse.json({ error: 'Invalid Request' }, { status: 400 });
26+
}
27+
// Get system prompt
28+
const prompt = await readPrompt(id);
29+
if (!prompt || !prompt.content) {
30+
return NextResponse.json({ error: 'Prompt not found' }, { status: 404 });
31+
}
32+
33+
return NextResponse.json({ prompt }, { status: 200 });
34+
} catch (error) {
35+
console.error('Error fetching system prompt:', error);
36+
return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 });
37+
}
38+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { NextRequest, NextResponse } from 'next/server';
2+
import { generateMetadata } from '@/lib/promptService';
3+
import { getAppSessionFromRequest, validateAppSession } from '@/lib/session';
4+
5+
/**
6+
* @route POST /api/system-prompts/save
7+
* @desc Save the current system prompt to Azure Blob Storage
8+
* @body { prompt: string }
9+
* @response 200 { message: string, url: string } or 400 { error: string } or 401 { error: string } or 501 { error: string }
10+
* @access Protected (any authenticated user/workshop)
11+
*/
12+
export async function POST(
13+
request: NextRequest,
14+
{ params }: { params: Promise<{ id: string }> }
15+
) {
16+
try {
17+
// Validate authentication
18+
const nextResponse = NextResponse.next();
19+
const appSession = await getAppSessionFromRequest(request, nextResponse);
20+
if (!await validateAppSession(appSession)) {
21+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
22+
}
23+
24+
const body = await request.json();
25+
const { id } = body;
26+
if (!id) {
27+
return NextResponse.json({ error: 'Invalid Request' }, { status: 400 });
28+
}
29+
await generateMetadata(id);
30+
31+
return NextResponse.json({ message: 'System prompt saved successfully', id }, { status: 200 });
32+
} catch (error) {
33+
console.error('Error generating metadata:', error);
34+
return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 });
35+
}
36+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { NextRequest, NextResponse } from 'next/server';
2+
import { savePromptToBlobStorage } from '@/lib/promptService';
3+
import { getAppSessionFromRequest, validateAppSession } from '@/lib/session';
4+
5+
/**
6+
* @route POST /api/system-prompts/save
7+
* @desc Save the current system prompt to Azure Blob Storage
8+
* @body { prompt: string }
9+
* @response 200 { message: string, url: string } or 400 { error: string } or 401 { error: string } or 501 { error: string }
10+
* @access Protected (any authenticated user/workshop)
11+
*/
12+
export async function POST(
13+
request: NextRequest,
14+
) {
15+
try {
16+
// Validate authentication
17+
const nextResponse = NextResponse.next();
18+
const appSession = await getAppSessionFromRequest(request, nextResponse);
19+
if (!await validateAppSession(appSession)) {
20+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
21+
}
22+
23+
const body = await request.json();
24+
const { prompt } = body;
25+
26+
if (!prompt || typeof prompt !== 'string' || prompt.trim().length === 0) {
27+
return NextResponse.json({ error: 'Invalid prompt' }, { status: 400 });
28+
}
29+
30+
const { id } = await savePromptToBlobStorage(prompt);
31+
if (!id) {
32+
return NextResponse.json({ error: 'Failed to save prompt' }, { status: 500 });
33+
}
34+
35+
return NextResponse.json({ message: 'System prompt saved successfully', id }, { status: 200 });
36+
} catch (error) {
37+
console.error('Error saving system prompt:', error);
38+
return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 });
39+
}
40+
}

workshop-ui/src/app/prompt-engineering/page.module.css

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,10 @@
198198
align-items: center;
199199
justify-content: center;
200200

201+
svg {
202+
flex: none;
203+
}
204+
201205
&:disabled {
202206
background-color: #ccc;
203207
cursor: not-allowed;
@@ -219,6 +223,17 @@
219223
width: 100%;
220224
border-radius: 0;
221225

226+
&:disabled {
227+
background-color: #ccc;
228+
cursor: not-allowed;
229+
}
230+
}
231+
232+
&.saveButton {
233+
background-color: #ffc107;
234+
width: 100%;
235+
border-radius: 0;
236+
222237
&:disabled {
223238
background-color: #ccc;
224239
cursor: not-allowed;
@@ -245,4 +260,24 @@
245260
color: #721c24;
246261
}
247262
}
263+
}
264+
265+
.qrContainer {
266+
margin-top: 12px;
267+
display: flex;
268+
flex-direction: column;
269+
align-items: center;
270+
271+
.qrCode {
272+
background: #fff;
273+
padding: 12px;
274+
border-radius: 8px;
275+
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
276+
}
277+
278+
.qrLabel {
279+
font-size: 12px;
280+
color: #666;
281+
margin-top: 8px;
282+
}
248283
}

0 commit comments

Comments
 (0)