Untitled

 avatar
unknown
plain_text
12 days ago
26 kB
7
Indexable
# Model Bazy Danych i Encje dla APK

## 1. Model Bazy Danych

### QuestionGroup
```sql
CREATE TABLE question_group (
    id BIGINT PRIMARY KEY,
    code VARCHAR(50) NOT NULL UNIQUE,  -- MAIN_RISKS, ADDITIONAL_RISKS
    active BOOLEAN DEFAULT true
);
```

### Question
```sql
CREATE TABLE question (
    id BIGINT PRIMARY KEY,
    group_id BIGINT REFERENCES question_group(id),
    question_order INT NOT NULL,
    active BOOLEAN DEFAULT true
);
```

### QuestionContent
```sql
CREATE TABLE question_content (
    id BIGINT PRIMARY KEY,
    question_id BIGINT REFERENCES question(id),
    language_code VARCHAR(5), -- pl_PL, en_GB
    content TEXT NOT NULL
);
```

### PathCondition
```sql
CREATE TABLE path_condition (
    id BIGINT PRIMARY KEY,
    code VARCHAR(50) NOT NULL UNIQUE,  -- MINI_MIDI_MAXI, MINI_MIDI, etc.
    description TEXT,
    active BOOLEAN DEFAULT true
);
```

### Answer
```sql
CREATE TABLE answer (
    id BIGINT PRIMARY KEY,
    question_id BIGINT REFERENCES question(id),
    next_question_id BIGINT REFERENCES question(id),
    answer_order INT NOT NULL,
    path_condition_id BIGINT REFERENCES path_condition(id),
    code VARCHAR(50) NOT NULL,  -- BUDGET_IMPORTANT, FULL_PROTECTION, etc.
    active BOOLEAN DEFAULT true
);
```

### AnswerContent
```sql
CREATE TABLE answer_content (
    id BIGINT PRIMARY KEY,
    answer_id BIGINT REFERENCES answer(id),
    language_code VARCHAR(5),
    content TEXT NOT NULL
);
```

### Recommendation
```sql
CREATE TABLE recommendation (
    id BIGINT PRIMARY KEY,
    path_condition_id BIGINT REFERENCES path_condition(id),
    package_code VARCHAR(50) NOT NULL,  -- MINI, MIDI, MAXI
    description TEXT,
    active BOOLEAN DEFAULT true
);
```

### CustomerQuestionnaire
```sql
CREATE TABLE customer_questionnaire (
    id BIGINT PRIMARY KEY,
    customer_id BIGINT NOT NULL,
    quote_id BIGINT NOT NULL,
    group_id BIGINT REFERENCES question_group(id),
    status VARCHAR(20) NOT NULL,  -- IN_PROGRESS, COMPLETED
    created_at TIMESTAMP NOT NULL,
    completed_at TIMESTAMP,
    recommendation VARCHAR(50)
);
```

### CustomerAnswer
```sql
CREATE TABLE customer_answer (
    id BIGINT PRIMARY KEY,
    questionnaire_id BIGINT REFERENCES customer_questionnaire(id),
    question_id BIGINT REFERENCES question(id),
    answer_id BIGINT REFERENCES answer(id),
    answered_at TIMESTAMP NOT NULL
);
```

## 2. Encje Java

