---
phase: 14-user-directory-view
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
  - SharepointToolbox/Localization/Strings.resx
  - SharepointToolbox/Localization/Strings.fr.resx
  - SharepointToolbox/ViewModels/Tabs/UserAccessAuditViewModel.cs
  - SharepointToolbox/Views/Tabs/UserAccessAuditView.xaml.cs
  - SharepointToolbox.Tests/ViewModels/UserAccessAuditViewModelDirectoryTests.cs
autonomous: true
requirements:
  - UDIR-05
  - UDIR-01

must_haves:
  truths:
    - "SelectDirectoryUserCommand takes a GraphDirectoryUser, converts it to GraphUserResult, adds it to SelectedUsers via existing logic"
    - "After SelectDirectoryUserCommand, the user appears in SelectedUsers and can be audited with RunCommand"
    - "SelectDirectoryUserCommand does not add duplicates (same UPN check as existing AddUserCommand)"
    - "Localization keys for directory UI exist in both EN and FR resource files"
    - "Code-behind has a DirectoryDataGrid_MouseDoubleClick handler that invokes SelectDirectoryUserCommand"
  artifacts:
    - path: "SharepointToolbox/ViewModels/Tabs/UserAccessAuditViewModel.cs"
      provides: "SelectDirectoryUserCommand bridging directory selection to audit pipeline"
      contains: "SelectDirectoryUserCommand"
    - path: "SharepointToolbox/Views/Tabs/UserAccessAuditView.xaml.cs"
      provides: "Event handler for directory DataGrid double-click"
      contains: "DirectoryDataGrid_MouseDoubleClick"
    - path: "SharepointToolbox.Tests/ViewModels/UserAccessAuditViewModelDirectoryTests.cs"
      provides: "Tests for SelectDirectoryUserCommand"
      contains: "SelectDirectoryUser"
  key_links:
    - from: "SharepointToolbox/ViewModels/Tabs/UserAccessAuditViewModel.cs"
      to: "SharepointToolbox/Core/Models/GraphDirectoryUser.cs"
      via: "command parameter type"
      pattern: "GraphDirectoryUser"
    - from: "SharepointToolbox/Views/Tabs/UserAccessAuditView.xaml.cs"
      to: "SharepointToolbox/ViewModels/Tabs/UserAccessAuditViewModel.cs"
      via: "command invocation"
      pattern: "SelectDirectoryUserCommand"
---

<objective>
Add localization keys for directory UI, the SelectDirectoryUserCommand that bridges directory selection to the audit pipeline, and a code-behind event handler for DataGrid double-click.

Purpose: Provides the infrastructure (localization, command, event handler) that Plan 14-02 needs to build the XAML view. SC2 requires selecting a directory user to trigger an audit — this command makes that possible.

Output: Localization keys (EN+FR), SelectDirectoryUserCommand with tests, code-behind event handler.
</objective>

<execution_context>
@C:/Users/dev/.claude/get-shit-done/workflows/execute-plan.md
@C:/Users/dev/.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/phases/14-user-directory-view/14-RESEARCH.md

<interfaces>
<!-- Current ViewModel command pattern (AddUserCommand) -->
From SharepointToolbox/ViewModels/Tabs/UserAccessAuditViewModel.cs:
```csharp
public RelayCommand<GraphUserResult> AddUserCommand { get; }

private void ExecuteAddUser(GraphUserResult? user)
{
    if (user == null) return;
    if (!SelectedUsers.Any(u => u.UserPrincipalName == user.UserPrincipalName))
    {
        SelectedUsers.Add(user);
    }
    SearchQuery = string.Empty;
    SearchResults.Clear();
}
```

<!-- GraphDirectoryUser record -->
From SharepointToolbox/Core/Models/GraphDirectoryUser.cs:
```csharp
public record GraphDirectoryUser(
    string DisplayName, string UserPrincipalName,
    string? Mail, string? Department, string? JobTitle, string? UserType);
```

<!-- GraphUserResult record -->
From SharepointToolbox/Services/IGraphUserSearchService.cs:
```csharp
public record GraphUserResult(string DisplayName, string UserPrincipalName, string? Mail);
```

<!-- Existing code-behind pattern -->
From SharepointToolbox/Views/Tabs/UserAccessAuditView.xaml.cs:
```csharp
private void SearchResultsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (sender is ListBox listBox && listBox.SelectedItem is GraphUserResult user)
    {
        var vm = (UserAccessAuditViewModel)DataContext;
        if (vm.AddUserCommand.CanExecute(user))
            vm.AddUserCommand.Execute(user);
        listBox.SelectedItem = null;
    }
}
```

<!-- Existing localization key pattern -->
From Strings.resx:
```xml
<data name="audit.grp.users" xml:space="preserve"><value>Select Users</value></data>
<data name="audit.btn.run" xml:space="preserve"><value>Run Audit</value></data>
```
</interfaces>
</context>

<tasks>

