# ProfilePicturePicker

![Status](https://img.shields.io/badge/status-stable-brightgreen)

Componente para seleção, recorte e gerenciamento de foto de perfil. Permite selecionar uma imagem via clique ou arrastar e soltar, recortá-la em um cropper integrado e exibi-la como thumbnail. Implementa `ControlValueAccessor` para integração com Angular Forms.

## Quando usar

- Cadastro ou edição de perfil de usuário com foto
- Formulários que precisam de upload de imagem com recorte antes de salvar
- Campos de avatar em sistemas de gestão de pessoas

## Quando não usar

- Para upload de arquivos genéricos (documentos, PDFs, etc.) — use `FilePicker`
- Para seleção de imagem sem recorte — use um input de arquivo simples
- Quando o aspecto ratio varia dinamicamente por item — configure `aspectRatio` conforme o caso

## Instalação

```typescript
import { ProfilePicturePickerModule } from '@seniorsistemas/angular-components/profile-picture-picker';

@NgModule({ imports: [ProfilePicturePickerModule] })
export class MeuModulo {}
```

## Uso básico

```html
<s-profile-picture-picker
  formControlName="avatar"
  subtitle="Formato: JPG, PNG (máximo de 1 MB)"
  simpleTitle="Arraste sua foto ou"
  actionTitle="selecione um arquivo"
  accept=".png, .jpg"
  [supportedExtensions]="['png', 'jpg']"
  [maxFileSize]="1048576"
  (imageChange)="onImageChange($event)"
  (removedImage)="onImageRemoved()"
  (invalidFile)="onArquivoInvalido($event)"
/>
```

## API

### Inputs

| Propriedade | Tipo | Padrão | Obrigatório | Descrição |
|-------------|------|--------|:-----------:|-----------|
| `subtitle` | `string` | — | Sim | Legenda exibida abaixo do título com orientações de formato e tamanho |
| `simpleTitle` | `string` | `undefined` | Não | Parte estática do título (antes da ação clicável) |
| `actionTitle` | `string` | `undefined` | Não | Parte clicável do título — ao clicar, abre o seletor de arquivo |
| `image` | `string \| ProfilePicturePickerData \| null` | `null` | Não | Imagem atual. Aceita string base64 ou objeto com dados do arquivo |
| `aspectRatio` | `number` | `1` | Não | Proporção de aspecto do recorte (`1` = quadrado, `16/9` = widescreen) |
| `accept` | `string` | `undefined` | Não | Atributo `accept` do input de arquivo (ex: `".png, .jpg"`) |
| `supportedExtensions` | `string[]` | `[]` | Não | Extensões aceitas para validação (ex: `['png', 'jpg']`) |
| `maxFileSize` | `number` | `undefined` | Não | Tamanho máximo em bytes. Exemplo: `1048576` = 1 MB |
| `removeButtonLabel` | `string` | Tradução padrão | Não | Texto do botão de remover a foto |
| `changeButtonLabel` | `string` | Tradução padrão | Não | Texto do botão de alterar a foto |
| `confirmationTexts` | `ConfirmationTexts` | `undefined` | Não | Textos do diálogo de confirmação de remoção |
| `cropperLabelsConfig` | `CropperLabelsConfig` | `undefined` | Não | Textos customizados do Image Cropper integrado |

### Outputs

| Evento | Tipo | Descrição |
|--------|------|-----------|
| `imageChange` | `EventEmitter<string \| ProfilePicturePickerData>` | Emitido quando uma imagem é selecionada e recortada |
| `removedImage` | `EventEmitter<void>` | Emitido quando o usuário confirma a remoção da imagem |
| `invalidFile` | `EventEmitter<FileValidationErrors>` | Emitido quando a validação do arquivo falha |
| ~~`changedImage`~~ | `EventEmitter<string>` | **Descontinuado** — use `imageChange` |

### Tipos

```typescript
interface ProfilePicturePickerData {
  source: File;   // Arquivo original selecionado
  base64: string; // Imagem recortada em base64
}

interface FileValidationErrors {
  file: File | null;
  validation: 'maxFileSize' | 'maxFileLimit' | 'typeInvalid' | 'unsupportedExtension';
}

interface ConfirmationTexts {
  removalHeader: string;       // Título do diálogo de confirmação
  removalMessage: string;      // Mensagem do diálogo
  removalAcceptLabel: string;  // Label do botão confirmar
  removalRejectLabel: string;  // Label do botão cancelar
}

interface CropperLabelsConfig {
  header?: string;
  cropLabel?: string;
  removeLabel?: string;
  cancelLabel?: string;
  selectAnotherLabel?: string;
  emptyStateTitle?: string;
  emptyStateActionLabel?: string;
}
```

## Exemplos

### Cadastro de novo usuário

```html
<form [formGroup]="form">
  <s-profile-picture-picker
    formControlName="foto"
    subtitle="Formato: JPG, PNG (máximo de 1 MB)"
    simpleTitle="Arraste sua foto ou"
    actionTitle="selecione um arquivo"
    accept=".png, .jpg"
    [supportedExtensions]="['png', 'jpg']"
    [maxFileSize]="1048576"
    (invalidFile)="onArquivoInvalido($event)"
  ></s-profile-picture-picker>
</form>
```

### Edição com imagem pré-carregada

```html
<form [formGroup]="form">
  <!-- O formControl recebe a string base64 da imagem atual -->
  <s-profile-picture-picker
    formControlName="foto"
    subtitle="Formato: JPG, PNG"
    [changeButtonLabel]="'Trocar foto'"
    [removeButtonLabel]="'Excluir foto'"
    [confirmationTexts]="confirmacaoTextos"
  ></s-profile-picture-picker>
</form>
```

### Com aspect ratio widescreen (banner)

```html
<s-profile-picture-picker
  formControlName="capa"
  subtitle="Formato: JPG, PNG — proporção 16:9"
  [aspectRatio]="16 / 9"
></s-profile-picture-picker>
```

## Acessibilidade

- A área de upload aceita foco via teclado e interação por clique
- O drag & drop é complementar — sempre há o botão clicável como alternativa
- O diálogo de confirmação de remoção usa PrimeNG `ConfirmDialog`, que é acessível por teclado
- O thumbnail é decorativo e não carece de texto alternativo quando a imagem é de perfil do usuário logado

## Componentes relacionados

- [`ImageCropper`](../image-cropper/README.md) — cropper de imagem usado internamente
- [`Thumbnail`](../thumbnail/README.md) — exibição de imagem em miniatura
- [`FilePicker`](../file-picker/README.md) — seleção de arquivos genérica
