odyssey-frontend / src /lib /components /ApiKeyInput.svelte
Fraser's picture
Initial backend setup with Gradio
7ac86fa
<script lang="ts">
import { setApiKey } from '$lib/stores/story';
export let onApiKeySet: ((apiKey: string) => void) | undefined = undefined;
let inputKey = '';
let isSet = false;
function handleSubmit(event: Event) {
event.preventDefault();
if (inputKey.trim()) {
setApiKey(inputKey.trim());
isSet = true;
onApiKeySet?.(inputKey.trim());
}
}
function handleReset() {
inputKey = '';
isSet = false;
setApiKey('');
}
</script>
<div class="api-key-input">
{#if !isSet}
<div class="input-container">
<h2>Enter OpenAI API Key</h2>
<p class="description">
Your API key is used to generate the story and videos with GPT-4 and Sora.
It's stored only in your browser and never sent to our servers.
</p>
<form on:submit={handleSubmit}>
<input
type="password"
bind:value={inputKey}
placeholder="sk-..."
class="api-key-field"
required
/>
<button type="submit" class="submit-button">
Start Adventure
</button>
</form>
<p class="info">
Don't have an API key? Get one at <a href="https://platform.openai.com/api-keys" target="_blank" rel="noopener">OpenAI Platform</a>
</p>
</div>
{:else}
<div class="key-set">
<p>✓ API Key Set</p>
<button on:click={handleReset} class="reset-button">
Change Key
</button>
</div>
{/if}
</div>
<style>
.api-key-input {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 2rem;
min-height: 300px;
}
.input-container {
max-width: 500px;
width: 100%;
text-align: center;
}
h2 {
margin: 0 0 0.5rem 0;
color: #1a1a1a;
font-size: 1.75rem;
}
.description {
color: #666;
margin: 0 0 2rem 0;
line-height: 1.5;
font-size: 0.95rem;
}
form {
display: flex;
flex-direction: column;
gap: 1rem;
}
.api-key-field {
padding: 0.75rem 1rem;
font-size: 1rem;
border: 2px solid #ddd;
border-radius: 0.5rem;
font-family: 'Monaco', 'Consolas', monospace;
}
.api-key-field:focus {
outline: none;
border-color: #007bff;
}
.submit-button {
padding: 1rem 2rem;
font-size: 1.1rem;
font-weight: 600;
background: #007bff;
color: white;
border: none;
border-radius: 0.5rem;
cursor: pointer;
transition: background 0.2s;
}
.submit-button:hover {
background: #0056b3;
}
.info {
margin-top: 1.5rem;
font-size: 0.85rem;
color: #666;
}
.info a {
color: #007bff;
text-decoration: none;
}
.info a:hover {
text-decoration: underline;
}
.key-set {
display: flex;
align-items: center;
gap: 1rem;
padding: 1rem 1.5rem;
background: #d4edda;
border: 1px solid #c3e6cb;
border-radius: 0.5rem;
color: #155724;
}
.key-set p {
margin: 0;
font-weight: 600;
}
.reset-button {
padding: 0.5rem 1rem;
font-size: 0.9rem;
background: white;
color: #155724;
border: 1px solid #c3e6cb;
border-radius: 0.375rem;
cursor: pointer;
transition: background 0.2s;
}
.reset-button:hover {
background: #f1f1f1;
}
</style>