<task type="auto">
  <name>Task 1: Add localization keys for directory UI (EN + FR)</name>
  <files>
    SharepointToolbox/Localization/Strings.resx,
    SharepointToolbox/Localization/Strings.fr.resx
  </files>
  <behavior>
    - Both resx files contain matching keys for directory browse UI
  </behavior>
  <action>
    1. Add to `Strings.resx` (EN):
       - `audit.mode.search` = "Search"
       - `audit.mode.browse` = "Browse Directory"
       - `directory.grp.browse` = "User Directory"
       - `directory.btn.load` = "Load Directory"
       - `directory.btn.cancel` = "Cancel"
       - `directory.filter.placeholder` = "Filter users..."
       - `directory.chk.guests` = "Include guests"
       - `directory.status.count` = "users"
       - `directory.hint.doubleclick` = "Double-click a user to add to audit"
       - `directory.col.name` = "Name"
       - `directory.col.upn` = "Email"
       - `directory.col.department` = "Department"
       - `directory.col.jobtitle` = "Job Title"
       - `directory.col.type` = "Type"

    2. Add to `Strings.fr.resx` (FR):
       - `audit.mode.search` = "Recherche"
       - `audit.mode.browse` = "Parcourir l'annuaire"
       - `directory.grp.browse` = "Annuaire utilisateurs"
       - `directory.btn.load` = "Charger l'annuaire"
       - `directory.btn.cancel` = "Annuler"
       - `directory.filter.placeholder` = "Filtrer les utilisateurs..."
       - `directory.chk.guests` = "Inclure les invités"
       - `directory.status.count` = "utilisateurs"
       - `directory.hint.doubleclick` = "Double-cliquez sur un utilisateur pour l'ajouter à l'audit"
       - `directory.col.name` = "Nom"
       - `directory.col.upn` = "Courriel"
       - `directory.col.department` = "Département"
       - `directory.col.jobtitle` = "Poste"
       - `directory.col.type` = "Type"
  </action>
  <verify>
    <automated>dotnet build --no-restore -warnaserror</automated>
  </verify>
  <done>14 localization keys present in both EN and FR resource files.</done>
</task>

<task type="auto" tdd="true">
  <name>Task 2: Add SelectDirectoryUserCommand to ViewModel</name>
  <files>
    SharepointToolbox/ViewModels/Tabs/UserAccessAuditViewModel.cs,
    SharepointToolbox.Tests/ViewModels/UserAccessAuditViewModelDirectoryTests.cs
  </files>
  <behavior>
    - SelectDirectoryUserCommand is a RelayCommand<GraphDirectoryUser>
    - It converts GraphDirectoryUser to GraphUserResult and adds to SelectedUsers
    - Duplicate UPN check (same as AddUserCommand)
    - Does NOT clear SearchQuery/SearchResults (not in search mode context)
    - After execution, IsBrowseMode stays true — user can continue selecting from directory
  </behavior>
  <action>
    1. Add command declaration in ViewModel:
       ```csharp
       public RelayCommand<GraphDirectoryUser> SelectDirectoryUserCommand { get; }
       ```

    2. Initialize in BOTH constructors:
       ```csharp
       SelectDirectoryUserCommand = new RelayCommand<GraphDirectoryUser>(ExecuteSelectDirectoryUser);
       ```

    3. Implement the command method:
       ```csharp
       private void ExecuteSelectDirectoryUser(GraphDirectoryUser? dirUser)
       {
           if (dirUser == null) return;
           var userResult = new GraphUserResult(dirUser.DisplayName, dirUser.UserPrincipalName, dirUser.Mail);
           if (!SelectedUsers.Any(u => u.UserPrincipalName == userResult.UserPrincipalName))
           {
               SelectedUsers.Add(userResult);
           }
       }
       ```

    4. Add tests to `UserAccessAuditViewModelDirectoryTests.cs`:
       - Test: SelectDirectoryUserCommand adds user to SelectedUsers
       - Test: SelectDirectoryUserCommand skips duplicates
       - Test: SelectDirectoryUserCommand with null does nothing
       - Test: After SelectDirectoryUser, user can be audited with RunCommand (integration: add user + check SelectedUsers.Count > 0)
  </action>
  <verify>
    <automated>dotnet build --no-restore -warnaserror && dotnet test SharepointToolbox.Tests --filter "FullyQualifiedName~UserAccessAuditViewModelDirectory" --no-build -q</automated>
  </verify>
  <done>SelectDirectoryUserCommand bridges directory selection to audit pipeline. Tests pass.</done>
</task>

<task type="auto">
  <name>Task 3: Add code-behind event handler for directory DataGrid</name>
  <files>
    SharepointToolbox/Views/Tabs/UserAccessAuditView.xaml.cs
  </files>
  <behavior>
    - DirectoryDataGrid_MouseDoubleClick handler extracts the clicked GraphDirectoryUser
    - Invokes SelectDirectoryUserCommand with the selected user
    - Uses the same pattern as SearchResultsListBox_SelectionChanged
  </behavior>
  <action>
    1. Add to `UserAccessAuditView.xaml.cs`:
       ```csharp
       private void DirectoryDataGrid_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
       {
           if (sender is DataGrid grid && grid.SelectedItem is GraphDirectoryUser user)
           {
               var vm = (UserAccessAuditViewModel)DataContext;
               if (vm.SelectDirectoryUserCommand.CanExecute(user))
                   vm.SelectDirectoryUserCommand.Execute(user);
           }
       }
       ```

    2. Add the required using statement if not present:
       ```csharp
       using System.Windows.Controls;  // Already present
       using SharepointToolbox.Core.Models;  // For GraphDirectoryUser
       ```
  </action>
  <verify>
    <automated>dotnet build --no-restore -warnaserror</automated>
  </verify>
  <done>Code-behind event handler exists, ready to be wired in XAML (Plan 14-02).</done>
</task>

</tasks>

<verification>
```bash
dotnet build --no-restore -warnaserror
dotnet test SharepointToolbox.Tests --filter "FullyQualifiedName~UserAccessAuditViewModelDirectory" --no-build -q
```
Both must pass with zero failures.
</verification>

<success_criteria>
- 14 localization keys in both EN and FR resx files
- SelectDirectoryUserCommand converts GraphDirectoryUser → GraphUserResult → SelectedUsers
- Duplicate UPN check prevents adding same user twice
- Code-behind event handler for DataGrid double-click
- All tests pass, build clean
</success_criteria>

<output>
After completion, create `.planning/phases/14-user-directory-view/14-01-SUMMARY.md`
</output>