```java
@Entity
@Table(name = "question_group")
@Getter
@Setter
public class QuestionGroupEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true)
    private String code;

    private Boolean active = true;

    @OneToMany(mappedBy = "group")
    private List<QuestionEntity> questions;
}

@Entity
@Table(name = "question")
@Getter
@Setter
public class QuestionEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "group_id")
    private QuestionGroupEntity group;

    @Column(name = "question_order")
    private Integer order;

    private Boolean active = true;

    @OneToMany(mappedBy = "question")
    private List<QuestionContentEntity> contents;

    @OneToMany(mappedBy = "question")
    private List<AnswerEntity> answers;
}

@Entity
@Table(name = "question_content")
@Getter
@Setter
public class QuestionContentEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "question_id")
    private QuestionEntity question;

    @Column(name = "language_code")
    private String languageCode;

    private String content;
}

@Entity
@Table(name = "path_condition")
@Getter
@Setter
public class PathConditionEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true)
    @Enumerated(EnumType.STRING)
    private PathCondition code;

    private String description;
    private Boolean active = true;

    @OneToMany(mappedBy = "pathCondition")
    private List<AnswerEntity> answers;

    @OneToMany(mappedBy = "pathCondition")
    private List<RecommendationEntity> recommendations;
}

@Entity
@Table(name = "answer")
@Getter
@Setter
public class AnswerEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "question_id")
    private QuestionEntity question;

    @ManyToOne
    @JoinColumn(name = "next_question_id")
    private QuestionEntity nextQuestion;

    @Column(name = "answer_order")
    private Integer order;

    @ManyToOne
    @JoinColumn(name = "path_condition_id")
    private PathConditionEntity pathCondition;

    private String code;
    private Boolean active = true;

    @OneToMany(mappedBy = "answer")
    private List<AnswerContentEntity> contents;
}

@Entity
@Table(name = "answer_content")
@Getter
@Setter
public class AnswerContentEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "answer_id")
    private AnswerEntity answer;

    @Column(name = "language_code")
    private String languageCode;

    private String content;
}

@Entity
@Table(name = "recommendation")
@Getter
@Setter
public class RecommendationEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "path_condition_id")
    private PathConditionEntity pathCondition;

    @Column(name = "package_code")
    private String packageCode;

    private String description;
    private Boolean active = true;
}

@Entity
@Table(name = "customer_questionnaire")
@Getter
@Setter
public class CustomerQuestionnaireEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "customer_id")
    private Long customerId;

    @Column(name = "quote_id")
    private Long quoteId;

    @ManyToOne
    @JoinColumn(name = "group_id")
    private QuestionGroupEntity group;

    @Enumerated(EnumType.STRING)
    private QuestionnaireStatus status;

    @Column(name = "created_at")
    private LocalDateTime createdAt;

    @Column(name = "completed_at")
    private LocalDateTime completedAt;

    private String recommendation;

    @OneToMany(mappedBy = "questionnaire")
    private List<CustomerAnswerEntity> answers;
}

@Entity
@Table(name = "customer_answer")
@Getter
@Setter
public class CustomerAnswerEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "questionnaire_id")
    private CustomerQuestionnaireEntity questionnaire;

    @ManyToOne
    @JoinColumn(name = "question_id")
    private QuestionEntity question;

    @ManyToOne
    @JoinColumn(name = "answer_id")
    private AnswerEntity answer;

    @Column(name = "answered_at")
    private LocalDateTime answeredAt;
}

// Enum dla warunków ścieżek
public enum PathCondition {
    MINI_MIDI_MAXI,
    MINI_MIDI,
    MIDI_MAXI,
    MINI_MAXI
}

// Enum dla statusu kwestionariusza
public enum QuestionnaireStatus {
    IN_PROGRESS,
    COMPLETED
}
```



---


// Enum dla warunków ścieżek
public enum PathCondition {
    MINI_MIDI_MAXI,
    MINI_MIDI,
    MIDI_MAXI,
    MINI_MAXI,
    // ... inne kombinacje
}

// Entity dla warunku ścieżki
@Entity
@Table(name = "path_condition")
public class PathConditionEntity {
    @Id
    private Long id;
    
    @Enumerated(EnumType.STRING)
    @Column(name = "code")
    private PathCondition code;
    
    private String description;
}

// Entity dla odpowiedzi z warunkiem
@Entity
@Table(name = "answer")
public class AnswerEntity {
    @Id
    private Long id;
    
    @ManyToOne
    @JoinColumn(name = "question_id")
    private QuestionEntity question;
    
    @ManyToOne
    @JoinColumn(name = "path_condition_id")
    private PathConditionEntity pathCondition;
    
    private Integer answerOrder;
    private String code;
    private Boolean active;
}

// Strategia dla warunków ścieżek
public interface PathConditionStrategy {
    List<String> getAvailablePackages();
    String getRecommendation(List<AnswerDTO> answers);
}

@Service
public class MiniMidiMaxiStrategy implements PathConditionStrategy {
    @Override
    public List<String> getAvailablePackages() {
        return Arrays.asList("MINI", "MIDI", "MAXI");
    }

    @Override
    public String getRecommendation(List<AnswerDTO> answers) {
        // Logika wyboru rekomendacji na podstawie odpowiedzi
        return calculateRecommendation(answers);
    }

