openapi: 3.0.2
info:
  title: AAC Beacon - Source Documentation
  description: >-
    This document describes the functions, hooks, and components of the AAC
    Beacon

    React Native application using the OpenAPI 3.0 specification format as a

    structured reference for all exported modules.


    Each tag corresponds to a source file. Each path corresponds to a callable

    function or hook. Parameters map to function arguments and responses map to

    return values or side effects.


    Source files covered:

    - tts.js

    - WordGrid.js

    - SentenceBar.js

    - RoomSelector.js

    - InteractionLogModal.js

    - CategoryTabs.js

    - AppHeader.js

    - useSpeech.js

    - useSentenceBuilder.js

    - useSentence.js

    - useLocationDetection.js

    - useInteractionLogger.js
  version: 1.0.0
tags:
  - name: tts
    description: Text-to-speech service layer wrapping expo-speech
  - name: WordGrid
    description: Scrollable grid component for displaying and selecting word tiles
  - name: SentenceBar
    description: Horizontal bar component for displaying and managing the built sentence
  - name: RoomSelector
    description: Room chip selector component — manual BLE placeholder
  - name: InteractionLogModal
    description: Full-screen modal for viewing and exporting interaction logs
  - name: CategoryTabs
    description: Tab bar component for selecting word categories
  - name: AppHeader
    description: Top header bar component showing room context and log access
  - name: useSpeech
    description: Custom hook exposing TTS controls to components
  - name: useSentenceBuilder
    description: Custom hook for sentence state management with interaction logging
  - name: useSentence
    description: Custom hook for sentence state management with integrated TTS feedback
  - name: useLocationDetection
    description: Custom hook abstracting room/location detection with BLE upgrade path
  - name: useInteractionLogger
    description: Custom hook for recording and managing user interaction log entries
