# Organization SDK

SDK for accessing the organization service from Next.js or React applications. Includes pre-built UI components and hooks for managing organizations, members, and invitations.

## 📚 Documentation

**Full documentation available at:** [https://ktw-organization-docs.netlify.app/](https://ktw-organization-docs.netlify.app/)

For complete guides, API reference, examples, and integration instructions, visit the documentation site.

## Installation

```bash
npm install @thetechfossil/organization-sdk
```

## Quick Start

### 1. Setup Provider

Wrap your app with the `OrganizationProvider`:

```tsx
import { OrganizationProvider } from '@thetechfossil/organization-sdk';

function App() {
  return (
    <OrganizationProvider
      config={{
        baseUrl: 'http://localhost:4111',
        getToken: () => localStorage.getItem('token') || '',
      }}
    >
      <YourApp />
    </OrganizationProvider>
  );
}
```

### 2. Use Pre-built Components

```tsx
import {
  OrganizationList,
  CreateOrganizationForm,
  OrganizationDropdown,
  MemberList,
  InviteMemberForm
} from '@thetechfossil/organization-sdk';

function MyPage() {
  const [selectedOrg, setSelectedOrg] = useState(null);

  return (
    <div>
      {/* List all organizations */}
      <OrganizationList
        onSelect={(org) => setSelectedOrg(org)}
        onCreateClick={() => setShowCreateForm(true)}
      />

      {/* Organization dropdown selector */}
      <OrganizationDropdown
        value={selectedOrg?.id}
        onChange={(id, org) => setSelectedOrg(org)}
      />

      {/* Create organization form */}
      <CreateOrganizationForm
        onSuccess={(org) => console.log('Created:', org)}
        onCancel={() => setShowCreateForm(false)}
      />

      {/* Member list with management */}
      <MemberList
        organizationId={selectedOrg?.id}
        canManageMembers={true}
        onInviteClick={() => setShowInviteForm(true)}
      />

      {/* Invite member form */}
      <InviteMemberForm
        organizationId={selectedOrg?.id}
        onSuccess={(invitation) => console.log('Invited:', invitation)}
      />
    </div>
  );
}
```

## UI Components

### CreateOrganizationForm

Form for creating a new organization with auto-generated slug.

```tsx
<CreateOrganizationForm
  onSuccess={(organization) => {
    console.log('Created:', organization);
  }}
  onCancel={() => setShowForm(false)}
/>
```

### OrganizationList

Grid display of all user's organizations with optional create button.

```tsx
<OrganizationList
  onSelect={(org) => navigate(`/org/${org.id}`)}
  onCreateClick={() => setShowCreateForm(true)}
  showCreateButton={true}
/>
```

### OrganizationDropdown

Dropdown selector for choosing an organization.

```tsx
<OrganizationDropdown
  value={currentOrgId}
  onChange={(id, org) => setCurrentOrg(org)}
  placeholder="Select organization"
/>
```

### MemberList

List of organization members with role management, removal, and customizable role labels.

```tsx
// Basic usage with default roles
<MemberList
  organizationId={orgId}
  canManageMembers={isAdmin}
  showInviteButton={true}
  onInviteClick={() => setShowInviteForm(true)}
/>

// With custom roles for your application
<MemberList
  organizationId={orgId}
  canManageMembers={true}
  roles={[
    { value: 'ADMIN', label: 'Administrator' },
    { value: 'MANAGER', label: 'Manager' },
    { value: 'SALES', label: 'Sales Staff' },
    { value: 'SUPPORT', label: 'Support Staff' }
  ]}
  onInviteClick={() => setShowInviteForm(true)}
/>
```

### InviteMemberForm

Form for inviting new members via email with customizable roles.

```tsx
// Basic usage with default business roles
<InviteMemberForm
  organizationId={orgId}
  onSuccess={(invitation) => {
    console.log('Invitation sent:', invitation);
  }}
  onCancel={() => setShowForm(false)}
/>

// With custom roles for your application
<InviteMemberForm
  organizationId={orgId}
  roles={[
    { value: 'ADMIN', label: 'Administrator' },
    { value: 'MANAGER', label: 'Manager' },
    { value: 'SALES', label: 'Sales Staff' },
    { value: 'SUPPORT', label: 'Support Staff' }
  ]}
  onSuccess={(invitation) => console.log('Invited:', invitation)}
/>

// Hospital application example
<InviteMemberForm
  organizationId={orgId}
  roles={[
    { value: 'ADMIN', label: 'Administrator' },
    { value: 'DOCTOR', label: 'Doctor' },
    { value: 'NURSE', label: 'Nurse' },
    { value: 'RECEPTIONIST', label: 'Receptionist' }
  ]}
  onSuccess={(invitation) => console.log('Invited:', invitation)}
/>
```

### LogoUploader

Simple logo uploader with drag-and-drop support.
When `OrganizationProvider` has `getToken`, the SDK auto-provisions in-house Upfiles access with the user's JWT. Do not pass browser-exposed API keys.

```tsx
<LogoUploader
  value={logoUrl}
  onChange={setLogoUrl}
  folderPath="logos/"
  size={120}
/>
```

### ImagePicker

Versatile image picker with optional ImageManager integration.

```tsx
// Basic usage - direct upload
<ImagePicker
  value={imageUrl}
  onChange={(url, image) => setImageUrl(url)}
  label="Cover Image"
  shape="rounded" // 'square' | 'circle' | 'rounded'
  size={150}
/>

// With ImageManager from @thetechfossil/upfiles
import { ImageManager } from '@thetechfossil/upfiles';

<ImagePicker
  value={imageUrl}
  onChange={(url, image) => setImageUrl(url)}
  label="Select Image"
  renderImageManager={({ open, onOpenChange, onSelect, clientOptions }) => (
    <ImageManager
      open={open}
      onOpenChange={onOpenChange}
      onSelect={onSelect}
      clientOptions={clientOptions}
      title="Media Library"
    />
  )}
/>
```

## Hooks

### useOrganizationClient

Get the organization client instance.

```tsx
const client = useOrganizationClient();
```

### useOrganizations

Manage organizations list.

```tsx
const { organizations, loading, error, refetch, createOrganization } = useOrganizations(client);
```

### useOrganization

Get single organization details.

```tsx
const { organization, loading, error, updateOrganization } = useOrganization(client, orgId);
```

### useMembers

Manage organization members.

```tsx
const { members, loading, error, addMember, removeMember } = useMembers(client, orgId);
```

### useInvitations

Manage invitations.

```tsx
const { invitations, loading, error, inviteMember } = useInvitations(client, orgId);
```

## Server-Side Usage

For Next.js API routes or server components:

```typescript
import { OrganizationClient } from '@thetechfossil/organization-sdk';

const client = new OrganizationClient({
  baseUrl: process.env.ORGANIZATION_SERVICE_URL!,
  getToken: async () => {
    const session = await getServerSession();
    return session.token;
  },
});

const organizations = await client.getMyOrganizations();
```

## API Reference

### Client Methods

**Organizations:**
- `createOrganization(data: CreateOrganizationDto): Promise<Organization>`
- `getOrganization(id: string): Promise<Organization>`
- `getMyOrganizations(): Promise<Organization[]>`
- `updateOrganization(id: string, data: UpdateOrganizationDto): Promise<Organization>`
- `deleteOrganization(id: string): Promise<void>`

**Members:**
- `addMember(organizationId: string, data: AddMemberDto): Promise<OrganizationMember>`
- `getMembers(organizationId: string): Promise<OrganizationMember[]>`
- `updateMember(memberId: string, data: UpdateMemberDto): Promise<OrganizationMember>`
- `removeMember(memberId: string): Promise<void>`

**Groups:**
- `createGroup(organizationId: string, data: CreateGroupDto): Promise<UserGroup>`
- `getGroups(organizationId: string): Promise<UserGroup[]>`
- `addMemberToGroup(groupId: string, memberId: string): Promise<void>`
- `removeMemberFromGroup(groupId: string, memberId: string): Promise<void>`
- `deleteGroup(groupId: string): Promise<void>`

**Invitations:**
- `inviteMember(organizationId: string, data: InviteMemberDto): Promise<Invitation>`
- `acceptInvitation(token: string): Promise<Organization>`
- `getInvitations(organizationId: string): Promise<Invitation[]>`

## Types

```typescript
import {
  CommonRoles,
  Organization,
  OrganizationMember,
  UserGroup,
  Invitation,
  InvitationStatus
} from '@thetechfossil/organization-sdk';

// Common Roles (convenience constants)
CommonRoles.ADMIN    // 'ADMIN'
CommonRoles.MANAGER  // 'MANAGER'
CommonRoles.SALES    // 'SALES'
CommonRoles.SUPPORT  // 'SUPPORT'
CommonRoles.USER     // 'USER'

// Roles are flexible strings - define your own!
const myCustomRoles = ['ADMIN', 'DOCTOR', 'NURSE', 'PATIENT'];

// Invitation Status
InvitationStatus.PENDING
InvitationStatus.ACCEPTED
InvitationStatus.REJECTED
InvitationStatus.EXPIRED
```

## Custom Roles

Roles are now **flexible strings** - each application can define its own roles without being limited to predefined values.

### Quick Example

```tsx
// Business Application
const businessRoles = [
  { value: 'ADMIN', label: 'Administrator' },
  { value: 'MANAGER', label: 'Manager' },
  { value: 'SALES', label: 'Sales Staff' },
  { value: 'SUPPORT', label: 'Support Staff' },
];

<InviteMemberForm roles={businessRoles} />
<MemberList roles={businessRoles} />

// Hospital Application
const hospitalRoles = [
  { value: 'ADMIN', label: 'Administrator' },
  { value: 'DOCTOR', label: 'Doctor' },
  { value: 'NURSE', label: 'Nurse' },
  { value: 'RECEPTIONIST', label: 'Receptionist' },
];

<InviteMemberForm roles={hospitalRoles} />
<MemberList roles={hospitalRoles} />

// School Application
const schoolRoles = [
  { value: 'ADMIN', label: 'Administrator' },
  { value: 'TEACHER', label: 'Teacher' },
  { value: 'STUDENT', label: 'Student' },
  { value: 'PARENT', label: 'Parent' },
];

<InviteMemberForm roles={schoolRoles} />
<MemberList roles={schoolRoles} />
```

### Common Role Constants

For convenience, the SDK provides common role constants:

```typescript
import { CommonRoles } from '@thetechfossil/organization-sdk';

CommonRoles.ADMIN    // 'ADMIN'
CommonRoles.MANAGER  // 'MANAGER'
CommonRoles.SALES    // 'SALES'
CommonRoles.SUPPORT  // 'SUPPORT'
CommonRoles.USER     // 'USER'
```

## Theming

Components automatically adapt to light/dark mode based on system preferences or the `dark` class on the document element.

## License

MIT