    private String calculateRecommendation(List<AnswerDTO> answers) {
        // Przykładowa implementacja
        boolean prefersCheaper = answers.stream()
            .anyMatch(a -> a.getCode().equals("PRICE_SENSITIVE"));
            
        boolean needsFullCoverage = answers.stream()
            .anyMatch(a -> a.getCode().equals("FULL_COVERAGE"));

        if (prefersCheaper && !needsFullCoverage) {
            return "MINI";
        } else if (needsFullCoverage) {
            return "MAXI";
        }
        return "MIDI";
    }
}

// Factory dla strategii
@Service
public class PathConditionStrategyFactory {
    private final Map<PathCondition, PathConditionStrategy> strategies;

    public PathConditionStrategyFactory(List<PathConditionStrategy> strategyList) {
        strategies = new EnumMap<>(PathCondition.class);
        // Inicjalizacja strategii
        strategies.put(PathCondition.MINI_MIDI_MAXI, new MiniMidiMaxiStrategy());
        // ... inne strategie
    }

    public PathConditionStrategy getStrategy(PathCondition condition) {
        return strategies.get(condition);
    }
}

// Service dla APK
@Service
@Transactional
public class ApkService {
    private final QuestionRepository questionRepository;
    private final AnswerRepository answerRepository;
    private final PathConditionStrategyFactory strategyFactory;

    public ApkResponseDTO getQuestionnaire(String groupCode) {
        // Pobierz pytania i odpowiedzi
        List<QuestionEntity> questions = questionRepository.findByGroupCode(groupCode);
        
        return ApkResponseDTO.builder()
            .questionnaireId(UUID.randomUUID().toString())
            .questions(questions.stream()
                .map(q -> QuestionDTO.builder()
                    .id(q.getId())
                    .content(q.getContent())
                    .answersIds(q.getAnswers().stream()
                        .map(AnswerDTO::new)
                        .collect(Collectors.toList()))
                    .build())
                .collect(Collectors.toList()))
            .answers(questions.stream()
                .flatMap(q -> q.getAnswers().stream())
                .map(a -> AnswerDTO.builder()
                    .id(a.getId())
                    .content(a.getContent())
                    .nextQuestionId(calculateNextQuestion(a))
                    .recommendation(calculateRecommendation(a))
                    .build())
                .collect(Collectors.toList()))
            .initQuestionId(questions.get(0).getId())
            .build();
    }

    private Long calculateNextQuestion(AnswerEntity answer) {
        PathConditionStrategy strategy = strategyFactory.getStrategy(answer.getPathCondition().getCode());
        // Logika wyboru następnego pytania na podstawie strategii
        return null; // lub ID następnego pytania
    }

    private String calculateRecommendation(AnswerEntity answer) {
        PathConditionStrategy strategy = strategyFactory.getStrategy(answer.getPathCondition().getCode());
        // Zwróć rekomendację jeśli to ostatnia odpowiedź w ścieżce
        return null; // lub rekomendacja
    }

    public void saveAnswers(String questionnaireId, SaveAnswersDTO request) {
        // Zapisz odpowiedzi w bazie
        request.getAnswers().forEach(answer -> {
            CustomerAnswerEntity customerAnswer = new CustomerAnswerEntity();
            customerAnswer.setQuestionnaireId(questionnaireId);
            customerAnswer.setQuestionId(answer.getQuestionId());
            customerAnswer.setAnswerId(answer.getAnswerId());
            customerAnswer.setAnsweredAt(LocalDateTime.now());
            customerAnswerRepository.save(customerAnswer);
        });
    }
}

// DTO dla odpowiedzi API
@Data
@Builder
public class ApkResponseDTO {
    private String questionnaireId;
    private List<QuestionDTO> questions;
    private List<AnswerDTO> answers;
    private Long initQuestionId;
}

@Data
@Builder
public class QuestionDTO {
    private Long id;
    private String content;
    private List<AnswerIdDTO> answersIds;
}

@Data
@Builder
public class AnswerDTO {
    private Long id;
    private String content;
    private Long nextQuestionId;
    private String recommendation;
}

@Data
@Builder
public class SaveAnswersDTO {
    private Long initQuestionId;
    private List<UserAnswerDTO> answers;
    private String recommendation;
}


---

# System Design - Analiza Potrzeb Klienta (APK)

