Skip to main content

max / makenotwork

8.4 KB · 186 lines History Blame Raw
1 {% extends "base.html" %}
2
3 {% block title %}New Project - Makenot.work{% endblock %}
4 {% block body_attrs %} class="padded-page"{% endblock %}
5
6 {% block head %}
7 <link rel="stylesheet" href="/static/wizard.css">
8 {% endblock %}
9
10 {% block content %}
11 {% include "partials/site_header.html" %}
12
13 <div class="wizard-layout">
14 <aside class="wizard-sidebar">
15 <h2 class="subtitle-h2">New Project</h2>
16 {% include "wizards/partials/step_nav.html" %}
17 </aside>
18
19 <div class="wizard-content" id="wizard-step">
20 <div class="wizard-step">
21 <h2 class="subtitle-h2">Basics</h2>
22 <p class="step-description">Name your project, set a URL name, and choose the tools you will use.</p>
23
24 <form hx-post="/dashboard/new-project/step/basics"
25 hx-target="#wizard-step" hx-swap="innerHTML">
26 <div class="form-group">
27 <label for="wiz-title">Title</label>
28 <input type="text" id="wiz-title" name="title" required
29 placeholder="My Awesome Project" autocomplete="off">
30 </div>
31
32 <div class="form-group">
33 <label for="wiz-slug">URL name</label>
34 <input type="text" id="wiz-slug" name="slug" pattern="[a-z0-9-]+"
35 title="Letters, numbers, and hyphens only"
36 placeholder="my-project" required autocomplete="off"
37 hx-post="/api/validate/project-slug"
38 hx-trigger="keyup changed delay:500ms"
39 hx-target="#slug-status"
40 hx-indicator="#slug-spinner">
41 <div class="hint">Letters, numbers, hyphens only. This is your project URL.</div>
42 <span id="slug-spinner" class="htmx-indicator wizard-field-spinner">Checking...</span>
43 <span id="slug-status"></span>
44 </div>
45
46 <div class="form-group">
47 <label>What tools will you use?</label>
48 <div class="hint wizard-hint-gap-md">Select all that apply. You can change these anytime.</div>
49 <div class="type-grid">
50 {% for (value, label, desc) in project_features %}
51 <label class="type-card">
52 <input type="checkbox" name="features" value="{{ value }}">
53 <span class="type-card-inner">
54 <span class="type-card-label">{{ label }}</span>
55 <span class="type-card-desc">{{ desc }}</span>
56 </span>
57 </label>
58 {% endfor %}
59 </div>
60 </div>
61
62 <div class="form-group">
63 <label for="wiz-category">Category</label>
64 <div class="suggestion-input" id="category-suggestion">
65 <input type="text" id="wiz-category" name="category"
66 placeholder="What kind of project is this?"
67 autocomplete="off">
68 <div class="suggestion-dropdown" id="category-dropdown"></div>
69 </div>
70 <div class="hint">Choose an existing category or type a new one.</div>
71 </div>
72
73 <div class="form-group">
74 <label for="wiz-description">Description</label>
75 <textarea id="wiz-description" name="description" rows="4"
76 placeholder="Describe your project..."></textarea>
77 </div>
78
79 <div class="form-group">
80 <label>AI Disclosure</label>
81 <div class="hint wizard-hint-gap-sm">How was AI used in creating this project's content?</div>
82 <div class="wizard-radio-group">
83 <label class="wizard-radio-option">
84 <input type="radio" name="ai_tier" value="handmade" required>
85 <span><strong>Handmade</strong> — no AI tools used in content creation</span>
86 </label>
87 <label class="wizard-radio-option">
88 <input type="radio" name="ai_tier" value="assisted" required>
89 <span><strong>AI-Assisted</strong> — AI tools used as part of the creative process</span>
90 </label>
91 <label class="wizard-radio-option">
92 <input type="radio" name="ai_tier" value="generated" required>
93 <span><strong>AI-Generated</strong> — content primarily generated by AI</span>
94 </label>
95 </div>
96 </div>
97
98 <div class="form-group hidden" id="ai-disclosure-group">
99 <label for="wiz-ai-disclosure">Disclosure Details</label>
100 <textarea id="wiz-ai-disclosure" name="ai_disclosure" rows="2"
101 placeholder="Describe how AI was used..."></textarea>
102 </div>
103
104 <div class="wizard-actions">
105 <a href="/dashboard" class="btn-secondary">Cancel</a>
106 <button type="submit" class="btn-primary">Continue</button>
107 </div>
108 </form>
109 </div>
110 </div>
111 </div>
112 {% endblock %}
113
114 {% block scripts %}
115 <script src="/static/upload.js"></script>
116 <script src="/static/wizard.js"></script>
117 <script>
118 (function() {
119 var input = document.getElementById('wiz-category');
120 var dropdown = document.getElementById('category-dropdown');
121 if (!input || !dropdown) return;
122 var debounce;
123
124 function showDropdown(items, query) {
125 dropdown.innerHTML = '';
126 items.forEach(function(c) {
127 var div = document.createElement('div');
128 div.className = 'suggestion-item';
129 div.textContent = c.name;
130 div.addEventListener('mousedown', function(e) {
131 e.preventDefault();
132 input.value = c.name;
133 dropdown.classList.remove('open');
134 });
135 dropdown.appendChild(div);
136 });
137 var q = query.trim();
138 if (q.length > 0 && !items.some(function(c) { return c.name.toLowerCase() === q.toLowerCase(); })) {
139 var create = document.createElement('div');
140 create.className = 'suggestion-item suggestion-create';
141 create.textContent = 'Create: ' + q;
142 create.addEventListener('mousedown', function(e) {
143 e.preventDefault();
144 input.value = q;
145 dropdown.classList.remove('open');
146 });
147 dropdown.appendChild(create);
148 }
149 if (dropdown.children.length > 0) {
150 dropdown.classList.add('open');
151 } else {
152 dropdown.classList.remove('open');
153 }
154 }
155
156 input.addEventListener('input', function() {
157 clearTimeout(debounce);
158 var q = input.value.trim();
159 if (q.length < 1) { dropdown.classList.remove('open'); return; }
160 debounce = setTimeout(function() {
161 fetch('/api/categories/search?q=' + encodeURIComponent(q))
162 .then(function(r) { return r.json(); })
163 .then(function(cats) { showDropdown(cats, q); })
164 .catch(function() {});
165 }, 200);
166 });
167
168 input.addEventListener('focus', function() {
169 if (dropdown.children.length > 0) dropdown.classList.add('open');
170 });
171
172 input.addEventListener('blur', function() {
173 setTimeout(function() { dropdown.classList.remove('open'); }, 150);
174 });
175
176 // AI tier toggle
177 document.querySelectorAll('input[name="ai_tier"]').forEach(function(r) {
178 r.addEventListener('change', function() {
179 var group = document.getElementById('ai-disclosure-group');
180 group.classList.toggle('hidden', this.value !== 'assisted');
181 });
182 });
183 })();
184 </script>
185 {% endblock %}
186