{{-- Inline editor for the startup Team section. Each team member is a row that can be edited or removed in place; a separate "+ Add" affordance creates a new member. All persistence is AJAX (POST/PATCH/DELETE) against the team routes registered in routes/web.php — no page reload. NOTE (2026-06-14, Item 3 audit): the public signup form was refactored to a strict 5-field schema: name, position_option_id (FK), commitment code (full_time/part_time), country_id, linkedin_url. This admin editor still surfaces the legacy multi-select Positions + Short Bio + Founder flag + Phone + Twitter — admins continue to edit them on Monday-imported rows. A follow-up PR should align this editor to the 5-field shape; for now both schemas coexist. Required variables: $startup — the Startup model $members — collection of StartupMember models with relations loaded: ['jobType', 'country', 'positions.option'] --}} @php use App\Services\Admin\EntitySectionSchema; // Reuse the existing schema catalogue loader for countries + label // options. The startup schema already references job_type / position // implicitly through the section-level catalogues call, so we lean on // a one-off Label query for the two keys we need here. $locale = app()->getLocale(); $tr = fn ($row, $field) => $row ? ($locale === 'ar' ? ((string) ($row->{$field . '_ar'} ?: $row->{$field . '_en'})) : ((string) ($row->{$field . '_en'} ?: $row->{$field . '_ar'}))) : ''; // Countries — flat [id => name]. $teamCountries = \App\Models\Country::query()->orderBy('name_en')->get(['id', 'name_en', 'name_ar']) ->mapWithKeys(fn ($c) => [(int) $c->id => $tr($c, 'name')]) ->all(); // Job-type + position label catalogues. $teamJobTypes = collect(); $teamPositions = collect(); foreach (\App\Models\Label::query()->whereIn('key', ['job_type', 'position'])->with(['options' => fn ($q) => $q->orderBy('sort_order')->orderBy('id')])->get() as $label) { $target = $label->key === 'job_type' ? 'teamJobTypes' : 'teamPositions'; $$target = $label->options->map(fn ($o) => ['id' => (int) $o->id, 'name' => $tr($o, 'name')])->values(); } // Commitment-type labels for the JOB TYPE column fallback. Signup // form (Item 3, 2026-06-14) writes "Full-time" / "Part-time" to // `commitment_type_code` instead of `job_type_option_id`, so we // render the commitment label when the legacy column is empty. $commitmentLabels = \App\Models\CommitmentType::query()->get() ->mapWithKeys(fn ($c) => [$c->code => ($locale === 'ar' ? ($c->name_ar ?: $c->name_en) : ($c->name_en ?: $c->name_ar))]) ->all(); // Wire-format the existing members so Alpine seeds with them. $serializedMembers = $members->map(function ($m) use ($tr, $commitmentLabels) { // POSITIONS column resolution — three-tier fallback (newest first): // 1. Free-text `position` string (signup form since 2026-06-17). // 2. `position_option_id` label (signup form 2026-06-14 → 06-16). // 3. Legacy `members_positions` pivot (Monday-synced rows). // Whichever path resolves, we hydrate the same `positions` chip // array Alpine reads so the existing UI keeps working. $positionsArr = []; if (filled($m->position)) { // Free-text wins — single virtual chip with no FK id (the // chip renders by `name`; updates round-trip through the // member edit modal as a string). $positionsArr = [[ 'id' => null, 'name' => (string) $m->position, ]]; } else { $positionsArr = $m->positions->map(fn ($p) => [ 'id' => (int) $p->position_option_id, 'name' => $tr($p->option, 'name'), ])->values()->all(); if ($positionsArr === [] && $m->position_option_id) { $positionsArr = [[ 'id' => (int) $m->position_option_id, 'name' => $tr($m->positionOption, 'name'), ]]; } } // JOB TYPE column fallback: prefer the legacy label-option name // when set, otherwise resolve commitment_type_code → localized // CommitmentType name. Either way the table shows "Full Time". $jobTypeName = $tr($m->jobType, 'name'); if ($jobTypeName === '' && $m->commitment_type_code) { // The last fallback used to surface the RAW code ("full_time") // when the CommitmentType row was missing. Humanize it // ("Full Time") so the badge never reads as developer // jargon even if the seed gets out of sync. $jobTypeName = $commitmentLabels[$m->commitment_type_code] ?? ucwords(str_replace('_', ' ', $m->commitment_type_code)); } // Synthesize a `commitment_type_code` for legacy rows whose // employment type lives ONLY in the `jobType` label_option but // not in `commitment_type_code`. Without this the badge colour // routing falls back to grey for every legacy member. The match // is locale-aware: "Full Time" (EN) and "دوام كامل" (AR) both // map to `full_time`. $effectiveCommitmentCode = $m->commitment_type_code; if (! $effectiveCommitmentCode && $jobTypeName !== '') { $lower = mb_strtolower($jobTypeName); if (str_contains($lower, 'full') || str_contains($jobTypeName, 'كامل')) { $effectiveCommitmentCode = 'full_time'; } elseif (str_contains($lower, 'part') || str_contains($jobTypeName, 'جزئي') || str_contains($jobTypeName, 'جزء')) { $effectiveCommitmentCode = 'part_time'; } } return [ 'id' => (int) $m->id, 'name' => (string) $m->name, 'job_type_option_id' => $m->job_type_option_id ? (int) $m->job_type_option_id : null, 'job_type_name' => $jobTypeName, 'commitment_type_code' => $effectiveCommitmentCode, 'position_option_id' => $m->position_option_id ? (int) $m->position_option_id : null, 'country_id' => $m->country_id ? (int) $m->country_id : null, 'country_name' => $tr($m->country, 'name'), 'linkedin_url' => $m->linkedin_url, 'twitter_url' => $m->twitter_url, 'phone_number' => $m->phone_number, 'short_brief' => $m->short_brief, 'is_founder' => (bool) $m->is_founder, 'positions' => $positionsArr, ]; })->values(); @endphp

{{ __('admin.startups_admin.members.title') }}

{{-- Icon-only "+" button sits right before the chevron so the action sits in the same visual tier as the edit affordances on every other section. Hidden until Edit Mode is on. --}}
{{-- Table layout: NAME | JOB TYPE | POSITIONS | NATIONALITY | FOUNDER | actions. Each member is either a view-mode or an edit-mode with colspan that holds the per-row form. Switching is purely a CSS class toggle (tm-tr--editing hides the view cells and reveals the colspanning form row directly underneath). --}}
{{-- HTML5 allows multiple elements inside a
{{ __('admin.startups_admin.members.name') }} {{ __('admin.startups_admin.members.job_title') }} {{ __('admin.startups_admin.members.positions') }} {{ __('admin.startups_admin.members.nationality') }} {{ __('admin.startups_admin.members.founder') }}
; we use one per member so the x-for template has a single root element to repeat. View + Edit rows live side-by-side inside each tbody and toggle via x-show. --}}
@once @endonce