Files
project-managment/templates/users/form.html
T
sankalp b7d43b57f4 feat(templates/users): adopt role objects for branding and selection
Replace role name comparisons with slug checks and display role.name to support dynamic role definitions.
2026-06-29 06:56:55 +05:45

398 lines
26 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block title %}{% if editing %}Edit User{% else %}Create User{% endif %}{% endblock %}
{% block breadcrumb %}
<nav class="mb-4" aria-label="Breadcrumb">
<ol class="flex items-center gap-1.5 text-sm text-gray-500 dark:text-gray-400">
<li><a href="{% url 'users-list' %}" class="hover:text-gray-700 dark:hover:text-gray-300">Users</a></li>
<li class="text-gray-300 dark:text-gray-600"><i class="fas fa-chevron-right text-[10px]"></i></li>
{% if editing %}
<li><a href="{% url 'user-detail' user_obj.id %}" class="hover:text-gray-700 dark:hover:text-gray-300">{{ user_obj.get_full_name|default:user_obj.username }}</a></li>
<li class="text-gray-300 dark:text-gray-600"><i class="fas fa-chevron-right text-[10px]"></i></li>
<li class="text-gray-900 dark:text-white font-medium" aria-current="page">Edit</li>
{% else %}
<li class="text-gray-900 dark:text-white font-medium" aria-current="page">Create</li>
{% endif %}
</ol>
</nav>
{% endblock %}
{% block content %}
<div class="w-full">
<!-- Page Header -->
<div class="mb-6 flex items-center justify-between">
<h1 class="text-3xl font-bold text-gray-900 dark:text-white tracking-tight">
{% if editing %}Edit User{% else %}Create User{% endif %}
</h1>
</div>
<!-- Form -->
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="space-y-6">
<!-- Row 1: Name | Email -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label class="block text-sm font-semibold text-gray-900 dark:text-gray-100 mb-1.5">
Name <span class="text-red-500">*</span>
</label>
<input type="text" name="username" value="{{ form.username.value|default:'' }}"
required placeholder="Username"
class="w-full rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-950 px-3 py-2 text-sm focus:border-blue-500 focus:ring-1 focus:ring-blue-500 outline-none transition-colors">
{% if form.username.errors %}<p class="text-xs text-red-500 mt-1">{{ form.username.errors.0 }}</p>{% endif %}
</div>
<div>
<label class="block text-sm font-semibold text-gray-900 dark:text-gray-100 mb-1.5">
Email <span class="text-red-500">*</span>
</label>
<input type="email" name="email" value="{{ form.email.value|default:'' }}"
placeholder="Email address"
class="w-full rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-950 px-3 py-2 text-sm focus:border-blue-500 focus:ring-1 focus:ring-blue-500 outline-none transition-colors">
{% if form.email.errors %}<p class="text-xs text-red-500 mt-1">{{ form.email.errors.0 }}</p>{% endif %}
</div>
</div>
<!-- Row 2: First Name | Last Name -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label class="block text-sm font-semibold text-gray-900 dark:text-gray-100 mb-1.5">First Name</label>
<input type="text" name="first_name" value="{{ form.first_name.value|default:'' }}"
placeholder="First name"
class="w-full rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-950 px-3 py-2 text-sm focus:border-blue-500 focus:ring-1 focus:ring-blue-500 outline-none transition-colors">
</div>
<div>
<label class="block text-sm font-semibold text-gray-900 dark:text-gray-100 mb-1.5">Last Name</label>
<input type="text" name="last_name" value="{{ form.last_name.value|default:'' }}"
placeholder="Last name"
class="w-full rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-950 px-3 py-2 text-sm focus:border-blue-500 focus:ring-1 focus:ring-blue-500 outline-none transition-colors">
</div>
</div>
<!-- Row 3: Password fields (create only) -->
{% if not editing %}
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label class="block text-sm font-semibold text-gray-900 dark:text-gray-100 mb-1.5">
Password <span class="text-red-500">*</span>
</label>
<input type="password" name="password1" required placeholder="Password"
class="w-full rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-950 px-3 py-2 text-sm focus:border-blue-500 focus:ring-1 focus:ring-blue-500 outline-none transition-colors">
{% if form.password1.errors %}<p class="text-xs text-red-500 mt-1">{{ form.password1.errors.0 }}</p>{% endif %}
</div>
<div>
<label class="block text-sm font-semibold text-gray-900 dark:text-gray-100 mb-1.5">
Confirm Password <span class="text-red-500">*</span>
</label>
<input type="password" name="password2" required placeholder="Confirm password"
class="w-full rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-950 px-3 py-2 text-sm focus:border-blue-500 focus:ring-1 focus:ring-blue-500 outline-none transition-colors">
{% if form.password2.errors %}<p class="text-xs text-red-500 mt-1">{{ form.password2.errors.0 }}</p>{% endif %}
</div>
</div>
{% endif %}
<!-- Roles -->
<div>
<label class="block text-sm font-semibold text-gray-900 dark:text-gray-100 mb-1.5">Roles</label>
{% if can_change_role %}
<select name="role" class="w-full rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-950 px-3 py-2 text-sm focus:border-blue-500 focus:ring-1 focus:ring-blue-500 outline-none transition-colors">
{% for role in roles %}
<option value="{{ role.slug }}" {% if editing and current_role == role or not editing and role.slug == 'backend_developer' %}selected{% endif %}>{{ role.name }}</option>
{% endfor %}
</select>
{% else %}
<input type="hidden" name="role" value="backend_developer">
<div class="w-full rounded-lg border border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-900 px-3 py-2 text-sm text-gray-500 dark:text-gray-400">
Only admins can change roles.
</div>
{% endif %}
</div>
<!-- Active toggle -->
<div x-data="{ isActive: {{ user_obj.is_active|yesno:'true,false'|default:'true' }} }">
<input type="hidden" name="is_active" :value="isActive ? '1' : '0'">
<label class="flex items-start gap-3 cursor-pointer" @click.prevent="isActive = !isActive">
<div role="switch" class="mt-0.5 relative inline-flex h-5 w-9 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none"
:style="isActive ? 'background-color: var(--color-primary, #3b82f6)' : 'background-color: #d1d5db'">
<span class="pointer-events-none relative inline-block h-4 w-4 rounded-full bg-white shadow-sm ring-0 transition-transform duration-200 ease-in-out"
:style="isActive ? 'transform: translateX(16px)' : 'transform: translateX(0)'"></span>
</div>
<div>
<p class="text-sm font-semibold text-gray-900 dark:text-white">Active</p>
<p class="text-sm text-gray-500 dark:text-gray-400 mt-0.5">User is active and can log in</p>
</div>
</label>
</div>
<!-- Profile image (editing only) -->
{% if editing and user_obj.profile_image %}
<div>
<label class="block text-sm font-semibold text-gray-900 dark:text-gray-100 mb-1.5">Profile Image</label>
<div class="flex items-center gap-3">
<img src="{{ user_obj.profile_image.url }}" alt="Profile" class="w-12 h-12 rounded-full object-cover">
{{ form.profile_image }}
</div>
</div>
{% endif %}
</div>
<!-- Action Buttons -->
<div class="flex items-center gap-3" style="margin-top: 2rem;">
<button type="submit"
class="bg-blue-600 hover:bg-blue-700 text-white font-medium text-sm px-4 py-2 rounded-lg transition-colors">
{% if editing %}Save Changes{% else %}Create User{% endif %}
</button>
<a href="{% url 'users-list' %}"
class="bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-800 text-gray-900 dark:text-white font-medium text-sm px-4 py-2 rounded-lg transition-colors">
Cancel
</a>
</div>
</form>
<!-- Projects Section (edit mode only) -->
{% if editing %}
<div id="projects" style="margin-top: 4rem;" class="rounded-xl bg-white dark:bg-gray-950 shadow-sm ring-1 ring-gray-950/5 dark:ring-white/10"
x-data="{
openCols: false,
cols: { prefix: true, tickets: true, members: true },
createMemberOpen: {{ request.GET.open_attach|yesno:'true,false' }},
createMemberData: { project_id: '' },
open: false,
search: '',
selectedIds: [],
selectAll: false,
options: [
{% for p in available_projects %}
{ id: {{ p.id }}, name: '{{ p.name|escapejs }}' }{% if not forloop.last %},{% endif %}
{% endfor %}
],
get filteredOptions() {
if (this.search === '') return this.options;
return this.options.filter(i => String(i.name).toLowerCase().includes(this.search.toLowerCase()));
}
}">
<!-- Section header -->
<div class="px-6 py-4 border-b border-gray-100 dark:border-gray-600 flex flex-wrap items-center justify-between gap-3">
<h3 class="text-sm font-semibold text-gray-900 dark:text-white">Projects</h3>
<div class="flex items-center gap-2">
<!-- Search -->
<form method="GET" class="flex items-center gap-2">
<input type="hidden" name="proj_per_page" value="{{ proj_per_page }}">
<div class="relative">
<input type="text" name="project_search" value="{{ project_search }}" placeholder="Search projects..."
class="px-3 py-1.5 text-xs border border-gray-200 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-950 text-gray-900 dark:text-gray-100 placeholder-gray-400 focus:outline-none focus:ring-1 focus:ring-blue-500 w-44">
</div>
<button type="submit" class="px-2.5 py-1.5 text-xs font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors">Search</button>
{% if project_search %}
<a href="?#projects" class="text-xs text-gray-400 hover:text-gray-600 dark:hover:text-gray-200">Clear</a>
{% endif %}
</form>
<!-- Per page -->
<form method="GET">
<input type="hidden" name="project_search" value="{{ project_search }}">
<select name="proj_per_page" onchange="this.form.submit()"
class="text-xs border border-gray-200 dark:border-gray-600 rounded-lg py-1.5 px-2 bg-white dark:bg-gray-950 text-gray-700 dark:text-gray-300 focus:outline-none focus:ring-1 focus:ring-blue-500">
<option value="5" {% if proj_per_page == 5 %}selected{% endif %}>5 / page</option>
<option value="10" {% if proj_per_page == 10 %}selected{% endif %}>10 / page</option>
<option value="25" {% if proj_per_page == 25 %}selected{% endif %}>25 / page</option>
</select>
</form>
<!-- Column toggle -->
<div class="relative">
<button @click="openCols = !openCols"
class="flex items-center gap-1.5 px-2.5 py-1.5 text-xs font-medium text-gray-700 dark:text-gray-300 border border-gray-200 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-900 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7"/>
</svg>
Columns
</button>
<div x-show="openCols" @click.outside="openCols = false" x-cloak
class="absolute right-0 mt-1 w-40 bg-white dark:bg-gray-950 rounded-lg shadow-lg ring-1 ring-gray-950/5 dark:ring-white/10 z-20 py-1">
<label class="flex items-center gap-2 px-3 py-1.5 text-xs text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800 cursor-pointer">
<input type="checkbox" x-model="cols.prefix" class="rounded border-gray-300 text-blue-600"> Ticket Prefix
</label>
<label class="flex items-center gap-2 px-3 py-1.5 text-xs text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800 cursor-pointer">
<input type="checkbox" x-model="cols.tickets" class="rounded border-gray-300 text-blue-600"> Tickets
</label>
<label class="flex items-center gap-2 px-3 py-1.5 text-xs text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800 cursor-pointer">
<input type="checkbox" x-model="cols.members" class="rounded border-gray-300 text-blue-600"> Members
</label>
</div>
</div>
<!-- Attach button -->
<button type="button" @click="createMemberOpen = true"
class="inline-flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 transition-colors shadow-sm">
<i class="fas fa-plus"></i> Attach Project
</button>
</div>
</div>
<!-- Bulk delete form -->
<form id="projects-bulk-delete-form" method="post" action="{% url 'project-member-bulk-delete' %}">
{% csrf_token %}
<input type="hidden" name="user_id" value="{{ user_obj.id }}">
<template x-for="id in selectedIds" x-key="id">
<input type="hidden" name="member_ids" :value="id">
</template>
</form>
<!-- Selection toolbar -->
<div x-show="selectedIds.length > 0" x-cloak class="mb-4 flex items-center gap-3 px-4 py-2.5 bg-primary-50 dark:bg-primary-900/20 border border-primary-200 dark:border-primary-800 rounded-lg">
<span class="text-sm font-medium text-primary-700 dark:text-primary-300">
<span x-text="selectedIds.length"></span> selected
</span>
<button type="button" @click="confirmAction({title:'Detach Projects', message:'Detach ' + selectedIds.length + ' project(s)?', confirmText:'Detach', danger:true, onConfirm:function(){ document.getElementById('projects-bulk-delete-form').submit() }})"
class="dk-btn dk-btn-danger text-xs px-3 py-1">
<i class="fas fa-trash mr-1"></i> Detach Selected
</button>
<button type="button" @click="selectedIds = []; selectAll = false" class="text-xs text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 ml-auto">
<i class="fas fa-times mr-1"></i> Clear selection
</button>
</div>
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead>
<tr class="border-b border-gray-100 dark:border-gray-600 bg-gray-50 dark:bg-gray-800">
<th class="px-4 py-3 w-10">
<input type="checkbox" @change="selectAll = !selectAll; selectedIds = selectAll ? Array.from(document.querySelectorAll('.member-checkbox')).map(cb => cb.value) : []" class="rounded border-gray-300 dark:border-gray-600 text-blue-600 focus:ring-blue-500">
</th>
<th class="px-4 py-3 text-left text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">Project Name</th>
<th class="px-4 py-3 text-left text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">Description</th>
<th x-show="cols.prefix" class="px-4 py-3 text-center text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">Ticket Prefix</th>
<th x-show="cols.tickets" class="px-4 py-3 text-center text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">Tickets</th>
<th x-show="cols.members" class="px-4 py-3 text-center text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">Members</th>
<th class="px-4 py-3 text-right text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">Actions</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100 dark:divide-gray-700">
{% for membership in user_memberships %}
<tr class="hover:bg-gray-50 dark:hover:bg-gray-800/30 transition-colors" :class="selectedIds.includes('{{ membership.id }}') && 'bg-blue-50 dark:bg-blue-900/10'">
<td class="px-4 py-3">
<input type="checkbox" class="member-checkbox rounded border-gray-300 dark:border-gray-600 text-blue-600 focus:ring-blue-500" :value="'{{ membership.id }}'" x-model="selectedIds">
</td>
<td class="px-4 py-3 font-medium text-gray-900 dark:text-white">{{ membership.project.name }}</td>
<td class="px-4 py-3 text-gray-500 dark:text-gray-400 max-w-xs truncate">{{ membership.project.description|default:"—"|striptags|truncatechars:50 }}</td>
<td x-show="cols.prefix" class="px-4 py-3 text-center">
<span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-mono font-medium bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-300">{{ membership.project.ticket_prefix }}</span>
</td>
<td x-show="cols.tickets" class="px-4 py-3 text-center text-gray-900 dark:text-white font-medium">{{ membership.ticket_count }}</td>
<td x-show="cols.members" class="px-4 py-3 text-center text-gray-900 dark:text-white font-medium">{{ membership.member_count }}</td>
<td class="px-4 py-3 text-right">
<div class="flex items-center justify-end gap-3">
<a href="{% url 'project-detail' membership.project.id %}"
class="text-xs text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 font-medium">View</a>
<form method="post" action="{% url 'project-member-delete' membership.id %}" class="inline">
{% csrf_token %}
<button type="button"
@click="confirmAction({title:'Detach Project', message:'Remove this user from {{ membership.project.name|escapejs }}?', confirmText:'Detach', danger:true, onConfirm:function(){ $el.closest('form').submit() }})"
class="text-xs text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 font-medium">Detach</button>
</form>
</div>
</td>
</tr>
{% empty %}
<tr>
<td colspan="7" class="px-4 py-10 text-center text-sm text-gray-400 dark:text-gray-500">
{% if project_search %}No projects match "{{ project_search }}".{% else %}Not assigned to any projects yet.{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- Footer: count + pagination -->
<div class="px-4 py-3 border-t border-gray-100 dark:border-gray-600 flex items-center justify-between">
<p class="text-xs text-gray-500 dark:text-gray-400">
Showing {{ proj_page_obj.start_index }}–{{ proj_page_obj.end_index }} of {{ proj_page_obj.paginator.count }} result{{ proj_page_obj.paginator.count|pluralize }}
</p>
{% if proj_page_obj.has_other_pages %}
<div class="flex items-center gap-1">
{% if proj_page_obj.has_previous %}
<a href="?proj_page={{ proj_page_obj.previous_page_number }}&proj_per_page={{ proj_per_page }}{% if project_search %}&project_search={{ project_search }}{% endif %}#projects"
class="px-2.5 py-1 rounded text-xs font-medium text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800">Previous</a>
{% endif %}
{% for n in proj_page_obj.paginator.page_range %}
{% if n == proj_page_obj.number %}
<span class="px-2.5 py-1 rounded text-xs font-medium bg-blue-600 text-white">{{ n }}</span>
{% elif n >= proj_page_obj.number|add:"-2" and n <= proj_page_obj.number|add:"2" %}
<a href="?proj_page={{ n }}&proj_per_page={{ proj_per_page }}{% if project_search %}&project_search={{ project_search }}{% endif %}#projects"
class="px-2.5 py-1 rounded text-xs font-medium text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800">{{ n }}</a>
{% endif %}
{% endfor %}
{% if proj_page_obj.has_next %}
<a href="?proj_page={{ proj_page_obj.next_page_number }}&proj_per_page={{ proj_per_page }}{% if project_search %}&project_search={{ project_search }}{% endif %}#projects"
class="px-2.5 py-1 rounded text-xs font-medium text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800">Next</a>
{% endif %}
</div>
{% endif %}
</div>
<!-- Create Project Attachment Modal -->
<div x-cloak x-show="createMemberOpen" class="fixed inset-0 z-50 flex items-center justify-center">
<div class="fixed inset-0 bg-black/50" @click="createMemberOpen = false"></div>
<div class="relative bg-white dark:bg-gray-900 rounded-xl shadow-xl border border-gray-200 dark:border-gray-700 w-full max-w-md mx-4 sm:mx-auto my-auto z-10 overflow-visible">
<!-- Header -->
<div class="px-6 py-5 flex items-center justify-between">
<h3 class="text-base font-bold text-gray-900 dark:text-white">Attach Project</h3>
<button type="button" @click="createMemberOpen = false" class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
<!-- Body & Form -->
<form method="post" action="{% url 'user-project-attach' %}">
{% csrf_token %}
<input type="hidden" name="user_id" value="{{ user_obj.id }}">
<div class="px-6 pb-4">
<div class="relative w-full">
<input type="hidden" name="project_id" x-model="createMemberData.project_id">
<button type="button" @click="open = !open" @click.away="open = false" class="w-full flex items-center justify-between px-3 py-2.5 text-sm border border-gray-200 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:outline-none hover:bg-gray-50 dark:hover:bg-gray-700">
<span x-text="createMemberData.project_id ? options.find(o => o.id == createMemberData.project_id)?.name || 'Select an option' : 'Select an option'" :class="!createMemberData.project_id && 'text-gray-400'"></span>
<svg class="w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path></svg>
</button>
<!-- Dropdown Menu -->
<div x-cloak x-show="open" class="absolute left-0 right-0 top-full mt-1 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg z-50 overflow-hidden">
<div class="p-2 border-b border-gray-100 dark:border-gray-700">
<div class="relative">
<i class="fas fa-search absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 text-xs"></i>
<input type="text" x-model="search" placeholder="Search projects..." class="w-full pl-8 pr-3 py-1.5 text-sm border border-gray-200 dark:border-gray-600 rounded bg-gray-50 dark:bg-gray-900 focus:outline-none focus:ring-1 focus:ring-blue-500 text-gray-900 dark:text-white" @click.stop>
</div>
</div>
<ul class="max-h-48 overflow-y-auto py-1">
<template x-for="option in filteredOptions" :key="option.id">
<li @click="createMemberData.project_id = option.id; open = false; search = ''" class="px-3 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-blue-50 dark:hover:bg-blue-900/30 cursor-pointer" x-text="option.name"></li>
</template>
<li x-show="filteredOptions.length === 0" class="px-3 py-4 text-sm text-gray-500 text-center">No projects found</li>
</ul>
</div>
</div>
</div>
<!-- Footer -->
<div class="px-6 py-4 border-t border-gray-100 dark:border-gray-700 flex items-center justify-start gap-2">
<button type="submit" class="px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 transition-colors">Attach</button>
{% if available_projects.exists %}
<button type="submit" name="create_another" value="1" class="px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-200 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors">Attach & attach another</button>
{% endif %}
<button type="button" @click="createMemberOpen = false" class="px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-200 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors">Cancel</button>
</div>
</form>
</div>
</div>
</div>
{% endif %}
</div>
{% endblock %}