|
import { client } from "./client.mjs"; |
|
import { html, create, styled } from "./misc.mjs"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const useStore = create((set, get) => ({ |
|
|
|
|
|
|
|
speakers: [], |
|
|
|
setSpeakers: (speakers) => set({ speakers }), |
|
|
|
formData: { |
|
seed: 42, |
|
name: "", |
|
}, |
|
setFormData: (data) => set({ formData: data }), |
|
})); |
|
|
|
window.addEventListener("load", async () => { |
|
const speakers = await client.listSpeakers(); |
|
useStore.get().setSpeakers(speakers.data); |
|
}); |
|
|
|
const SpeakerFactory = () => { |
|
|
|
|
|
const { setSpeakers, formData, setFormData } = useStore(); |
|
return html` |
|
<feildset class="speaker-factory"> |
|
<div> |
|
<label |
|
>seed |
|
|
|
<input |
|
type="number" |
|
value=${formData.seed} |
|
oninput=${(e) => setFormData({ ...formData, seed: e.target.value })} |
|
/> |
|
</label> |
|
<label |
|
>name |
|
<input |
|
type="text" |
|
value=${formData.name} |
|
oninput=${(e) => setFormData({ ...formData, name: e.target.value })} |
|
/> |
|
</label> |
|
|
|
<button |
|
onclick=${async () => { |
|
const speaker = await client.createSpeaker(formData); |
|
setSpeakers([...useStore.get().speakers, speaker]); |
|
setFormData({ seed: 0, name: "" }); |
|
}} |
|
> |
|
创建 |
|
</button> |
|
</div> |
|
</feildset> |
|
`; |
|
}; |
|
|
|
const SpeakerList = () => { |
|
|
|
|
|
const { speakers } = useStore(); |
|
|
|
return html` |
|
<fieldset class="spekaer-list"> |
|
<legend>Speakers</legend> |
|
|
|
<table class="speaker-list"> |
|
<thead> |
|
<tr> |
|
<th>id</th> |
|
<th>name</th> |
|
</tr> |
|
</thead> |
|
<tbody> |
|
${speakers.map( |
|
(speaker) => html` |
|
<tr> |
|
<td>${speaker.id}</td> |
|
<td>${speaker.name}</td> |
|
</tr> |
|
` |
|
)} |
|
</tbody> |
|
</table> |
|
</fieldset> |
|
`; |
|
}; |
|
|
|
const SpeakerPageContainer = styled.div` |
|
display: flex; |
|
flex-direction: row; |
|
|
|
textarea { |
|
width: 100%; |
|
height: 10rem; |
|
margin-bottom: 1rem; |
|
|
|
min-height: 10rem; |
|
|
|
resize: vertical; |
|
} |
|
|
|
button { |
|
padding: 0.5rem 1rem; |
|
background-color: #007bff; |
|
color: white; |
|
border: none; |
|
cursor: pointer; |
|
} |
|
|
|
button:hover { |
|
background-color: #0056b3; |
|
} |
|
|
|
button:disabled { |
|
background-color: #6c757d; |
|
cursor: not-allowed; |
|
} |
|
|
|
fieldset { |
|
margin-top: 1rem; |
|
padding: 1rem; |
|
border: 1px solid #333; |
|
} |
|
|
|
legend { |
|
font-weight: bold; |
|
} |
|
|
|
label { |
|
display: block; |
|
margin-bottom: 0.5rem; |
|
} |
|
|
|
select, |
|
input[type="range"], |
|
input[type="number"] { |
|
width: 100%; |
|
margin-top: 0.25rem; |
|
} |
|
|
|
input[type="range"] { |
|
width: calc(100% - 2rem); |
|
} |
|
|
|
input[type="number"] { |
|
width: calc(100% - 2rem); |
|
padding: 0.5rem; |
|
} |
|
|
|
input[type="text"] { |
|
width: 100%; |
|
padding: 0.5rem; |
|
} |
|
|
|
audio { |
|
margin-top: 1rem; |
|
} |
|
|
|
textarea, |
|
input, |
|
select { |
|
background-color: #333; |
|
color: white; |
|
border: 1px solid #333; |
|
border-radius: 0.25rem; |
|
padding: 0.5rem; |
|
} |
|
|
|
table { |
|
width: 100%; |
|
border-collapse: collapse; |
|
} |
|
|
|
th, |
|
td { |
|
padding: 0.5rem; |
|
border: 1px solid #333; |
|
} |
|
|
|
th { |
|
background-color: #333; |
|
color: white; |
|
} |
|
|
|
th:nth-child(2), |
|
td:nth-child(2) { |
|
width: 60%; |
|
} |
|
|
|
.speaker-factory { |
|
flex: 1; |
|
} |
|
|
|
.spekaer-list { |
|
width: 256px; |
|
} |
|
`; |
|
|
|
export const SpeakerPage = () => { |
|
return html` |
|
<${SpeakerPageContainer}> |
|
<${SpeakerList} /> |
|
<${SpeakerFactory} /> |
|
<//> |
|
`; |
|
}; |
|
|