feat(frontend): channel type selector on create
Required Type dropdown (general|work|report|discuss|triage|custom) in the create-channel modal; sends xType; shows type badge on channel rows. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -25,7 +25,10 @@ function timeOf(iso?: string): string {
|
|||||||
return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
|
return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
|
||||||
}
|
}
|
||||||
|
|
||||||
type GuildChannel = { id: string; name: string; guildId?: string }
|
const X_TYPES = ['general', 'work', 'report', 'discuss', 'triage', 'custom'] as const
|
||||||
|
type XType = (typeof X_TYPES)[number]
|
||||||
|
|
||||||
|
type GuildChannel = { id: string; name: string; guildId?: string; xType?: XType }
|
||||||
type MemberItem = { userId: string; email: string; name: string; status: string }
|
type MemberItem = { userId: string; email: string; name: string; status: string }
|
||||||
|
|
||||||
export default function ChatPage() {
|
export default function ChatPage() {
|
||||||
@@ -41,6 +44,7 @@ export default function ChatPage() {
|
|||||||
const [joinGuildNodeId, setJoinGuildNodeId] = useState('')
|
const [joinGuildNodeId, setJoinGuildNodeId] = useState('')
|
||||||
const [selectedMemberIds, setSelectedMemberIds] = useState<string[]>([])
|
const [selectedMemberIds, setSelectedMemberIds] = useState<string[]>([])
|
||||||
const [newChannelPublic, setNewChannelPublic] = useState(false)
|
const [newChannelPublic, setNewChannelPublic] = useState(false)
|
||||||
|
const [newChannelXType, setNewChannelXType] = useState<XType>('general')
|
||||||
const [showCreateChannelModal, setShowCreateChannelModal] = useState(false)
|
const [showCreateChannelModal, setShowCreateChannelModal] = useState(false)
|
||||||
const [showSettingsModal, setShowSettingsModal] = useState(false)
|
const [showSettingsModal, setShowSettingsModal] = useState(false)
|
||||||
const [showAddGuildModal, setShowAddGuildModal] = useState(false)
|
const [showAddGuildModal, setShowAddGuildModal] = useState(false)
|
||||||
@@ -178,6 +182,7 @@ export default function ChatPage() {
|
|||||||
const payload = {
|
const payload = {
|
||||||
name: newChannelName.trim(),
|
name: newChannelName.trim(),
|
||||||
guildId: effectiveGuildId,
|
guildId: effectiveGuildId,
|
||||||
|
xType: newChannelXType,
|
||||||
isPublic: newChannelPublic,
|
isPublic: newChannelPublic,
|
||||||
memberUserIds: selectedMemberIds,
|
memberUserIds: selectedMemberIds,
|
||||||
}
|
}
|
||||||
@@ -186,6 +191,7 @@ export default function ChatPage() {
|
|||||||
setNewChannelName('')
|
setNewChannelName('')
|
||||||
setSelectedMemberIds([])
|
setSelectedMemberIds([])
|
||||||
setNewChannelPublic(false)
|
setNewChannelPublic(false)
|
||||||
|
setNewChannelXType('general')
|
||||||
setShowCreateChannelModal(false)
|
setShowCreateChannelModal(false)
|
||||||
await loadChannels()
|
await loadChannels()
|
||||||
if (createdId) setSelectedChannelId(createdId)
|
if (createdId) setSelectedChannelId(createdId)
|
||||||
@@ -287,6 +293,7 @@ export default function ChatPage() {
|
|||||||
>
|
>
|
||||||
<span className="hash">#</span>
|
<span className="hash">#</span>
|
||||||
<span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{c.name}</span>
|
<span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{c.name}</span>
|
||||||
|
{c.xType ? <span className="chan-tag">{c.xType}</span> : null}
|
||||||
</button>
|
</button>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
@@ -422,6 +429,20 @@ export default function ChatPage() {
|
|||||||
onChange={(e) => setNewChannelName(e.target.value)}
|
onChange={(e) => setNewChannelName(e.target.value)}
|
||||||
placeholder="Channel name"
|
placeholder="Channel name"
|
||||||
/>
|
/>
|
||||||
|
<div className="field" style={{ marginTop: 10 }}>
|
||||||
|
<label>Type</label>
|
||||||
|
<select
|
||||||
|
className="input"
|
||||||
|
value={newChannelXType}
|
||||||
|
onChange={(e) => setNewChannelXType(e.target.value as XType)}
|
||||||
|
>
|
||||||
|
{X_TYPES.map((t) => (
|
||||||
|
<option key={t} value={t}>
|
||||||
|
{t}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<label className="check-row" style={{ marginTop: 10 }}>
|
<label className="check-row" style={{ marginTop: 10 }}>
|
||||||
<input type="checkbox" checked={newChannelPublic} onChange={(e) => setNewChannelPublic(e.target.checked)} />
|
<input type="checkbox" checked={newChannelPublic} onChange={(e) => setNewChannelPublic(e.target.checked)} />
|
||||||
<span>Public — visible to all guild members</span>
|
<span>Public — visible to all guild members</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user