feat
This commit is contained in:
@@ -193,48 +193,21 @@ public function destroy($id)
|
||||
return response()->json(['message' => 'Question deleted successfully']);
|
||||
}
|
||||
|
||||
// USER submits their answer(s) for a question.
|
||||
// USER submits their answer(s) for a single question.
|
||||
// An empty option_ids array (or omitting it) means "no answer" / skip.
|
||||
public function answer(Request $request, $id)
|
||||
{
|
||||
$question = SurveyQuestion::findOrFail($id);
|
||||
|
||||
$data = $request->validate([
|
||||
'option_ids' => 'required|array|min:1',
|
||||
'option_ids' => 'nullable|array',
|
||||
'option_ids.*' => 'integer',
|
||||
]);
|
||||
|
||||
$optionIds = array_values(array_unique($data['option_ids']));
|
||||
|
||||
// Every selected option must belong to this question.
|
||||
$validOptionIds = $question->options()->pluck('id')->all();
|
||||
if (array_diff($optionIds, $validOptionIds)) {
|
||||
throw ValidationException::withMessages([
|
||||
'option_ids' => ['One or more options do not belong to this question.'],
|
||||
]);
|
||||
}
|
||||
|
||||
// Enforce single vs multiple selection.
|
||||
if ($question->type === 'single' && count($optionIds) > 1) {
|
||||
throw ValidationException::withMessages([
|
||||
'option_ids' => ['This question allows only a single option.'],
|
||||
]);
|
||||
}
|
||||
|
||||
$userId = auth()->id();
|
||||
|
||||
DB::transaction(function () use ($question, $optionIds, $userId) {
|
||||
// Replace any previous answer for this user + question.
|
||||
$question->answers()->where('user_id', $userId)->delete();
|
||||
|
||||
$rows = array_map(fn ($optionId) => [
|
||||
'user_id' => $userId,
|
||||
'survey_question_id' => $question->id,
|
||||
'survey_option_id' => $optionId,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
], $optionIds);
|
||||
|
||||
$question->answers()->getRelated()->insert($rows);
|
||||
DB::transaction(function () use ($question, $data, $userId) {
|
||||
$this->syncAnswerFor($question, $data['option_ids'] ?? [], $userId);
|
||||
});
|
||||
|
||||
return response()->json([
|
||||
@@ -243,6 +216,82 @@ public function answer(Request $request, $id)
|
||||
]);
|
||||
}
|
||||
|
||||
// USER submits answers for many questions at once. Each item may carry an
|
||||
// empty option_ids (skip), and the whole answers array may be empty too.
|
||||
public function bulkAnswer(Request $request)
|
||||
{
|
||||
$data = $request->validate([
|
||||
'answers' => 'present|array',
|
||||
'answers.*.question_id' => 'required|integer|exists:survey_questions,id',
|
||||
'answers.*.option_ids' => 'nullable|array',
|
||||
'answers.*.option_ids.*' => 'integer',
|
||||
]);
|
||||
|
||||
$userId = auth()->id();
|
||||
$items = $data['answers'] ?? [];
|
||||
|
||||
$questions = SurveyQuestion::with('options')
|
||||
->whereIn('id', collect($items)->pluck('question_id')->unique()->all())
|
||||
->get()
|
||||
->keyBy('id');
|
||||
|
||||
DB::transaction(function () use ($items, $questions, $userId) {
|
||||
foreach ($items as $item) {
|
||||
$question = $questions->get($item['question_id']);
|
||||
if (!$question) {
|
||||
continue;
|
||||
}
|
||||
$this->syncAnswerFor($question, $item['option_ids'] ?? [], $userId);
|
||||
}
|
||||
});
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Answers submitted successfully',
|
||||
'questions' => SurveyQuestion::with(['options', 'userAnswers'])
|
||||
->where('is_active', true)
|
||||
->orderBy('order')
|
||||
->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
// Validate and replace a single user's answer set for one question.
|
||||
// Empty $optionIds clears the answer (the user chose not to answer it).
|
||||
private function syncAnswerFor(SurveyQuestion $question, array $optionIds, int $userId): void
|
||||
{
|
||||
$optionIds = array_values(array_unique(array_map('intval', $optionIds)));
|
||||
|
||||
// Every selected option must belong to this question.
|
||||
$validOptionIds = $question->options()->pluck('id')->all();
|
||||
if (array_diff($optionIds, $validOptionIds)) {
|
||||
throw ValidationException::withMessages([
|
||||
'option_ids' => ["One or more options do not belong to question #{$question->id}."],
|
||||
]);
|
||||
}
|
||||
|
||||
// Enforce single vs multiple selection.
|
||||
if ($question->type === 'single' && count($optionIds) > 1) {
|
||||
throw ValidationException::withMessages([
|
||||
'option_ids' => ["Question #{$question->id} allows only a single option."],
|
||||
]);
|
||||
}
|
||||
|
||||
// Replace any previous answer for this user + question.
|
||||
$question->answers()->where('user_id', $userId)->delete();
|
||||
|
||||
if ($optionIds) {
|
||||
$now = now();
|
||||
$rows = array_map(fn ($optionId) => [
|
||||
'user_id' => $userId,
|
||||
'survey_question_id' => $question->id,
|
||||
'survey_option_id' => $optionId,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
], $optionIds);
|
||||
|
||||
$question->answers()->getRelated()->insert($rows);
|
||||
}
|
||||
}
|
||||
|
||||
// USER: suggest media based on the tags attached to the options this user has chosen.
|
||||
public function suggestedMedia(Request $request)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user