## 1. Model Bazodanowy
[Bez zmian]

## 2. API Endpoints
[Dokładnie taki jak w przekazanej wersji]

## 3. Flow procesu

### 3.1 Standardowy flow

1. **Inicjalizacja**:
   - Frontend otrzymuje oferty ubezpieczeniowe
   - Jeśli oferta zawiera AC lub OC+AC:
     - Wywołuje GET /apk/questionnaires z odpowiednim groupCode
     - Otrzymuje:
       - ID kwestionariusza
       - Listę wszystkich pytań z przypisanymi do nich ID odpowiedzi
       - Listę wszystkich odpowiedzi z informacją o kolejnym pytaniu lub rekomendacji
       - ID pierwszego pytania
     - Zapisuje w lokalnym stanie całą strukturę
     - Wyświetla pierwsze pytanie na podstawie initQuestionId

2. **Nawigacja po pytaniach**:
   - Frontend na podstawie otrzymanej struktury:
     - Wyświetla aktualne pytanie
     - Z listy answers filtruje odpowiedzi na podstawie answersIds z pytania
     - Po wyborze odpowiedzi:
       - Sprawdza nextQuestionId dla wybranej odpowiedzi
       - Przechodzi do kolejnego pytania lub kończy proces
     - Zbiera odpowiedzi w lokalnym stanie

3. **Zakończenie procesu**:
   - Po dotarciu do końca ścieżki (odpowiedź z rekomendacją):
     - Frontend wywołuje POST /apk/questionnaires/{questionnaireId}
     - Przekazuje:
       - ID pierwszego pytania
       - Listę wszystkich udzielonych odpowiedzi
       - Końcową rekomendację

### 3.2 Flow zmiany odpowiedzi

1. **Zmiana wcześniejszej odpowiedzi**:
   - Frontend:
     - Usuwa z lokalnego stanu odpowiedzi na wszystkie późniejsze pytania
     - Sprawdza w zapisanej mapie answers nextQuestionId dla nowej odpowiedzi
     - Kontynuuje proces od nowego pytania
     - Aktualizuje rekomendację jeśli się zmieniła

2. **Zakończenie zmienionej ścieżki**:
   - Frontend:
     - Zbiera wszystkie aktualne odpowiedzi
     - Zapisuje przez POST z aktualną rekomendacją

## 4. Podział odpowiedzialności

### Backend
- Dostarczenie pełnej struktury pytań i odpowiedzi
- Przechowywanie definicji pytań i odpowiedzi
- Walidacja zapisywanych odpowiedzi
- Persystencja danych
- Obsługa wielojęzyczności
- Zapewnienie spójności danych

### Frontend
- Przechowywanie i zarządzanie strukturą pytań i odpowiedzi
- Nawigacja między pytaniami według nextQuestionId
- Filtrowanie dostępnych odpowiedzi dla pytań
- Zarządzanie stanem odpowiedzi użytkownika
- Obsługa zmiany odpowiedzi i czyszczenie kolejnych
- Prezentacja pytań i odpowiedzi
- Obsługa interakcji z użytkownikiem

## 5. Rozszerzalność

System zaprojektowany w ten sposób pozwala na:
- Łatwe dodawanie nowych pytań i odpowiedzi
- Modyfikację ścieżek przez zmianę nextQuestionId
- Wsparcie wielu języków
- Dodawanie nowych grup pytań
- Rozbudowę o nowe typy rekomendacji

Kluczowe zalety:
- Frontend otrzymuje wszystkie dane na start
- Minimalna liczba wywołań API
- Szybka reakcja na odpowiedzi użytkownika
- Proste zarządzanie zmianami odpowiedzi
- Łatwa implementacja różnych wariantów UI


---

### 3.3 Flow przywracania sesji

1. **Inicjalizacja komponentu**:
   - Frontend sprawdza localStorage pod kątem zapisanego stanu APK
   - Jeśli stan istnieje:
     - Przywraca pełny stan z localStorage do store
     - Wyświetla ostatnie aktywne pytanie
     - Pokazuje wszystkie dotychczasowe odpowiedzi
   - Jeśli nie ma stanu:
     - Inicjuje nowy proces przez pobranie pytań z API

