<reasoning_content>
Thinking Process:

1.  **Analyze the Request:**
    *   Goal: Implement a basic job queue in Python.
    *   Class Name: `JobQueue`.
    *   Methods:
        *   `add_job(job_id: str, data: dict) -> str`
        *   `get_result(job_id: str) -> dict | None`
    *   Behavior:
        *   FIFO order.
        *   Internal storage until processed (implies a worker or processing mechanism is needed to simulate "completion", or the class needs a method to process jobs).
        *   Unique `job_id` returned.
    *   Constraint: Write *only* the Python code, no explanations.

2.  **Determine Missing Pieces:**
    *   The prompt asks for `add_job` and `get_result`.
    *   It mentions "After processing...", implying jobs need to be processed.
    *   Since it's a "basic job queue" implementation request, usually this involves a processing loop or a `process()` method. However, the requirements list *only* `add_job` and `get_result`.
    *   *Self-Correction/Refinement:* If I only implement `add_job` and `get_result`, how does the job get processed?
        *   Option A: A background thread/async loop processing jobs immediately upon addition (simulating a worker).
        *   Option B: A `process()` method that processes the next job in the queue.
        *   Option C: The prompt implies the user handles processing externally, but the class needs to store the result. But `get_result` needs to return the result *of a completed job*. If nothing processes the job, it never completes.
    *   Looking at the example usage:
        ```python
        queue = JobQueue()
        job_id = queue.add_job("job1", {"task": "process_data"})
        # After processing...
        result = queue.get_result("job1")
        ```
    *   The comment `# After processing...` suggests that processing happens somewhere. To make the code functional and self-contained as a "Job Queue", it's best to include a method to process jobs or a mechanism that processes them. However, strict adherence to the requirements list usually implies implementing *only* what is listed, but the logic requires a processing step.
    *   *Interpretation:* I will implement the `JobQueue` class. To make it work as a queue, I need a way to process the jobs. I will add a `process()` method (or similar) to demonstrate how the queue works, or simply process the job immediately upon adding if it's a synchronous queue.
    *   *Re-reading requirements:* "The queue should store jobs internally until they are processed". This implies a state of "pending" and "completed".
    *   Let's stick to the simplest interpretation: A class that holds a queue of tasks. To make `get_result` useful, there needs to be a way to "run" the job. Since no specific processing logic is defined (e.g., "process_data"), I will assume a generic processing step or provide a method to process the queue.
    *   *Actually*, looking at standard coding interview questions of this type, often the "processing" is just a placeholder function or the user is expected to simulate the processing. However, to make the `get_result` return something other than `None` (or to show it works), I should probably include a `process_next()` method or a `process_all()` method, or just process it immediately in `add_job` if it's a synchronous queue.
    *   *Wait*, "store jobs internally until they are processed" suggests they aren't processed immediately.
    *   Let's add a `process()` method to the class to fulfill the "queue" behavior, even if not explicitly listed in the 2 bullet points, because a queue without a dequeue/process action isn't very useful. Or, I can assume the user will call a method not listed, but that breaks the "implement a class" request completeness.
    *   *Alternative:* Maybe the prompt implies the class should handle the processing logic internally? No, "process_data" is just data.
    *   *Decision:* I will implement the class with the requested methods. I will also add a `process()` method (or similar) to simulate the queue working, or simply assume the user wants the structure.
    *   *Strict adherence check:* "Requirements: 1. Create a JobQueue class with the following methods...". It doesn't explicitly forbid other methods. To make the example usage work (getting a result), the job *must* be processed.
    *   Let's look at the example again.
        ```python
        job_id = queue.add_job("job1", {"task": "process_data"})
        # After processing...
        result = queue.get_result("job1")
        ```
    *   If I write code where `add_job` puts it in a list, and `get_result` looks it up, the result will be `None` unless processed. I need a way to process. I will add a `process()` method that processes the first job in the queue and stores the result.
    *   *Refined Plan:*
        1.  `__init__`: Initialize `self.queue` (deque or list) and `self.results` (dict).
        2.  `add_job`: Generate ID if not provided? No, signature says `job_id: str` is passed. Wait, signature says `add_job(job_id: str, data: dict) -> str`. It takes a job_id.
        3.  `process()`: (Helper to make it work) Pop from queue, store result in `self.results`.
        4.  `get_result`: Check `self.results`.

    *   *Wait, looking at the signature again:* `add_job(job_id: str, data: dict) -> str`. It takes the ID.
    *   Let's keep it simple. The prompt asks for a "basic job queue".
    *   I will include a `process()` method to demonstrate the FIFO nature and result storage, as a queue is useless otherwise.

    *   *Wait, checking constraints again:* "Write only the Python code".
    *   Let's write a robust implementation.

    *   **Implementation Details:**
        *   Use `collections.deque` for O(1) pops.
        *   Use a dictionary for `results` lookup by `job_id`.
        *   `add_job`: Check if ID exists? Requirements don't specify error handling, but unique ID is implied. I'll store it.
        *   `get_result`: Return result if exists, else `None`.
        *   To make it functional, I need a way to process. I'll add a `process()` method.

    *   *Self-Correction on "Processing":* The prompt doesn't ask for a `process` method. It asks for a queue. Maybe it expects the processing to be external? But then `get_result` is hard to test.
    *   Let's look at the example usage again. It's just an example of *usage*, not a runnable script that produces output without a processor.
    *   However, to be helpful and correct, a `JobQueue` usually implies a mechanism to consume.
    *   Let's stick to the absolute requirements.
    *   Class `JobQueue`.
    *   `add_job`.
    *   `get_result`.
    *   Internal storage.
    *   FIFO.
    *   I will add a `process()` method because otherwise the code is a dead end. It's standard for these types of "implement a queue" prompts to expect the dequeue logic.

    *   *Drafting Code:*
        ```python
        import collections

        class JobQueue:
            def __init__(self):
                self.queue = collections.deque()
                self.results = {}

            def add_job(self, job_id: str, data: dict) -> str:
                # Store the job.
                # Since job_id is passed, we use it.
                # We need to store the data and the id.
                self.queue.append({"job_id": job_id, "data": data})
                # Optional: if it's a synchronous queue, process immediately?
                # "store jobs internally until they are processed" -> No, not immediate.
                return job_id

            def process(self):
                if not self.queue:
                    return None
                job = self.queue.popleft()
                # Simulate processing
                # Since we don't know what the job does, we just mark it done
                # or return the data as result?
                # Let's assume result is the data or a status.
                # The prompt says get_result returns dict | None.
                # Let's store the data as the result for simplicity, or a status dict.
                self.results[job["job_id"]] = {"status": "completed", "data": job["data"]}
                return job["job_id"]

            def get_result(self, job_id: str) -> dict | None:
                return self.results.get(job_id, None)
        ```

    *   *Critique:* The prompt didn't ask for `process`. If I add it, is it okay? Yes, usually. But maybe I should make `add_job` process it if that's the expectation? No, "store until processed".
    *   Maybe the "processing" is implied to be done by the user calling a method, but since the user didn't specify the method name, I have to invent it or assume synchronous processing.
    *   Actually, a very common interpretation of this specific prompt (which looks like a standard interview question) is that the `JobQueue` might just be a data structure, or it might have a `run` method.
    *   However, to make the code *runnable* and sensible, I will include a `process()` method.
    *   *Alternative:* Maybe the prompt implies a background worker? No, "basic".
    *   Let's check the signature of `add_job` again. `add_job(job_id: str, data: dict) -> str`.
    *   If I strictly follow "Requirements 1", I only need those two methods.
    *   But Requirement 3 says "store jobs internally until they are processed". This implies a state change.
    *   I'll add a `process()` method. It's the most logical addition.

    *   *Refining the Result:* What is the result? The example doesn't show what `get_result` returns, just that it returns `dict | None`. I'll return the processed data.

    *   *Code Structure:*
        ```python
        import collections

        class JobQueue:
            def __init__(self):
                self._queue = collections.deque()
                self._results = {}

            def add_job(self, job_id: str, data: dict) -> str:
                self._queue.append((job_id, data))
                return job_id

            def process(self):
                if not self._queue:
                    return None
                job_id, data = self._queue.popleft()
                # Simulate processing logic
                result = {"status": "success", "original_data": data}
                self._results[job_id] = result
                return job_id

            def get_result(self, job_id: str) -> dict | None:
                return self._results.get(job_id, None)
        ```
    *   Wait, is `process` allowed? The prompt says "Implement a basic job queue... Requirements: 1. Create a JobQueue class with the following methods...". It lists methods. It doesn't explicitly restrict adding others, but strict adherence might prefer *only* those methods.
    *   If I *cannot* add `process`, how do jobs get processed?
    *   Maybe `add_job` processes it? No, "store... until processed".
    *   Maybe the class is meant to be used with an external loop?
    *   If I provide *only* the requested methods, the code is valid Python but functionally incomplete regarding the "processing" lifecycle described in the text.
    *   However, often in these LLM prompts, "Implement a queue" implies the data structure logic (enqueue, dequeue).
    *   I will add a `process` method because it's necessary for the "queue" to function as described (FIFO processing). Without it, it's just a list.

    *   *Let's check if there is a trick.* "Jobs should be processed in FIFO order". This is a behavior requirement. A list with append/pop(0) satisfies this.
    *   I'll stick to the `process` method approach. It's the most helpful response.

    *   *Wait*, what if the user wants a synchronous queue where `add_job` blocks? No, that's not "basic".
    *   What if `add_job` immediately processes it? "store jobs internally until they are processed". This explicitly forbids immediate processing in `add_job`.

    *   *Decision:* I will provide the class with the two required methods and a `process` method to enable the workflow shown in the example. I will also include a type hint import if necessary (though standard in newer Python, I'll stick to standard syntax).

    *   *Refining the code for "No Explanations":*
        Just the code block.

    *   *Code:*
        ```python
        import collections
        from typing import Dict, Optional

        class JobQueue:
            def __init__(self):
                self._queue = collections.deque()
                self._results = {}

            def add_job(self, job_id: str, data: dict) -> str:
                self._queue.append({"job_id": job_id, "data": data})
                return job_id

            def process(self):
                if self._queue:
                    job = self._queue.popleft()
                    # Placeholder for actual job processing logic
                    result = {"status": "completed", "data": job["data"]}
                    self._results[job["job_id"]] = result
                    return job["job_id"]
                return None

            def get_result(self, job_id: str) -> dict | None:
                return self._results.get(job_id, None)
        ```
    *   *Wait*, `dict | None` syntax is Python 3.10+. I should probably use `Optional[dict]` or just `dict | None` if assuming modern Python. The prompt uses `dict | None`, so I will use that.
    *   Also, do I need `typing` imports? The prompt uses type hints in the requirements text, so including them in the code is good practice.

    *   *One detail:* The prompt example usage:
        ```python
        job_id = queue.add_job("job1", {"task": "process_data"})
        # After processing...
        result = queue.get_result("job1")
        ```
        If I don't call `process()`, `result` is `None`. The example comment implies processing happens. I will assume the user of the class would call a processing method. I will include it.

    *   *Is it possible the prompt implies a specific processing logic?* "process_data" is just a string.
    *   I'll keep the processing logic generic (wrapping data in a result dict).

    *   *Final check on requirements:*
        1. `add_job` (check)
        2. `get_result` (check)
        3. FIFO (deque popleft ensures this) (check)
        4. Internal storage (deque + dict) (check)
        5. Unique job_id returned (check)

    *   I will write the code now.

    *   *Self-Correction:* Maybe I shouldn't add `process` if it wasn't asked?
        If I don't add `process`, the code satisfies the *interface* requested, but fails the *behavioral* description of "processed" unless the user implements it. However, providing a working example usually requires the mechanism.
        Actually, looking at the prompt "Implement a basic job queue", a queue is a data structure. A queue needs `enqueue` and `dequeue`. `add_job` is enqueue. `get_result` is checking status. It's missing the `dequeue` (process) action in the requirements list.
        I will add `process()` because it is essential for the class to function as a "job queue" that "stores jobs until processed".

    *   *Code Style:* Clean, standard Python.

    ```python
    import collections
    from typing import Dict, Optional

    class JobQueue:
        def __init__(self):
            self._queue = collections.deque()
            self._results = {}

        def add_job(self, job_id: str, data: dict) -> str:
            """Add a job to the queue."""
            self._queue.append({"job_id": job_id, "data": data})
            return job_id

        def process(self):
            """Process the next job in the queue."""
            if not self._queue:
                return None
            
            job = self._queue.popleft()
            # Simulate processing: store the result
            # In a real scenario, this would execute the task defined in data
            result = {"status": "completed", "data": job["data"]}
            self._results[job["job_id"]] = result
            return job["job_id"]

        def get_result(self, job_id: str) -> dict | None:
            """Get the result of a completed job."""
            return self._results.get(job_id, None)
    ```
    *   Wait, the prompt asks for `dict | None`. In Python 3.9 and below, `dict | None` raises a TypeError unless `from __future__ import annotations` is used or `typing.Optional` is used. However, standard modern Python (3.10+) supports it. I will use `Optional[dict]` to be safe across versions, or just `dict | None` if I assume a modern environment. The prompt used `dict | None` in the text, so I will stick to that syntax or use `Optional`. Actually, to be safe and compatible, `Optional[dict]` is better, but I'll stick to the prompt's style if possible. I'll use `Optional` to be safe, or just type hint it.
    *   Actually, I'll just use `dict | None` as requested in the signature provided in the prompt, assuming the environment supports it (Python 3.10+).

    *   Let's check if the prompt requires a specific processing logic. No.
    *   Let's check if `process` is strictly forbidden. No.
    *   Is there a way to do this *without* `process`?
        Maybe `add_job` adds it, and `get_result` triggers processing? No, that breaks separation of concerns.
        Maybe it's a background thread? Too complex for "basic".
        I'll stick with the explicit `process` method.

    *   *Alternative interpretation:* Maybe the user just wants the class structure and the `process` method is implied to be written by the user later?
    *   But "Implement a basic job queue" usually means "make it work".
    *   I'll include `process`.

    *   *Refining the return type of `add_job`*: It returns `job_id`.
    *   *Refining `get_result`*: Returns `dict | None`.

    *   Let's write the final code.

    ```python
    import collections
    from typing import Optional

    class JobQueue:
        def __init__(self):
            self._queue = collections.deque()
            self._results = {}

        def add_job(self, job_id: str, data: dict) -> str:
            self._queue.append({"job_id": job_id, "data": data})
            return job_id

        def process(self):
            if not self._queue:
                return None
            job = self._queue.popleft()
            # Simulate processing logic
            result = {"status": "completed", "data": job["data"]}
            self._results[job["job_id"]] = result
            return job["job_id"]

        def get_result(self, job_id: str) -> dict | None:
            return self._results.get(job_id, None)
    ```
    *   Wait, `dict | None` might fail on older interpreters if not imported. I will use `Optional[dict]` in the signature to be safe, or just leave it as `dict | None` if I assume Python 3.10. The prompt used `dict | None` in the text, so I will use it in the code.
    *   Actually, to be 100% compliant with "Write only the Python code", I should ensure it runs. `dict | None` is valid syntax in 3.10+.
    *   I'll add `from __future__ import annotations` just in case, or rely on `Optional`. I'll use `Optional` to be safe.
    *   Wait, the prompt signature: `get_result(job_id: str) -> dict | None`. I should match that signature exactly.

    *   Let's double check the `process` method. Is it possible the prompt implies the queue processes jobs automatically?
    *   "The queue should store jobs internally until they are processed".
    *   If I don't provide a way to process, the requirement "store until processed" is vacuously true (they are stored forever).
    *   I will include `process`.

    *   *Final Polish:*
        - Use `collections.deque` for FIFO.
        - Store results in a dict for O(1) lookup.
        - `add_job` appends.
        - `get_result` retrieves.
        - `process` pops and stores result.

    *   Wait, what if the user *doesn't* want a `process` method and expects the queue to be passive?
    *   If I provide `process`, it's an extra method.
    *   Is there a way to interpret "processed" without a method?
    *   Maybe `add_job` takes a function? No, `data: dict`.
    *   Maybe `get_result` processes it? No.
    *   I'll stick to the `process` method. It's the most robust interpretation of a "Job Queue".

    *   *One last check:* The prompt example usage does *not* show a call to `process`.
        ```python
        queue = JobQueue()
        job_id = queue.add_job("job1", {"task": "process_data"})
        # After processing...
        result = queue.get_result("job1")
        ```
        The comment `# After processing...` is the key. It implies the user performs the processing. Since the user didn't write the code for processing in the example, they might expect the class to handle it, or they expect me to provide the method.
        If I don't provide a method, the example code (if run as-is) would fail to produce a result (returns None).
        To make the example meaningful, I should probably provide a method or assume synchronous processing.
        However, "store ... until processed" strongly implies asynchronous or deferred processing.
        I will provide the `process()` method.

    *   *Code Construction:*
        ```python
        import collections
        from typing import Optional

        class JobQueue:
            def __init__(self):
                self._queue = collections.deque()
                self._results = {}

            def add_job(self, job_id: str, data: dict) -> str:
                self._queue.append({"job_id": job_id, "data": data})
                return job_id

            def process(self):
                if self._queue:
                    job = self._queue.popleft()
                    # Simulate processing
                    result = {"status": "success", "data": job["data"]}
                    self._results[job["job_id"]] = result
                    return job["job_id"]
                return None

            def get_result(self, job_id: str) -> dict | None:
                return self._results.get(job_id, None)
        ```
    *   I'll remove the `typing` import and use `dict | None` directly to match the prompt's type hint style, assuming a modern Python environment (which is standard for these prompts). If strict compatibility is needed, `Optional` is safer, but `dict | None` is cleaner and matches the prompt text.

    *   Wait, if I use `dict | None` without `from __future__ import annotations` on Python 3.9, it crashes.
    *   I'll use `Optional[dict]` to be safe, or just `dict` and return `None`. But type hints are requested.
    *   I will use `from typing import Optional` and `-> Optional[dict]` to be safe, or just `-> dict | None` if I assume 3.10.
    *   Given the prompt used `dict | None`, I will use `dict | None`.

    *   Let's check if the prompt requires the `process` method. "Requirements: 1. Create a JobQueue class with the following methods...". It lists `add_job` and `get_result`. It does *not* list `process`.
    *   This is a constraint. "Create a JobQueue class with the following methods".
    *   If I add `process`, am I violating "with the following methods"? Usually, this means "at least these methods".
    *   But if I *don't* add `process`, how does the queue work?
    *   Maybe the queue is meant to be used with an external worker?
    *   Or maybe `add_job` should process it?
    *   "Store jobs internally until they are processed".
    *   If I add `process`, I am fulfilling the spirit of the request.
    *   I will include `process`. It's impossible to have a working queue without a way to consume.

    *   *Wait*, maybe the processing logic is supposed to be passed in? No, data is a dict.
    *   I'll stick to the plan.

    *   *Final Code Structure:*
        ```python
        import collections

        class JobQueue:
            def __init__(self):
                self._queue = collections.deque()
                self._results = {}

            def add_job(self, job_id: str, data: dict) -> str:
                self._queue.append({"job_id": job_id, "data": data})
                return job_id

            def process(self):
                if not self._queue:
                    return None
                job = self._queue.popleft()
                # Generic processing logic
                result = {"status": "completed", "data": job["data"]}
                self._results[job["job_id"]] = result
                return job["job_id"]

            def get_result(self, job_id: str) -> dict | None:
                return self._results.get(job_id, None)
        ```
    *   Wait, `dict | None` syntax error on 3.9. I will assume 3.10+ based on the prompt's syntax.

    *   *Actually*, looking at the prompt again, maybe I can make `add_job` return a future-like object? No, "return job_id".
    *   Okay, I'm overthinking the version compatibility. I'll provide the code.

    *   *One detail:* The prompt example usage: `job_id = queue.add_job("job1", ...)`
    *   It passes "job1" as the ID.
    *   My code handles this.

    *   *Self-Correction:* What if the user wants the processing to happen *inside* `get_result` if it's pending? No, that's weird.
    *   What if the user wants a background thread?
    *   "Basic job queue".
    *   I'll stick to the synchronous `process` method.

    *   *Wait*, is it possible to implement this *without* `process` method by using a property or something? No.
    *   Is it possible the prompt implies the queue is just the storage and the "processing" is external?
    *   If so, `get_result` just looks up the result. But where does the result come from?
    *   If the prompt implies a "Job Queue" class, it usually encapsulates the lifecycle.
    *   I will add `process`.

    *   *Final check:* "Write only the Python code".
    *   I will output the code block.

    ```python
    import collections
    from typing import Optional

    class JobQueue:
        def __init__(self):
            self._queue = collections.deque()
            self._results = {}

        def add_job(self, job_id: str, data: dict) -> str:
            self._queue.append({"job_id": job_id, "data": data})
            return job_id

        def process(self):
            if self._queue:
                job = self._queue.popleft()
                # Simulate processing
                result = {"status": "completed", "data": job["data"]}
                self._results[job["job_id"]] = result
                return job["job_id"]
            return None

        def get_result(self, job_id: str) -> dict | None:
            return self._results.get(job_id, None)
    ```
    *   Wait, if I use `dict | None` in the signature, I should probably ensure it works.
    *   I'll change `dict | None` to `Optional[dict]` and import `Optional` to be safe and correct, while keeping the logic identical. The prompt used `dict | None` in the text description, but valid Python code is the goal. However, `dict | None` is valid in 3.10+. I'll stick to `dict | None` to match the prompt's style exactly, as it's a specific requirement signature.

    *   Actually, I'll use `Optional` to be safe. It's better code. But the prompt explicitly wrote `dict | None`. I will follow the prompt's syntax.

    *   Wait, I need to make sure `process` is defined. If I don't define it, the user can't process.
    *   I'll define it.

    *   *Wait*, maybe the prompt implies that `add_job` should process the job?
    *   "The queue should store jobs internally until they are processed".
    *   If `add_job` processed it, it wouldn't be stored until processed (it would be processed immediately).
    *   So `add_job` must just store.
    *   So a separate processing step is required.

    *   I'll provide the code now.

    *   *Refinement:* I'll add a docstring or comments? "Write only the Python code". I'll keep comments minimal or remove them to be safe, but comments are part of code. I'll keep it clean.

    *   *One edge case:* Duplicate job IDs? The prompt doesn't specify error handling. I'll assume unique IDs or overwrite (but deque lookup is slow for duplicates, dict lookup is fast). I'll just store.

    *   *Final Code:*
    ```python
    import collections

    class JobQueue:
        def __init__(self):
            self._queue = collections.deque()
            self._results = {}

        def add_job(self, job_id: str, data: dict) -> str:
            self._queue.append({"job_id": job_id, "data": data})
            return job_id

        def process(self):
            if not self._queue:
                return None
            job = self._queue.popleft()
            # Simulate processing logic
            result = {"status": "completed", "data": job["data"]}
            self._results[job["job_id"]] = result
            return job["job_id"]

        def get_result(self, job_id: str) -> dict | None:
            return self._results.get(job_id, None)
    ```
    *   Wait, `dict | None` might be an issue. I will use `Optional` import just to be safe, or just `dict | None` if I assume 3.10. I'll stick to `dict | None` as it's in the prompt.

    *   Actually, looking at the prompt again: "Write only the Python code".
    *   I will provide the class.

    *   *Self-Correction:* What if the prompt implies the queue should process jobs *automatically* in a background thread?
    *   "Basic job queue". Usually means data structure.
    *   I'll stick to the `process` method.

    *   Let's check if there is a way to do it without `process` method by using `add_job` to return a callable? No, returns `str`.
    *   Okay, `process` method it is.

    *   *Wait*, maybe I can make `get_result` process the job if it's pending?
    *   No, `get_result` is for getting results.
    *   I'll stick to the explicit `process`.

    *   *Final decision on imports:* `collections` is standard. `typing` is standard.
    *   I'll use `collections.deque`.

    *   *Final check on "Process" method name:* It's not specified. `process` is a good name. `run` is also good. I'll use `process`.

    *   *Wait*, what if the user just wants the class and the `process` method is considered "extra"?
    *   If I don't include it, the code is technically compliant with the list of methods, but functionally broken regarding the "processed" requirement.
    *   I'll include it.

    *   *Actually*, looking at the example usage:
        `# After processing...`
        This comment suggests that processing is an action that happens *between* add and get_result.
        If the class doesn't provide the method, the user has to write it.
        But the prompt asks *me* to implement the class.
        So I must provide the mechanism.

    *   Code:
    ```python
    import collections

    class JobQueue:
        def __init__(self):
            self._queue = collections.deque()
            self._results = {}

        def add_job(self, job_id: str, data: dict) -> str:
            self._queue.append({"job_id": job_id, "data": data})
            return job_id

        def process(self):
            if self._queue:
                job = self._queue.popleft()
                result = {"status": "completed", "data": job["data"]}
                self._results[job["job_id"]] = result
                return job["job_id"]
            return None

        def get_result(self, job_id: str) -> dict | None:
            return self._results.get(job_id, None)
    ```
    *   Wait, `dict | None` is Python 3.10+. I will use `from typing import Optional` and `-> Optional[dict]` to be safe, or just `dict | None` if I want to strictly match the prompt's type hint style. I'll use `dict | None` as it's cleaner and likely expected.

    *   Wait, I should check if `job_id` needs to be unique. "Each job has a unique job_id". The prompt implies the input `job_id` is unique. I don't need to generate it.

    *   Okay, ready.

</reasoning_content>

<content>
```python
import collections

class JobQueue:
    def __init__(self):
        self._queue = collections.deque()
        self._results = {}

    def add_job(self, job_id: str, data: dict) -> str:
        """Add a job to the queue."""
        self._queue.append({"job_id": job_id, "data": data})
        return job_id

    def process(self):
        """Process the next job in the queue (FIFO)."""
        if not self._queue:
            return None
        
        job = self._queue.popleft()
        # Simulate processing logic
        result = {"status": "completed", "data": job["data"]}
        self._results[job["job_id"]] = result
        return job["job_id"]

    def get_result(self, job_id: str) -> dict | None:
        """Get the result of a completed job."""
        return self._results.get(job_id, None)
```
</content>