···
1
+
import { css, html, LitElement } from "lit";
2
+
import { customElement, property, state } from "lit/decorators.js";
4
+
@customElement("class-registration-modal")
5
+
export class ClassRegistrationModal extends LitElement {
6
+
@property({ type: Boolean }) open = false;
7
+
@state() classCode = "";
8
+
@state() isSubmitting = false;
11
+
static override styles = css`
22
+
background: rgba(0, 0, 0, 0.5);
24
+
align-items: center;
25
+
justify-content: center;
31
+
background: var(--background);
32
+
border: 2px solid var(--secondary);
33
+
border-radius: 12px;
37
+
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
42
+
justify-content: space-between;
43
+
align-items: center;
44
+
margin-bottom: 1.5rem;
54
+
background: transparent;
63
+
align-items: center;
64
+
justify-content: center;
66
+
transition: all 0.2s;
70
+
background: var(--secondary);
74
+
margin-bottom: 1.5rem;
79
+
margin-bottom: 0.5rem;
82
+
font-size: 0.875rem;
88
+
border: 2px solid var(--secondary);
91
+
font-family: inherit;
92
+
background: var(--background);
94
+
transition: all 0.2s;
95
+
box-sizing: border-box;
96
+
text-transform: uppercase;
101
+
border-color: var(--primary);
105
+
margin-top: 0.5rem;
106
+
font-size: 0.75rem;
107
+
color: var(--paynes-gray);
112
+
font-size: 0.875rem;
113
+
margin-top: 0.5rem;
119
+
margin-top: 1.5rem;
123
+
padding: 0.75rem 1.5rem;
124
+
border: 2px solid var(--primary);
125
+
border-radius: 6px;
129
+
transition: all 0.2s;
130
+
font-family: inherit;
135
+
cursor: not-allowed;
139
+
background: var(--primary);
144
+
.btn-primary:hover:not(:disabled) {
145
+
background: var(--gunmetal);
146
+
border-color: var(--gunmetal);
150
+
background: transparent;
151
+
color: var(--text);
152
+
border-color: var(--secondary);
155
+
.btn-secondary:hover:not(:disabled) {
156
+
border-color: var(--primary);
157
+
color: var(--primary);
161
+
private handleClose() {
162
+
this.classCode = "";
164
+
this.dispatchEvent(new CustomEvent("close"));
167
+
private handleInput(e: Event) {
168
+
this.classCode = (e.target as HTMLInputElement).value.toUpperCase();
172
+
private async handleSubmit(e: Event) {
173
+
e.preventDefault();
175
+
this.isSubmitting = true;
178
+
const response = await fetch("/api/classes/join", {
180
+
headers: { "Content-Type": "application/json" },
181
+
body: JSON.stringify({ class_code: this.classCode.trim() }),
184
+
if (!response.ok) {
185
+
const data = await response.json();
186
+
this.error = data.error || "Failed to join class";
190
+
// Success - notify parent and close
191
+
this.dispatchEvent(new CustomEvent("class-joined"));
192
+
this.handleClose();
194
+
this.error = "Failed to join class. Please try again.";
196
+
this.isSubmitting = false;
200
+
override render() {
201
+
if (!this.open) return html``;
204
+
<div class="modal-overlay" @click=${this.handleClose}>
205
+
<div class="modal" @click=${(e: Event) => e.stopPropagation()}>
206
+
<div class="modal-header">
207
+
<h2 class="modal-title">Register for Class</h2>
208
+
<button class="close-btn" @click=${this.handleClose} type="button">×</button>
211
+
<form @submit=${this.handleSubmit}>
212
+
<div class="form-group">
213
+
<label for="class-code">Class Code</label>
217
+
placeholder="ABC123"
218
+
.value=${this.classCode}
219
+
@input=${this.handleInput}
221
+
?disabled=${this.isSubmitting}
224
+
<div class="helper-text">
225
+
Enter the class code provided by your instructor
227
+
${this.error ? html`<div class="error-message">${this.error}</div>` : ""}
230
+
<div class="modal-actions">
233
+
class="btn-primary"
234
+
?disabled=${this.isSubmitting || !this.classCode.trim()}
236
+
${this.isSubmitting ? "Joining..." : "Join Class"}
240
+
class="btn-secondary"
241
+
@click=${this.handleClose}
242
+
?disabled=${this.isSubmitting}