Packages
AI module for PhoenixKit — endpoints, prompts, completions, and usage tracking
Current section
Files
Jump to
Current section
Files
lib/phoenix_kit_ai/web/prompt_form.html.heex
<div class="flex flex-col w-full px-4 py-6">
<.admin_page_header
title={@page_title}
subtitle={gettext("Create reusable prompts with variable substitution")}
/>
<%!-- Form Content (capped at 5xl — wide enough for prompt content
textareas to be readable, narrow enough that single-line inputs
don't stretch absurdly on ultrawide displays). --%>
<div class="max-w-5xl mx-auto w-full">
<%!-- Form --%>
<div class="card bg-base-200">
<div class="card-body">
<.form for={@form} phx-change="validate" phx-submit="save" class="space-y-5">
<%!-- Name --%>
<.input
field={@form[:name]}
type="text"
label={gettext("Name") <> " *"}
placeholder={gettext("e.g., Translator, Code Reviewer")}
phx-debounce="1000"
required
/>
<%!-- Slug — auto-generated, read-only --%>
<.input
field={@form[:slug]}
type="text"
label={gettext("Slug")}
class="font-mono text-sm bg-base-300"
placeholder={gettext("auto-generated-slug")}
readonly
/>
<%!-- Description --%>
<.textarea
field={@form[:description]}
errors={
Enum.map(@form[:description].errors,
&PhoenixKitWeb.Components.Core.Input.translate_error/1)
}
label={gettext("Description (Optional)")}
rows="2"
placeholder={gettext("Brief description of what this prompt does...")}
/>
<%!-- System Prompt --%>
<div>
<.textarea
field={@form[:system_prompt]}
errors={
Enum.map(@form[:system_prompt].errors,
&PhoenixKitWeb.Components.Core.Input.translate_error/1)
}
label={gettext("System Prompt (Optional)")}
rows="4"
class="font-mono text-sm"
placeholder={
gettext("Optional system instructions for the AI model.\n\nExample:\nYou are a professional {{Role}} who always responds in {{Language}}.")
}
/>
<p class="text-sm text-base-content/60 mt-1">
{gettext("Sent as the system message before the user prompt. Supports {{variables}} too.")}
</p>
</div>
<%!-- Content --%>
<.textarea
field={@form[:content]}
errors={
Enum.map(@form[:content].errors,
&PhoenixKitWeb.Components.Core.Input.translate_error/1)
}
label={gettext("Content") <> " *"}
rows="8"
class="font-mono text-sm"
placeholder={
gettext("Enter your prompt template...\n\nUse {{VariableName}} for dynamic content.\n\nExample:\nTranslate the following text to {{Language}}:\n\n{{Text}}")
}
required
/>
<%!-- Extracted Variables Preview --%>
<%= if length(@extracted_variables) > 0 do %>
<div class="alert">
<.icon name="hero-variable" class="w-5 h-5" />
<div>
<div class="font-medium">{gettext("Detected Variables")}</div>
<div class="flex flex-wrap gap-2 mt-1">
<%= for var <- @extracted_variables do %>
<span class="badge badge-primary badge-outline font-mono">
{"{{#{var}}}"}
</span>
<% end %>
</div>
</div>
</div>
<% end %>
<%!-- Enabled Toggle — stylised, kept as raw HTML --%>
<div>
<label class="flex items-center gap-3 cursor-pointer">
<input
type="checkbox"
name="prompt[enabled]"
value="true"
checked={@form[:enabled].value != false}
class="checkbox checkbox-primary"
/>
<span class="font-medium">{gettext("Enabled")}</span>
</label>
<p class="text-sm text-base-content/60 mt-1 ml-8">
{gettext("Disabled prompts cannot be used via the API")}
</p>
</div>
<.form_actions
class="pt-4 gap-2"
cancel_to={PhoenixKitAI.Routes.ai_path() <> "/prompts"}
submit_icon="hero-check"
submit_label={
if @prompt, do: gettext("Update Prompt"), else: gettext("Create Prompt")
}
/>
</.form>
</div>
</div>
<.form_section
title={gettext("Variable Syntax")}
icon="hero-question-mark-circle"
class="bg-base-200 mt-6"
>
<div class="text-sm space-y-4">
<div>
<p class="mb-2">{gettext("Use double curly braces for variables:")}</p>
<div class="bg-base-300 p-3 rounded font-mono text-xs">
Translate to {"{{Language}}"}:<br />
{"{{Text}}"}
</div>
</div>
<div>
<p class="font-medium mb-1">{gettext("Naming rules:")}</p>
<ul class="list-disc list-inside text-base-content/70 space-y-1">
<li>
{gettext("Use letters, numbers, and underscores only —")}
<span class="text-error">{gettext("no spaces")}</span>
</li>
<li>
<code class="bg-base-300 px-1 rounded">{"{{UserLanguage}}"}</code>
{gettext("or")}
<code class="bg-base-300 px-1 rounded">{"{{user_language}}"}</code>
{gettext("— both work")}
</li>
<li>
<code class="bg-base-300 px-1 rounded">{"{{User Language}}"}</code>
{gettext("— won't be detected as a variable")}
</li>
</ul>
</div>
<div>
<p class="font-medium mb-1">{gettext("Missing variables:")}</p>
<p class="text-base-content/70">
{gettext("If a variable isn't provided when the prompt is used, it stays as-is in the output (e.g.,")}
<code class="bg-base-300 px-1 rounded">{"{{Language}}"}</code>
{gettext("remains unchanged).")}
</p>
</div>
</div>
</.form_section>
</div>
</div>