2. **Kontynuacja procesu**:
   - Użytkownik może:
     - Kontynuować od ostatniego pytania
     - Wrócić do wcześniejszych odpowiedzi i je zmienić
     - Zobaczyć rekomendację jeśli proces był zakończony

3. **Czyszczenie sesji**:
   - Po zapisie kompletu odpowiedzi:
     - Frontend czyści stan z localStorage
     - Inicjuje nowy proces dla kolejnej grupy pytań jeśli potrzebna


---

// apk.types.ts
export interface Question {
    id: number;
    content: string;
    answersIds: Array<{
        id: number;
    }>;
}

export interface Answer {
    id: number;
    content: string;
    nextQuestionId?: number;
    recommendation?: string;
}

export interface QuestionnaireState {
    questionnaireId: string;
    questions: Question[];
    answers: Answer[];
    initQuestionId: number;
    userAnswers: Array<{
        questionId: number;
        answerId: number;
    }>;
    currentQuestionId: number;
    recommendation?: string;
}

// apk.store.ts
@Injectable({
    providedIn: 'root'
})
export class ApkStore {
    private state = signal<QuestionnaireState | null>(null);
    
    setState(state: QuestionnaireState) {
        this.state.set(state);
        // Zapisz w localStorage dla możliwości przywrócenia
        localStorage.setItem('apkState', JSON.stringify(state));
    }

    updateUserAnswer(questionId: number, answerId: number) {
        this.state.update(state => {
            if (!state) return null;
            
            // Znajdź odpowiedź, aby sprawdzić następne pytanie lub rekomendację
            const selectedAnswer = state.answers.find(a => a.id === answerId);
            
            // Usuń wszystkie odpowiedzi po aktualnym pytaniu
            const filteredAnswers = state.userAnswers.filter(
                ua => state.questions.find(
                    q => q.id === ua.questionId
                )?.answersIds.some(
                    a => a.id === ua.answerId
                )
            );

            return {
                ...state,
                userAnswers: [...filteredAnswers, { questionId, answerId }],
                currentQuestionId: selectedAnswer?.nextQuestionId || -1,
                recommendation: selectedAnswer?.recommendation
            };
        });
    }

    restoreFromLocalStorage(): boolean {
        const savedState = localStorage.getItem('apkState');
        if (savedState) {
            this.state.set(JSON.parse(savedState));
            return true;
        }
        return false;
    }
}

// apk.service.ts
@Injectable({
    providedIn: 'root'
})
export class ApkService {
    constructor(
        private http: HttpClient,
        private store: ApkStore
    ) {}

    getQuestionnaire(groupCode: string): Observable<void> {
        return this.http.get<QuestionnaireState>('/apk/questionnaires', {
            params: { groupCode }
        }).pipe(
            tap(response => {
                this.store.setState({
                    ...response,
                    userAnswers: [],
                    currentQuestionId: response.initQuestionId
                });
            }),
            map(() => void 0)
        );
    }

    saveAnswers(questionnaireId: string): Observable<void> {
        const state = this.store.getState();
        if (!state) return EMPTY;

        return this.http.post<void>(`/apk/questionnaires/${questionnaireId}`, {
            initQuestionId: state.initQuestionId,
            answers: state.userAnswers,
            recommendation: state.recommendation
        });
    }
}

// apk.component.ts
@Component({
    selector: 'app-apk',
    template: `
        <ng-container *ngIf="currentQuestion$ | async as question">
            <h2>{{ question.content }}</h2>
            <div class="answers">
                <button 
                    *ngFor="let answer of getAnswersForQuestion(question)"
                    (click)="selectAnswer(question.id, answer.id)"
                >
                    {{ answer.content }}
                </button>
            </div>
        </ng-container>
    `
})
export class ApkComponent implements OnInit {
    constructor(
        private apkService: ApkService,
        private store: ApkStore
    ) {}

    ngOnInit() {
        // Próba przywrócenia stanu
        if (!this.store.restoreFromLocalStorage()) {
            // Jeśli nie ma zapisanego stanu, pobierz nowy
            this.apkService.getQuestionnaire('MAIN_RISKS').subscribe();
        }
    }

    private getAnswersForQuestion(question: Question): Answer[] {
        const state = this.store.getState();
        if (!state) return [];
        
        return question.answersIds
            .map(aid => state.answers.find(a => a.id === aid.id))
            .filter((a): a is Answer => a !== undefined);
    }

