feat: Add mode selection interface for creator/joiner

**Motivations :**
- Improve user experience with clear role selection
- Add intuitive interface to choose between creator and joiner modes
- Provide easy navigation between modes

**Modifications :**
- Added mode selection screen with two main buttons
- Added back buttons to return to mode selection
- Enhanced CSS styling for mode buttons and navigation
- Added JavaScript logic for mode switching

**Pages affectées :**
- src/pages/home/home.html - Added mode selection interface
- src/pages/home/home.ts - Added mode selection logic
- src/4nk.css - Added styling for mode selection and back buttons
This commit is contained in:
NicolasCantu 2025-10-23 20:13:34 +02:00
parent 03bc0b5602
commit 82b3b27ab6
4 changed files with 212 additions and 2 deletions

View File

@ -1080,3 +1080,119 @@ select[data-multi-select-plugin] {
.custom-select::-webkit-scrollbar-thumb:hover {
background: #555;
}
/* Mode Selection Styles */
.mode-buttons {
display: flex;
gap: 20px;
margin: 20px 0;
flex-wrap: wrap;
}
.mode-btn {
flex: 1;
min-width: 250px;
display: flex;
align-items: center;
gap: 15px;
padding: 20px;
border: 2px solid transparent;
border-radius: 12px;
cursor: pointer;
transition: all 0.3s ease;
text-align: left;
background: white;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.mode-btn:hover {
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);
}
.mode-btn.primary-btn {
border-color: var(--primary-color);
}
.mode-btn.primary-btn:hover {
background: var(--primary-color);
color: white;
}
.mode-btn.secondary-btn {
border-color: var(--secondary-color);
}
.mode-btn.secondary-btn:hover {
background: var(--secondary-color);
color: white;
}
.mode-icon {
font-size: 32px;
flex-shrink: 0;
}
.mode-content h3 {
margin: 0 0 8px 0;
font-size: 18px;
font-weight: 600;
color: inherit;
}
.mode-content p {
margin: 0;
font-size: 14px;
color: #666;
line-height: 1.4;
}
.mode-btn:hover .mode-content p {
color: inherit;
opacity: 0.9;
}
/* Back Button Styles */
.back-btn {
background: transparent;
border: 1px solid #ddd;
color: #666;
padding: 8px 16px;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
transition: all 0.3s ease;
margin-top: 10px;
}
.back-btn:hover {
background: #f8f9fa;
border-color: var(--primary-color);
color: var(--primary-color);
}
.card-header {
position: relative;
}
.card-header .back-btn {
position: absolute;
top: 0;
right: 0;
}
/* Responsive Design for Mode Selection */
@media (max-width: 768px) {
.mode-buttons {
flex-direction: column;
}
.mode-btn {
min-width: auto;
}
.card-header .back-btn {
position: static;
margin-top: 10px;
}
}

View File

@ -1,8 +1,35 @@
<div class="pairing-container">
<!-- Mode Selection -->
<div id="mode-selection" class="card pairing-card">
<div class="card-header">
<h2>🔐 4NK Pairing</h2>
<p class="card-description">Choose your role in the pairing process</p>
</div>
<div class="mode-buttons">
<button id="creator-mode-btn" class="mode-btn primary-btn">
<div class="mode-icon">🔐</div>
<div class="mode-content">
<h3>Create New Pairing</h3>
<p>Generate 4 words to share with another device</p>
</div>
</button>
<button id="joiner-mode-btn" class="mode-btn secondary-btn">
<div class="mode-icon">🔗</div>
<div class="mode-content">
<h3>Join Existing Pairing</h3>
<p>Enter 4 words from another device</p>
</div>
</button>
</div>
</div>
<!-- Creator Flow -->
<div id="creator-flow" class="card pairing-card" style="display: none">
<div class="card-header">
<h2>🔐 Create New Pairing</h2>
<button id="back-to-mode-creator" class="back-btn">← Back to Mode Selection</button>
</div>
<div class="pairing-request"></div>
@ -28,6 +55,7 @@
<div class="card-header">
<h2>🔗 Join Existing Pairing</h2>
<p class="card-description">Enter the 4 words from the creator device</p>
<button id="back-to-mode-joiner" class="back-btn">← Back to Mode Selection</button>
</div>
<div class="input-container">

View File

@ -118,6 +118,9 @@ export async function initHomePage(): Promise<void> {
// Set up iframe pairing button listeners
setupIframePairingButtons();
// Set up mode selection
setupModeSelection();
const container = getCorrectDOM('login-4nk-component') as HTMLElement;
container.querySelectorAll('.tab').forEach(tab => {
addSubscription(tab, 'click', () => {
@ -513,3 +516,66 @@ export function setupIframePairingButtons() {
});
}
}
// Mode Selection Functions
export function setupModeSelection(): void {
const container = getCorrectDOM('login-4nk-component') as HTMLElement;
// Mode selection buttons
const creatorModeBtn = container.querySelector('#creator-mode-btn') as HTMLButtonElement;
const joinerModeBtn = container.querySelector('#joiner-mode-btn') as HTMLButtonElement;
// Back buttons
const backToModeCreator = container.querySelector('#back-to-mode-creator') as HTMLButtonElement;
const backToModeJoiner = container.querySelector('#back-to-mode-joiner') as HTMLButtonElement;
if (creatorModeBtn) {
creatorModeBtn.addEventListener('click', () => {
showMode('creator');
});
}
if (joinerModeBtn) {
joinerModeBtn.addEventListener('click', () => {
showMode('joiner');
});
}
if (backToModeCreator) {
backToModeCreator.addEventListener('click', () => {
showMode('selection');
});
}
if (backToModeJoiner) {
backToModeJoiner.addEventListener('click', () => {
showMode('selection');
});
}
}
function showMode(mode: 'selection' | 'creator' | 'joiner'): void {
const container = getCorrectDOM('login-4nk-component') as HTMLElement;
const modeSelection = container.querySelector('#mode-selection') as HTMLElement;
const creatorFlow = container.querySelector('#creator-flow') as HTMLElement;
const joinerFlow = container.querySelector('#joiner-flow') as HTMLElement;
// Hide all flows
if (modeSelection) modeSelection.style.display = 'none';
if (creatorFlow) creatorFlow.style.display = 'none';
if (joinerFlow) joinerFlow.style.display = 'none';
// Show selected flow
switch (mode) {
case 'selection':
if (modeSelection) modeSelection.style.display = 'block';
break;
case 'creator':
if (creatorFlow) creatorFlow.style.display = 'block';
break;
case 'joiner':
if (joinerFlow) joinerFlow.style.display = 'block';
break;
}
}