paths:
  /tts/speak:
    post:
      tags:
        - tts
      summary: Speak text aloud
      description: |-
        Speaks the given text using the device speech engine (expo-speech).
        Stops any currently playing speech before starting a new utterance.
        Does nothing if the text is empty or whitespace only.
        Language is en-US, rate 0.9, pitch 1.0.
      operationId: speak
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - text
              properties:
                text:
                  type: string
                  description: The text to be spoken aloud
                  example: I want water
      responses:
        '200':
          description: Speech started successfully or skipped (empty input)
        '204':
          description: No content — text was empty or whitespace, speech skipped
  /tts/stop:
    post:
      tags:
        - tts
      summary: Stop current speech
      description: Immediately stops any ongoing speech playback.
      operationId: stop
      responses:
        '200':
          description: Speech stopped successfully
  /WordGrid/render:
    post:
      tags:
        - WordGrid
      summary: Render the word tile grid
      description: >-
        Renders a scrollable grid of word tiles. Each tile displays an emoji and

        a label. Pressing a tile invokes the onAddWord callback with the word
        label.

        Tile background is tinted and bordered using the active category color.
      operationId: renderWordGrid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WordGridProps'
      responses:
        '200':
          description: Component rendered successfully
        '400':
          description: Missing or invalid props
  /SentenceBar/render:
    post:
      tags:
        - SentenceBar
      summary: Render the sentence bar
      description: |-
        Renders a horizontal bar showing the current sentence as individual word
        chips, along with backspace, clear, and speak action buttons.
        Displays a placeholder when the sentence is empty.
      operationId: renderSentenceBar
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SentenceBarProps'
      responses:
        '200':
          description: Component rendered successfully
        '400':
          description: Missing or invalid props
  /RoomSelector/render:
    post:
      tags:
        - RoomSelector
      summary: Render the room selector chip row
      description: >-
        Renders a horizontally scrollable row of room chips for manually

        simulating room entry. Includes a "General" chip to clear the room
        context.

        This component is a placeholder for Bluetooth beacon detection — once
        BLE

        is integrated it can be hidden or used as a manual override only.
      operationId: renderRoomSelector
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RoomSelectorProps'
      responses:
        '200':
          description: Component rendered successfully
        '400':
          description: Missing or invalid props
  /InteractionLogModal/render:
    post:
      tags:
        - InteractionLogModal
      summary: Render the interaction log modal
      description: >-
        Renders a full-screen modal displaying all recorded interaction log
        entries

        in reverse chronological order. Includes an Export JSON button that

        triggers a file download on web or the native share sheet on mobile.

        The export button is disabled when there are no logs.
      operationId: renderInteractionLogModal
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/InteractionLogModalProps'
      responses:
        '200':
          description: Modal rendered successfully
        '400':
          description: Missing or invalid props
  /InteractionLogModal/formatTimestamp:
    get:
      tags:
        - InteractionLogModal
      summary: Format a timestamp value to a locale string
      description: >-
        Converts a timestamp value to a human-readable locale date/time string.

        Returns the original value unchanged if it cannot be parsed as a valid
        Date.
      operationId: formatTimestamp
      parameters:
        - name: value
          in: query
          required: true
          description: An ISO date string or numeric timestamp to format
          schema:
            type: string
            example: '2024-05-01T10:30:00.000Z'
      responses:
        '200':
          description: Formatted timestamp string returned
          content:
            application/json:
              schema:
                type: object
                properties:
                  result:
                    type: string
                    example: 5/1/2024, 10:30:00 AM
        '400':
          description: Invalid or unparseable timestamp value
  /InteractionLogModal/handleExportJson:
    post:
      tags:
        - InteractionLogModal
      summary: Export interaction logs as JSON
      description: >-
        Serializes all log entries into a JSON payload with metadata
        (exportedAt,

        totalLogs). On web platforms, triggers a file download. On native
        platforms,

        opens the system share sheet. Disables itself while an export is in
        progress.

        No-op if there are no logs.
      operationId: handleExportJson
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                logs:
                  type: array
                  items:
                    $ref: '#/components/schemas/LogEntry'
      responses:
        '200':
          description: Export triggered successfully
        '204':
          description: No logs to export — operation skipped
        '500':
          description: Export failed — alert shown to user
  /CategoryTabs/render:
    post:
      tags:
        - CategoryTabs
      summary: Render category tab buttons
      description: >-
        Renders a row of tappable category tabs. The active tab is highlighted

        with its assigned category color. Pressing a tab invokes
        onSelectCategory.
      operationId: renderCategoryTabs
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CategoryTabsProps'
      responses:
        '200':
          description: Component rendered successfully
        '400':
          description: Missing or invalid props
  /AppHeader/render:
    post:
      tags:
        - AppHeader
      summary: Render the app header bar
      description: |-
        Renders the top header showing the AAC Beacon title, the current room
        context (emoji + label, or "General" if no room is set), and a
        "View Logs" button.
      operationId: renderAppHeader
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AppHeaderProps'
      responses:
        '200':
          description: Component rendered successfully
        '400':
          description: Missing or invalid props
  /useSpeech:
    get:
      tags:
        - useSpeech
      summary: Initialize the speech hook
      description: |-
        Custom hook that wraps the TTS service and exposes speakText and
        stopSpeech helpers to React components.
      operationId: useSpeech
      responses:
        '200':
          description: Hook initialized — returns TTS control functions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UseSpeechReturn'
  /useSentenceBuilder:
    post:
      tags:
        - useSentenceBuilder
      summary: Initialize the sentence builder hook
      description: >-
        Custom hook that manages sentence state and logs every sentence-related

        user action via the provided onLogPress callback. Intended as the
        primary

        sentence hook when interaction logging is required.
      operationId: useSentenceBuilder
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                onLogPress:
                  type: string
                  description: Callback reference — (buttonName, metadata?) => void
                  example: logButtonPress
      responses:
        '200':
          description: Hook initialized — returns sentence state and action functions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UseSentenceBuilderReturn'
  /useSentenceBuilder/addWord:
    post:
      tags:
        - useSentenceBuilder
      summary: Append a word to the sentence
      description: >-
        Appends a word to the current sentence array and logs a word_tile press
        event.
      operationId: addWord_builder
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - word
              properties:
                word:
                  type: string
                  example: water
      responses:
        '200':
          description: Word appended and logged
  /useSentenceBuilder/removeLastWord:
    post:
      tags:
        - useSentenceBuilder
      summary: Remove the last word from the sentence
      description: >-
        Removes the last word in the sentence array and logs a remove_last_word
        event.
      operationId: removeLastWord_builder
      responses:
        '200':
          description: Last word removed and logged
  /useSentenceBuilder/clearSentence:
    post:
      tags:
        - useSentenceBuilder
      summary: Clear the entire sentence
      description: Resets the sentence array to empty and logs a clear_sentence event.
      operationId: clearSentence_builder
      responses:
        '200':
          description: Sentence cleared and logged
  /useSentenceBuilder/speakSentence:
    post:
      tags:
        - useSentenceBuilder
      summary: Speak the full sentence
      description: |-
        Shows a native Alert with the full sentence joined by spaces and logs
        a speak_sentence event. No-op if the sentence is empty.
      operationId: speakSentence_builder
      responses:
        '200':
          description: Sentence spoken (or skipped if empty)
  /useSentence:
    get:
      tags:
        - useSentence
      summary: Initialize the sentence hook with TTS feedback
      description: |-
        Custom hook managing sentence state with immediate TTS feedback on each
        word added. Also supports speaking the full sentence on demand and
        clearing with speech stopped.
      operationId: useSentence
      responses:
        '200':
          description: Hook initialized — returns sentence state and action functions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UseSentenceReturn'
  /useSentence/addWord:
    post:
      tags:
        - useSentence
      summary: Append a word and speak it immediately
      description: >-
        Appends a word to the sentence array and immediately speaks that word
        via TTS.
      operationId: addWord_sentence
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - word
              properties:
                word:
                  type: string
                  example: hungry
      responses:
        '200':
          description: Word appended and spoken
  /useSentence/speakSentence:
    post:
      tags:
        - useSentence
      summary: Speak the full sentence
      description: >-
        Joins all words with spaces and passes the result to the TTS speak
        function.
      operationId: speakSentence_sentence
      responses:
        '200':
          description: Full sentence spoken via TTS
  /useSentence/clear:
    post:
      tags:
        - useSentence
      summary: Clear sentence and stop speech
      description: >-
        Resets the sentence array to empty and calls TTS stop to halt any
        ongoing speech.
      operationId: clear_sentence
      responses:
        '200':
          description: Sentence cleared and speech stopped
  /useLocationDetection:
    get:
      tags:
        - useLocationDetection
      summary: Initialize the location detection hook
      description: |-
        Abstraction layer for room/location detection. Currently operates in
        manual mode via setRoomManually. Designed so that Bluetooth beacon
        scanning can replace the internals in the future without changing the
        hook's return shape or any consuming components.
      operationId: useLocationDetection
      responses:
        '200':
          description: Hook initialized — returns room state and control functions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UseLocationDetectionReturn'
  /useLocationDetection/setRoomManually:
    post:
      tags:
        - useLocationDetection
      summary: Manually set the active room by ID
      description: |-
        Looks up a room by ID from the full rooms list and sets it as the
        current room. Pass null to clear the active room and revert to General.
      operationId: setRoomManually
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                roomId:
                  type: string
                  nullable: true
                  description: The ID of the room to activate, or null to clear
                  example: kitchen
      responses:
        '200':
          description: Room updated successfully
        '404':
          description: Room ID not found in the available rooms list
  /useInteractionLogger:
    post:
      tags:
        - useInteractionLogger
      summary: Initialize the interaction logger hook
      description: >-
        Custom hook that maintains a session-scoped log of user interaction
        events.

        Generates a pseudo-unique device ID on mount combining platform OS,
        version,

        and a random suffix. Each logged entry captures the button name, ISO
        timestamp,

        device ID, room context, and any extra metadata fields.
      operationId: useInteractionLogger
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                currentRoom:
                  $ref: '#/components/schemas/Room'
      responses:
        '200':
          description: Hook initialized — returns device ID, logs array, and logButtonPress
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UseInteractionLoggerReturn'
  /useInteractionLogger/logButtonPress:
    post:
      tags:
        - useInteractionLogger
      summary: Record a new interaction log entry
      description: |-
        Creates and appends a new log entry to the interactionLogs array.
        The entry merges deviceId, buttonName, pressedAt (ISO string), location
        (derived from currentRoom), and any extra fields from metadata.
        Also prints the entry to the console via JSON.stringify.
      operationId: logButtonPress
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - buttonName
              properties:
                buttonName:
                  type: string
                  description: Identifier of the button or action triggered
                  example: word_tile
                metadata:
                  type: object
                  description: Optional additional fields merged into the log entry
                  example:
                    word: water
                    sentenceLength: 3
                    category: Drinks
      responses:
        '200':
          description: Log entry recorded and printed to console
  /useInteractionLogger/createDeviceId:
    get:
      tags:
        - useInteractionLogger
      summary: Generate a pseudo-unique device identifier
      description: |-
        Builds a device ID string in the format {os}-{version}-{randomSuffix}
        using Platform.OS, Platform.Version, and a random base-36 suffix.
        Called once on hook mount.
      operationId: createDeviceId
      responses:
        '200':
          description: Device ID string generated
          content:
            application/json:
              schema:
                type: object
                properties:
                  deviceId:
                    type: string
                    example: ios-17-x4f2a9b3