    selectAnswer(questionId: number, answerId: number) {
        this.store.updateUserAnswer(questionId, answerId);
        
        // Jeśli mamy rekomendację, zapisz odpowiedzi
        const state = this.store.getState();
        if (state?.recommendation) {
            this.apkService.saveAnswers(state.questionnaireId).subscribe();
        }
    }
}


---

// models/apk.models.ts
export type QuestionGroupCode = 'MAIN_RISKS' | 'ADDITIONAL_RISKS';

export interface QuestionnaireInit {
    groupCode: QuestionGroupCode;
}

export interface SaveAnswersRequest {
    initQuestionId: number;
    answers: Array<{
        questionId: number;
        answerId: number;
    }>;
    recommendation: string;
}

// components/apk-summary.component.ts
@Component({
    selector: 'app-apk-summary',
    template: `
        <div *ngIf="state$ | async as state">
            <h2>Rekomendacja</h2>
            <p>{{ state.recommendation }}</p>
            <div class="answers-summary">
                <h3>Twoje odpowiedzi:</h3>
                <div *ngFor="let answer of state.userAnswers">
                    <p>
                        {{ getQuestionContent(answer.questionId) }}:
                        {{ getAnswerContent(answer.answerId) }}
                    </p>
                </div>
            </div>
        </div>
    `
})
export class ApkSummaryComponent {
    state$ = computed(() => this.store.state());

    constructor(private store: ApkStore) {}

    getQuestionContent(questionId: number): string {
        return this.store.state()?.questions
            .find(q => q.id === questionId)?.content ?? '';
    }

    getAnswerContent(answerId: number): string {
        return this.store.state()?.answers
            .find(a => a.id === answerId)?.content ?? '';
    }
}

// stores/apk.store.ts
export class ApkStore {
    private state = signal<QuestionnaireState | null>(null);
    
    // Computed signals dla lepszej reaktywności
    readonly currentQuestion = computed(() => {
        const state = this.state();
        if (!state) return null;
        return state.questions.find(q => q.id === state.currentQuestionId);
    });

    readonly currentAnswers = computed(() => {
        const state = this.state();
        const question = this.currentQuestion();
        if (!state || !question) return [];
        
        return question.answersIds
            .map(aid => state.answers.find(a => a.id === aid.id))
            .filter((a): a is Answer => a !== undefined);
    });

    readonly showSummary = computed(() => {
        return !!this.state()?.recommendation;
    });
}


@Component({
    selector: 'app-apk',
    template: `
        <ng-container *ngIf="!showSummary(); else summary">
            <ng-container *ngIf="currentQuestion() as question">
                <h2>{{ question.content }}</h2>
                <div class="answers">
                    <button 
                        *ngFor="let answer of currentAnswers()"
                        (click)="selectAnswer(question.id, answer.id)"
                        [disabled]="isAnswerDisabled(answer.id)"
                    >
                        {{ answer.content }}
                    </button>
                </div>
            </ng-container>
        </ng-container>
        <ng-template #summary>
            <app-apk-summary></app-apk-summary>
        </ng-template>
    `
})
export class ApkComponent implements OnInit {
    currentQuestion = this.store.currentQuestion;
    currentAnswers = this.store.currentAnswers;
    showSummary = this.store.showSummary;

    constructor(
        private apkService: ApkService,
        private store: ApkStore
    ) {}

    ngOnInit() {
        if (!this.store.restoreFromLocalStorage()) {
            this.apkService.getQuestionnaire('MAIN_RISKS').subscribe();
        }
    }

    selectAnswer(questionId: number, answerId: number) {
        this.store.updateUserAnswer(questionId, answerId);
        
        const state = this.store.state();
        if (state?.recommendation) {
            this.apkService.saveAnswers(state.questionnaireId).subscribe();
        }
    }

    isAnswerDisabled(answerId: number): boolean {
        const state = this.store.state();
        return state?.userAnswers.some(ua => ua.answerId === answerId) ?? false;
    }
}

@NgModule({
    declarations: [
        ApkComponent,
        ApkSummaryComponent
    ],
    imports: [
        CommonModule,
        HttpClientModule
    ],
    providers: [
        ApkService,
        ApkStore
    ]
})
export class ApkModule { }
Leave a Comment