components:
  schemas:
    Room:
      type: object
      properties:
        id:
          type: string
          example: kitchen
        label:
          type: string
          example: Kitchen
        emoji:
          type: string
          example: 🍳
        color:
          type: string
          example: '#FF6B6B'
    Word:
      type: object
      required:
        - label
        - emoji
      properties:
        label:
          type: string
          example: water
        emoji:
          type: string
          example: 💧
    LogEntry:
      type: object
      properties:
        deviceId:
          type: string
          example: android-33-ab12cd34
        buttonName:
          type: string
          example: word_tile
        pressedAt:
          type: string
          format: date-time
          example: '2024-05-01T10:30:00.000Z'
        location:
          type: object
          properties:
            id:
              type: string
              example: kitchen
            label:
              type: string
              example: Kitchen
        word:
          type: string
          example: water
        sentenceLength:
          type: integer
          example: 3
        category:
          type: string
          example: Drinks
    WordGridProps:
      type: object
      required:
        - words
        - activeCategoryColor
        - onAddWord
      properties:
        words:
          type: array
          items:
            $ref: '#/components/schemas/Word'
        activeCategoryColor:
          type: string
          description: Hex color string for tile tint and border
          example: '#4CAF50'
        onAddWord:
          type: string
          description: 'Callback reference — (label: string) => void'
          example: addWord
    SentenceBarProps:
      type: object
      required:
        - sentence
        - onRemoveLastWord
        - onClearSentence
        - onSpeakSentence
      properties:
        sentence:
          type: array
          items:
            type: string
          example:
            - I
            - want
            - water
        onRemoveLastWord:
          type: string
          description: Callback reference — () => void
        onClearSentence:
          type: string
          description: Callback reference — () => void
        onSpeakSentence:
          type: string
          description: Callback reference — () => void
    RoomSelectorProps:
      type: object
      required:
        - rooms
        - activeRoomId
        - onSelectRoom
      properties:
        rooms:
          type: array
          items:
            $ref: '#/components/schemas/Room'
        activeRoomId:
          type: string
          nullable: true
          example: kitchen
        onSelectRoom:
          type: string
          description: 'Callback reference — (roomId: string | null) => void'
    InteractionLogModalProps:
      type: object
      required:
        - visible
        - logs
        - onClose
      properties:
        visible:
          type: boolean
          example: true
        logs:
          type: array
          items:
            $ref: '#/components/schemas/LogEntry'
        onClose:
          type: string
          description: Callback reference — () => void
    CategoryTabsProps:
      type: object
      required:
        - categories
        - activeCategory
        - categoryColors
        - onSelectCategory
      properties:
        categories:
          type: object
          description: Object whose keys are category name strings
          example:
            Drinks: []
            Food: []
            Feelings: []
        activeCategory:
          type: string
          example: Drinks
        categoryColors:
          type: object
          description: Map of category keys to hex color strings
          example:
            Drinks: '#2196F3'
            Food: '#4CAF50'
        onSelectCategory:
          type: string
          description: 'Callback reference — (category: string) => void'
    AppHeaderProps:
      type: object
      required:
        - onViewLogs
      properties:
        currentRoom:
          $ref: '#/components/schemas/Room'
          nullable: true
        onViewLogs:
          type: string
          description: Callback reference — () => void
    UseSpeechReturn:
      type: object
      properties:
        speakText:
          type: string
          description: 'Function — (text: string) => void — speaks the given text'
        stopSpeech:
          type: string
          description: Function — () => void — stops any ongoing speech
    UseSentenceBuilderReturn:
      type: object
      properties:
        sentence:
          type: array
          items:
            type: string
          example:
            - I
            - want
            - water
        addWord:
          type: string
          description: 'Function — (word: string) => void'
        removeLastWord:
          type: string
          description: Function — () => void
        clearSentence:
          type: string
          description: Function — () => void
        speakSentence:
          type: string
          description: Function — () => void
    UseSentenceReturn:
      type: object
      properties:
        sentence:
          type: array
          items:
            type: string
          example:
            - I
            - am
            - hungry
        addWord:
          type: string
          description: 'Function — (word: string) => void — appends and speaks word'
        speakSentence:
          type: string
          description: Function — () => void — speaks full sentence
        clear:
          type: string
          description: Function — () => void — clears sentence and stops speech
    UseLocationDetectionReturn:
      type: object
      properties:
        currentRoom:
          $ref: '#/components/schemas/Room'
          nullable: true
        detectionMode:
          type: string
          enum:
            - manual
            - bluetooth
          example: manual
        setRoomManually:
          type: string
          description: 'Function — (roomId: string | null) => void'
        allRooms:
          type: array
          items:
            $ref: '#/components/schemas/Room'
    UseInteractionLoggerReturn:
      type: object
      properties:
        deviceId:
          type: string
          description: Stable pseudo-unique device identifier for this session
          example: ios-17-x4f2a9b3
        interactionLogs:
          type: array
          items:
            $ref: '#/components/schemas/LogEntry'
        logButtonPress:
          type: string
          description: 'Function — (buttonName: string, metadata?: object) => void'
