diff --git a/app/config/app.php b/app/config/app.php
index f5f064b..0cf9a0b 100644
--- a/app/config/app.php
+++ b/app/config/app.php
@@ -3,5 +3,5 @@
"latte" => true,
"locale" => "tr_TR.utf8",
"timezone" => "Europe/Istanbul",
- "mode" => "Production" #Development or Production
+ "mode" => "development" #Development or Production
];
\ No newline at end of file
diff --git a/app/config/database.php b/app/config/database.php
index 297a7d9..7ab7ad7 100644
--- a/app/config/database.php
+++ b/app/config/database.php
@@ -7,5 +7,7 @@
"host" => "localhost",
"prefix" => "",
"user" => "root",
- "password" => ""
+ "password" => "",
+ "cache" => false,
+ "cacheTime" => 60,
];
diff --git a/app/controllers/Participate.php b/app/controllers/Participate.php
index 69db12e..d504b8e 100644
--- a/app/controllers/Participate.php
+++ b/app/controllers/Participate.php
@@ -277,8 +277,8 @@ public function apply()
$user = session_get("participator");
if ($survey->verifyPhone) {
- if (Participator::checkSurveyIsParticipated($user->personalId, true))
- warning("Bu anketi daha önce zaten cevapladınız!");
+ if (Participator::checkSurveyIsParticipated($surveyId, (string) $user->personalId, true))
+ warninglang("participate.already.answered");
}
$post = Request::post();
@@ -289,38 +289,98 @@ public function apply()
$formData = json_decode($survey->data);
- foreach ($formData as $key => $value) {
- if ($value->type == "description")
+ $slugToQuestion = [];
+ $slugToSection = [];
+ $sectionSlugs = [];
+ $activeSectionSlug = null;
+ foreach ($formData as $q) {
+ if (! isset($q->slug))
+ continue;
+ $slugToQuestion[$q->slug] = $q;
+ if ($q->type === "section") {
+ $activeSectionSlug = $q->slug;
+ $sectionSlugs[$q->slug] = true;
+ $slugToSection[$q->slug] = $q->slug;
continue;
+ }
+ $slugToSection[$q->slug] = $activeSectionSlug;
+ }
- // Koşullu soru kontrolü - tüm soru tipleri için
- $index = -1;
- $hasCondition = false;
-
- foreach ($formData as $dkey => $dvalue) {
- // Eğer bu soru koşula sahipse
- if (!empty($dvalue->conditions)) {
- foreach ($dvalue->conditions as $i => $p) {
- if ($p->value == $value->slug) {
- $hasCondition = true; // Bu soru bir koşula bağlı
- $parentAnswer = $post->{$dvalue->slug} ?? null;
-
- if ($p->index == $parentAnswer) {
- $index = $i;
- break 2; // iki foreach'ten çık
- }
- }
+ $isConditionSatisfied = function ($parentQ, $cond) use ($post) {
+ if (! $parentQ || ! $cond)
+ return false;
+ $parentSlug = $parentQ->slug ?? "";
+ if ($parentSlug === "")
+ return false;
+ $expected = (string) ($cond->index ?? "");
+ if ($parentQ->type === "radio" || $parentQ->type === "select") {
+ $actual = isset($post->{$parentSlug}) ? (string) $post->{$parentSlug} : "";
+ return $actual !== "" && $actual === $expected;
+ }
+ if ($parentQ->type === "checkbox") {
+ $key = $parentSlug . $expected;
+ return isset($post->{$key});
+ }
+ return false;
+ };
+
+ $isSlugVisible = function ($slug) use ($formData, $slugToSection, $sectionSlugs, $isConditionSatisfied) {
+ if (! $slug)
+ return true;
+
+ $directRules = [];
+ foreach ($formData as $parentQ) {
+ if (empty($parentQ->conditions))
+ continue;
+ foreach ($parentQ->conditions as $cond) {
+ if (($cond->value ?? null) == $slug)
+ $directRules[] = [$parentQ, $cond];
+ }
+ }
+ if (! empty($directRules)) {
+ $ok = false;
+ foreach ($directRules as [$pQ, $cond]) {
+ if ($isConditionSatisfied($pQ, $cond)) {
+ $ok = true;
+ break;
}
}
+ if (! $ok)
+ return false;
}
- // Eğer koşula bağlıysa ve koşul sağlanmamışsa bu soruyu atla
- if ($hasCondition && $index == -1) {
- continue;
+ $sectionSlug = $slugToSection[$slug] ?? null;
+ if (! $sectionSlug || ! isset($sectionSlugs[$sectionSlug]) || $sectionSlug === $slug)
+ return true;
+
+ $sectionRules = [];
+ foreach ($formData as $parentQ) {
+ if (empty($parentQ->conditions))
+ continue;
+ foreach ($parentQ->conditions as $cond) {
+ if (($cond->value ?? null) == $sectionSlug)
+ $sectionRules[] = [$parentQ, $cond];
+ }
}
+ if (empty($sectionRules))
+ return true;
+
+ foreach ($sectionRules as [$pQ, $cond]) {
+ if ($isConditionSatisfied($pQ, $cond))
+ return true;
+ }
+ return false;
+ };
+
+ foreach ($formData as $key => $value) {
+ if ($value->type == "description" || $value->type == "section")
+ continue;
+ if (! $isSlugVisible($value->slug))
+ continue;
switch ($value->type) {
case "radio":
+ case "sentiment_scale":
$rules[$value->slug] = [
"name" => $value->title,
#"required" => $value->isRequired,
@@ -344,7 +404,7 @@ public function apply()
$validate2 = ! in_array(true, $actions);
if ($validate2)
- $errors[] = $value->title . " sorusunu cevaplayınız!";
+ $errors[] = lang("survey.validation.checkbox_required", strip_tags($value->title));
}
break;
@@ -360,6 +420,83 @@ public function apply()
$rules[$value->slug]["required"] = $value->isRequired;
break;
+
+ case "short_text":
+ $maxLen = isset($value->maxLength) ? (int) $value->maxLength : 255;
+ if ($maxLen < 1)
+ $maxLen = 255;
+ if ($maxLen > 4000)
+ $maxLen = 4000;
+ $rules[$value->slug] = [
+ "name" => $value->title . "
",
+ "max" => $maxLen,
+ ];
+ if ($value->isRequired)
+ $rules[$value->slug]["required"] = true;
+ break;
+
+ case "email":
+ $rules[$value->slug] = [
+ "name" => $value->title . "
",
+ "max" => 255,
+ ];
+ if ($value->isRequired)
+ $rules[$value->slug]["required"] = true;
+ break;
+
+ case "url":
+ $rules[$value->slug] = [
+ "name" => $value->title . "
",
+ "max" => 2048,
+ ];
+ if ($value->isRequired)
+ $rules[$value->slug]["required"] = true;
+ break;
+
+ case "phone":
+ $rules[$value->slug] = [
+ "name" => $value->title . "
",
+ "max" => 32,
+ ];
+ if ($value->isRequired)
+ $rules[$value->slug]["required"] = true;
+ break;
+
+ case "date":
+ case "time":
+ $rules[$value->slug] = [
+ "name" => $value->title . "
",
+ "max" => 32,
+ ];
+ if ($value->isRequired)
+ $rules[$value->slug]["required"] = true;
+ break;
+
+ case "number":
+ $rules[$value->slug] = [
+ "name" => $value->title . "
",
+ ];
+ if ($value->isRequired)
+ $rules[$value->slug]["required"] = true;
+ break;
+
+ case "select":
+ $rules[$value->slug] = [
+ "name" => $value->title . "
",
+ "min" => 0,
+ "max" => max(0, count($value->answers) - 1),
+ ];
+ if ($value->isRequired)
+ $rules[$value->slug]["required"] = true;
+ break;
+
+ case "scale":
+ $rules[$value->slug] = [
+ "name" => $value->title . "
",
+ ];
+ if ($value->isRequired)
+ $rules[$value->slug]["required"] = true;
+ break;
}
}
@@ -371,6 +508,61 @@ public function apply()
if ($validate)
warning($validate);
+ foreach ($formData as $value) {
+ if ($value->type === "description" || $value->type === "section")
+ continue;
+ if (! $isSlugVisible($value->slug))
+ continue;
+ $slug = $value->slug;
+ if ($value->type === "email") {
+ $raw = isset($post->$slug) ? trim((string) $post->$slug) : "";
+ if ($raw !== "" && ! validate_email($raw))
+ warning(lang("validation.email_error"));
+ }
+ if ($value->type === "url") {
+ $raw = isset($post->$slug) ? trim((string) $post->$slug) : "";
+ if ($raw !== "" && ! filter_var($raw, FILTER_VALIDATE_URL))
+ warning(lang("validation.url.error", strip_tags($value->title)));
+ }
+ if ($value->type === "phone") {
+ $raw = isset($post->$slug) ? trim((string) $post->$slug) : "";
+ if ($raw === "")
+ continue;
+ $digits = preg_replace('/\D+/', '', $raw);
+ if ($digits !== "" && strlen($digits) < 10)
+ warning(lang("validation.phone.error", strip_tags($value->title)));
+ }
+ if ($value->type === "number") {
+ $raw = isset($post->$slug) ? trim((string) $post->$slug) : "";
+ if ($raw === "")
+ continue;
+ if (! is_numeric($raw))
+ warning(lang("survey.validation.number_range", strip_tags($value->title)));
+ $num = 0 + $raw;
+ if (isset($value->numMin) && is_numeric($value->numMin) && $num < (float) $value->numMin)
+ warning(lang("survey.validation.number_range", strip_tags($value->title)));
+ if (isset($value->numMax) && is_numeric($value->numMax) && $num > (float) $value->numMax)
+ warning(lang("survey.validation.number_range", strip_tags($value->title)));
+ }
+ if ($value->type === "scale") {
+ $raw = isset($post->$slug) ? trim((string) $post->$slug) : "";
+ if ($raw === "")
+ continue;
+ if (! is_numeric($raw))
+ warning(lang("survey.validation.scale_range", strip_tags($value->title)));
+ $num = (float) $raw;
+ $smin = isset($value->scaleMin) ? (float) $value->scaleMin : 1;
+ $smax = isset($value->scaleMax) ? (float) $value->scaleMax : 5;
+ if ($smin > $smax) {
+ $t = $smin;
+ $smin = $smax;
+ $smax = $t;
+ }
+ if ($num < $smin || $num > $smax)
+ warning(lang("survey.validation.scale_range", strip_tags($value->title)));
+ }
+ }
+
$result = false;
if ($survey->verifyPhone) {
$result = $this->db->from("answers")
diff --git a/app/controllers/Reports.php b/app/controllers/Reports.php
index 7ec10bc..72c4265 100644
--- a/app/controllers/Reports.php
+++ b/app/controllers/Reports.php
@@ -44,7 +44,7 @@ public function watch(int $surveyId)
->from("personals")
->where("id", "!=", "0")
->where("status", "=", 1)
- ->orderBy("fullName", "ASC")
+ ->orderBy("fullname", "ASC")
->results();
$args = [
@@ -54,7 +54,8 @@ public function watch(int $surveyId)
"anonymous" => $survey->anonymous,
"surveyId" => $surveyId,
"departmentList" => $departmentList,
- "personList" => $personList
+ "personList" => $personList,
+ "reportEmptyLabel" => lang("survey.report.empty"),
];
if (!$survey->anonymous)
diff --git a/app/controllers/surveys.php b/app/controllers/surveys.php
index e19bae5..f94d8f3 100644
--- a/app/controllers/surveys.php
+++ b/app/controllers/surveys.php
@@ -8,6 +8,37 @@
class Surveys extends Controller
{
+ /** Strings for public/js/app.js (survey builder). */
+ protected function surveyBuilderI18nJson(): string
+ {
+ $keys = [
+ 'survey.builder.questions', 'survey.builder.create', 'survey.builder.developing', 'survey.builder.preview',
+ 'survey.builder.required', 'survey.builder.horizontal_layout', 'survey.builder.condition_none', 'survey.builder.close',
+ 'survey.builder.radio_list', 'survey.builder.checkbox_list', 'survey.builder.textarea', 'survey.builder.description',
+ 'survey.builder.short_text', 'survey.builder.email', 'survey.builder.phone', 'survey.builder.url', 'survey.builder.date', 'survey.builder.time',
+ 'survey.builder.number', 'survey.builder.select', 'survey.builder.scale',
+ 'survey.builder.star_rating', 'survey.builder.like_dislike_scale', 'survey.builder.single_choice_scale',
+ 'survey.builder.negative_label', 'survey.builder.positive_label', 'survey.builder.negative_value', 'survey.builder.positive_value',
+ 'survey.builder.neutral_value', 'survey.builder.steps', 'survey.builder.unsectioned_zone',
+ 'survey.builder.section', 'survey.builder.new_question', 'survey.builder.new_answer',
+ 'survey.builder.desc_subtype.info', 'survey.builder.desc_subtype.warning', 'survey.builder.desc_subtype.success', 'survey.builder.desc_subtype.danger',
+ 'survey.builder.max_length', 'survey.builder.min', 'survey.builder.max', 'survey.builder.step',
+ 'survey.builder.scale_from', 'survey.builder.scale_to', 'survey.builder.label_left', 'survey.builder.label_right',
+ 'survey.builder.cover_photo', 'survey.builder.upload_file', 'survey.builder.drag_drop', 'survey.builder.image_formats',
+ 'survey.builder.about_survey', 'survey.builder.about_hint', 'survey.builder.cancel', 'survey.builder.save',
+ 'survey.builder.anonymous_publish', 'survey.builder.apply_template', 'survey.builder.template_blank',
+ 'survey.builder.template_satisfaction', 'survey.builder.template_contact',
+ 'survey.builder.template_event_registration', 'survey.builder.template_customer_feedback', 'survey.builder.template_employee_pulse', 'survey.builder.template_lead_capture',
+ 'survey.builder.draft_banner', 'survey.builder.section_subtitle',
+ 'survey.builder.phone_placeholder', 'survey.builder.back', 'survey.builder.next', 'survey.builder.finish',
+ ];
+ $out = [];
+ foreach ($keys as $k) {
+ $out[$k] = lang($k);
+ }
+ return json_encode($out, JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_APOS);
+ }
+
#[route(method: route::get | route::xhr_get, session: "user")]
public function index()
{
@@ -30,7 +61,10 @@ public function create()
"url" => "apply",
"surveyFormTitle" => lang("create.survey"),
"user" => User::info(),
- "showIfOnEditMode" => false
+ "showIfOnEditMode" => false,
+ "surveyBuilderI18nJson" => $this->surveyBuilderI18nJson(),
+ "isSurveyEdit" => false,
+ "isSurveyCreateJs" => "true",
]);
}
@@ -178,7 +212,10 @@ public function edit(int $surveyId)
"user" => User::info(),
"surveyFormTitle" => $surveyFormTitle,
"url" => $isOnEditMode ? "apply/$surveyId" : "apply",
- "showIfOnEditMode" => $isOnEditMode ? "" : ""
+ "showIfOnEditMode" => $isOnEditMode ? "" : "",
+ "surveyBuilderI18nJson" => $this->surveyBuilderI18nJson(),
+ "isSurveyEdit" => true,
+ "isSurveyCreateJs" => "false",
]);
}
diff --git a/app/lang/en_US.php b/app/lang/en_US.php
index d886c1f..56855f7 100644
--- a/app/lang/en_US.php
+++ b/app/lang/en_US.php
@@ -116,5 +116,83 @@
"participate.sms.otp.body" => "Your verification code for the survey system: %s",
"participate.sms.otp.body.ascii" => "Survey verification code: %s",
"participate.email.otp.subject" => "Survey Verification Code",
- "participate.email.otp.body" => "Your verification code for survey participation: %s"
+ "participate.email.otp.body" => "Your verification code for survey participation: %s",
+ "participate.submit" => "Submit",
+
+ "survey.report.filled" => "Filled",
+ "survey.report.empty" => "Empty",
+
+ "survey.validation.checkbox_required" => "Please answer the question: %s",
+ "survey.validation.number_range" => "Enter a valid number for «%s».",
+ "survey.validation.scale_range" => "Choose a value within the scale for «%s».",
+
+ "survey.builder.questions" => "Questions",
+ "survey.builder.create" => "Add",
+ "survey.builder.developing" => "Edit",
+ "survey.builder.preview" => "Preview",
+ "survey.builder.required" => "Required",
+ "survey.builder.horizontal_layout" => "Horizontal layout",
+ "survey.builder.condition_none" => "None",
+ "survey.builder.close" => "Close",
+ "survey.builder.radio_list" => "Multiple choice",
+ "survey.builder.checkbox_list" => "Checkboxes",
+ "survey.builder.textarea" => "Paragraph",
+ "survey.builder.description" => "Description / info box",
+ "survey.builder.short_text" => "Short answer",
+ "survey.builder.email" => "Email",
+ "survey.builder.phone" => "Phone",
+ "survey.builder.url" => "URL",
+ "survey.builder.date" => "Date",
+ "survey.builder.time" => "Time",
+ "survey.builder.number" => "Number",
+ "survey.builder.select" => "Dropdown",
+ "survey.builder.scale" => "Linear scale",
+ "survey.builder.star_rating" => "Star rating (1-5)",
+ "survey.builder.like_dislike_scale" => "Like / Dislike scale",
+ "survey.builder.single_choice_scale" => "Single-choice scale range (1-10)",
+ "survey.builder.negative_label" => "Negative value",
+ "survey.builder.positive_label" => "Positive value",
+ "survey.builder.negative_value" => "Disliked",
+ "survey.builder.positive_value" => "Liked",
+ "survey.builder.neutral_value" => "Neutral",
+ "survey.builder.steps" => "Steps",
+ "survey.builder.unsectioned_zone" => "Unsectioned area (drop question here)",
+ "survey.builder.section" => "Section title",
+ "survey.builder.new_question" => "New question",
+ "survey.builder.new_answer" => "New option",
+ "survey.builder.desc_subtype.info" => "Info",
+ "survey.builder.desc_subtype.warning" => "Warning",
+ "survey.builder.desc_subtype.success" => "Success",
+ "survey.builder.desc_subtype.danger" => "Danger",
+ "survey.builder.max_length" => "Max length",
+ "survey.builder.min" => "Min",
+ "survey.builder.max" => "Max",
+ "survey.builder.step" => "Step",
+ "survey.builder.scale_from" => "Scale from",
+ "survey.builder.scale_to" => "Scale to",
+ "survey.builder.label_left" => "Left label",
+ "survey.builder.label_right" => "Right label",
+ "survey.builder.cover_photo" => "Cover image",
+ "survey.builder.upload_file" => "Upload a file",
+ "survey.builder.drag_drop" => "or drag and drop",
+ "survey.builder.image_formats" => "PNG, JPG, GIF up to 10MB",
+ "survey.builder.about_survey" => "About the survey",
+ "survey.builder.about_hint" => "Write a few sentences about the survey.",
+ "survey.builder.cancel" => "Cancel",
+ "survey.builder.save" => "Save",
+ "survey.builder.anonymous_publish" => "Publish as anonymous survey",
+ "survey.builder.apply_template" => "Template",
+ "survey.builder.template_blank" => "Blank",
+ "survey.builder.template_satisfaction" => "Quick satisfaction",
+ "survey.builder.template_contact" => "Contact details",
+ "survey.builder.template_event_registration" => "Event registration",
+ "survey.builder.template_customer_feedback" => "Customer feedback",
+ "survey.builder.template_employee_pulse" => "Employee pulse",
+ "survey.builder.template_lead_capture" => "Lead / quote form",
+ "survey.builder.draft_banner" => "A saved draft was restored.",
+ "survey.builder.section_subtitle" => "Section subtitle (optional)",
+ "survey.builder.phone_placeholder" => "+90 5xx xxx xx xx",
+ "survey.builder.back" => "Back",
+ "survey.builder.next" => "Next",
+ "survey.builder.finish" => "Finish",
];
\ No newline at end of file
diff --git a/app/lang/tr_TR.php b/app/lang/tr_TR.php
index d15eb35..bc26241 100644
--- a/app/lang/tr_TR.php
+++ b/app/lang/tr_TR.php
@@ -116,5 +116,83 @@
"participate.sms.otp.body" => "Anket sistemine giriş için onay kodu: %s",
"participate.sms.otp.body.ascii" => "Anket katilim icin onay kodu: %s",
"participate.email.otp.subject" => "Anket Doğrulama Kodu",
- "participate.email.otp.body" => "Anket katılımı için doğrulama kodunuz: %s"
+ "participate.email.otp.body" => "Anket katılımı için doğrulama kodunuz: %s",
+ "participate.submit" => "Gönder",
+
+ "survey.report.filled" => "Dolu",
+ "survey.report.empty" => "Boş",
+
+ "survey.validation.checkbox_required" => "%s sorusunu yanıtlayınız!",
+ "survey.validation.number_range" => "%s için geçerli bir sayı giriniz.",
+ "survey.validation.scale_range" => "%s için ölçek aralığında bir değer seçiniz.",
+
+ "survey.builder.questions" => "Sorular",
+ "survey.builder.create" => "Ekle",
+ "survey.builder.developing" => "Düzenle",
+ "survey.builder.preview" => "Önizleme",
+ "survey.builder.required" => "Zorunlu",
+ "survey.builder.horizontal_layout" => "Yatay olarak diz",
+ "survey.builder.condition_none" => "Seçili değil",
+ "survey.builder.close" => "Kapat",
+ "survey.builder.radio_list" => "Çoktan seçmeli (tek)",
+ "survey.builder.checkbox_list" => "Çoktan seçmeli (çoklu)",
+ "survey.builder.textarea" => "Uzun metin",
+ "survey.builder.description" => "Açıklama / bilgi kutusu",
+ "survey.builder.short_text" => "Kısa metin",
+ "survey.builder.email" => "E-posta",
+ "survey.builder.phone" => "Telefon",
+ "survey.builder.url" => "URL",
+ "survey.builder.date" => "Tarih",
+ "survey.builder.time" => "Saat",
+ "survey.builder.number" => "Sayı",
+ "survey.builder.select" => "Açılır liste",
+ "survey.builder.scale" => "Ölçek (doğrusal)",
+ "survey.builder.star_rating" => "Yıldız değerlendirme (1-5)",
+ "survey.builder.like_dislike_scale" => "Beğendim / Beğenmedim ölçeği",
+ "survey.builder.single_choice_scale" => "Tek seçimli ölçek aralığı (1-10)",
+ "survey.builder.negative_label" => "Negatif değer",
+ "survey.builder.positive_label" => "Pozitif değer",
+ "survey.builder.negative_value" => "Beğenmedim",
+ "survey.builder.positive_value" => "Beğendim",
+ "survey.builder.neutral_value" => "Kararsızım",
+ "survey.builder.steps" => "Adım sayısı",
+ "survey.builder.unsectioned_zone" => "Bölümsüz alan (soruyu buraya bırak)",
+ "survey.builder.section" => "Bölüm başlığı",
+ "survey.builder.new_question" => "Yeni soru",
+ "survey.builder.new_answer" => "Yeni seçenek",
+ "survey.builder.desc_subtype.info" => "Bilgi",
+ "survey.builder.desc_subtype.warning" => "Uyarı",
+ "survey.builder.desc_subtype.success" => "Başarı",
+ "survey.builder.desc_subtype.danger" => "Tehlike",
+ "survey.builder.max_length" => "Maks. uzunluk",
+ "survey.builder.min" => "Min",
+ "survey.builder.max" => "Max",
+ "survey.builder.step" => "Adım",
+ "survey.builder.scale_from" => "Ölçek başlangıç",
+ "survey.builder.scale_to" => "Ölçek bitiş",
+ "survey.builder.label_left" => "Sol etiket",
+ "survey.builder.label_right" => "Sağ etiket",
+ "survey.builder.cover_photo" => "Kapak görseli",
+ "survey.builder.upload_file" => "Dosya yükle",
+ "survey.builder.drag_drop" => "veya sürükleyip bırakın",
+ "survey.builder.image_formats" => "PNG, JPG, GIF en fazla 10MB",
+ "survey.builder.about_survey" => "Anket hakkında",
+ "survey.builder.about_hint" => "Anket için birkaç cümle yazın.",
+ "survey.builder.cancel" => "İptal",
+ "survey.builder.save" => "Kaydet",
+ "survey.builder.anonymous_publish" => "Anonim anket olarak yayımla",
+ "survey.builder.apply_template" => "Şablon",
+ "survey.builder.template_blank" => "Boş şablon",
+ "survey.builder.template_satisfaction" => "Memnuniyet (kısa)",
+ "survey.builder.template_contact" => "İletişim bilgisi",
+ "survey.builder.template_event_registration" => "Etkinlik kaydı",
+ "survey.builder.template_customer_feedback" => "Müşteri geri bildirimi",
+ "survey.builder.template_employee_pulse" => "Çalışan nabız anketi",
+ "survey.builder.template_lead_capture" => "Teklif / lead formu",
+ "survey.builder.draft_banner" => "Kayıtlı taslak bulundu; alanlar geri yüklendi.",
+ "survey.builder.section_subtitle" => "Bölüm alt başlığı (isteğe bağlı)",
+ "survey.builder.phone_placeholder" => "05xx xxx xx xx",
+ "survey.builder.back" => "Geri",
+ "survey.builder.next" => "İleri",
+ "survey.builder.finish" => "Bitir",
];
\ No newline at end of file
diff --git a/app/models/Survey.php b/app/models/Survey.php
index da417ab..a692b53 100644
--- a/app/models/Survey.php
+++ b/app/models/Survey.php
@@ -78,7 +78,7 @@ public static function participators(int $surveyId)
$participators = [];
foreach ($uniqueParticipants as $participant) {
$fullData = Database::get()
- ->select("answers.*, personals.fullname, personals.department")
+ ->select("answers.*, personals.fullname, personals.department, personals.phone1, personals.phone2, personals.status")
->from("answers")
->leftJoin("personals", "personals.id = answers.personalId")
->where("answers.id", "=", $participant->maxId)
@@ -149,6 +149,20 @@ public static function generateReportData($survey)
}
$generatedData = [];
+ $slugToSection = [];
+ $sectionSlugs = [];
+ $activeSectionSlug = null;
+ foreach ($questionData as $q) {
+ if (! isset($q->slug))
+ continue;
+ if ($q->type === "section") {
+ $activeSectionSlug = $q->slug;
+ $sectionSlugs[$q->slug] = true;
+ $slugToSection[$q->slug] = $q->slug;
+ continue;
+ }
+ $slugToSection[$q->slug] = $activeSectionSlug;
+ }
$groupIndex = 0;
#for IK
@@ -158,13 +172,24 @@ public static function generateReportData($survey)
$groups = ["default"];
$isFirstDescription = true;
+ $currentGroupName = $groups[$groupIndex] ?? "default";
foreach ($questionData as $question) {
+ if ($question->type == "section") {
+ $sectionTitle = trim(strip_tags((string) ($question->title ?? "")));
+ if ($sectionTitle === "")
+ $sectionTitle = "section-" . ($groupIndex + 1);
+ $currentGroupName = $sectionTitle;
+ continue;
+ }
+
if ($question->type == "description") {
if ($isFirstDescription)
$isFirstDescription = false;
- else
+ else {
$groupIndex++;
+ $currentGroupName = $groups[$groupIndex] ?? $currentGroupName;
+ }
continue;
}
@@ -187,7 +212,25 @@ public static function generateReportData($survey)
}
}
- $group0 = $groups[$groupIndex];
+ if (! $hasCondition) {
+ $sectionSlug = $slugToSection[$question->slug] ?? null;
+ if ($sectionSlug && isset($sectionSlugs[$sectionSlug]) && $sectionSlug !== $question->slug) {
+ foreach ($questionData as $parentQ) {
+ if (empty($parentQ->conditions))
+ continue;
+ foreach ($parentQ->conditions as $cond) {
+ if ($cond->value == $sectionSlug) {
+ $hasCondition = true;
+ $parentQuestion = $parentQ;
+ $parentAnswerIndex = $cond->index;
+ break 2;
+ }
+ }
+ }
+ }
+ }
+
+ $group0 = $currentGroupName ?: ($groups[$groupIndex] ?? "default");
// Radio için tüm katılımcıları döndüren fonksiyon
$searchAll = function () use ($question, $answerData, $hasCondition, $parentQuestion, $parentAnswerIndex) {
@@ -233,7 +276,7 @@ public static function generateReportData($survey)
$s = $question->type == "checkbox" ? $question->slug . $k : $question->slug;
$exists = array_key_exists($s, $decodedJson);
- if ($exists && $question->type == "radio")
+ if ($exists && ($question->type == "radio" || $question->type == "select" || $question->type == "sentiment_scale"))
return $decodedJson[$s] == $k;
return $exists;
@@ -241,8 +284,8 @@ public static function generateReportData($survey)
}, ARRAY_FILTER_USE_BOTH);
};
- // Radio ve checkbox için farklı işlem
- if ($question->type == "radio") {
+ // Radio, select ve checkbox için farklı işlem
+ if ($question->type == "radio" || $question->type == "select" || $question->type == "sentiment_scale") {
// Radio için: Her katılımcıyı bir kez kontrol et ve cevabını bul
$allParticipants = $searchAll();
@@ -297,18 +340,21 @@ public static function generateReportData($survey)
}
}
- if ($question->type != "textarea")
+ $textLike = ["textarea", "short_text", "email", "number", "scale", "url", "phone", "date", "time"];
+ if (! in_array($question->type, $textLike, true))
continue;
$data = $searchAll();
foreach ($data as $answer) {
- $answerValue = json_decode($answer->data, JSON_OBJECT_AS_ARRAY)[$question->slug];
+ $decoded = json_decode($answer->data, JSON_OBJECT_AS_ARRAY);
+ if (! isset($decoded[$question->slug]))
+ continue;
+ $answerValue = $decoded[$question->slug];
$generatedData[$group0][$question->type . "::" . $question->title][] = (object) [
"id" => $answer->participantKey ?? $answer->personalId,
"fullname" => $answer->fullname,
"department" => $answer->department,
- #"answer" => $answerTitle,
"value" => $answerValue
];
@@ -324,78 +370,71 @@ public static function report($survey)
$result = [];
- $group0Data = current($generatedData);
- if (! $group0Data)
- $group0Data = [];
+ foreach ($generatedData as $groupName => $groupQuestions) {
+ foreach ($groupQuestions as $key => $question) {
+ $split = explode("::", $key, 2);
- foreach ($group0Data as $key => $question) {
- $split = explode("::", $key);
+ $type = $split[0] ?? "unknown";
+ $title = $split[1] ?? $key;
+ $displayTitle = ($groupName && $groupName !== "default")
+ ? ($groupName . " / " . $title)
+ : $title;
- $type = $split[0];
- $title = $split[1];
+ $result[$displayTitle] = [
+ "type" => $type,
+ "group" => $groupName,
+ ];
- $result[$title] = [
- "type" => $type
- ];
+ $result[$displayTitle]["list-json"] = [];
- $result[$title]["list-json"] = [];
+ $totalCount = 0;
+ if ($type === "radio" || $type === "checkbox" || $type === "select" || $type === "sentiment_scale") {
+ $uniqueParticipantIds = [];
- $totalCount = 0;
- if ($type === "radio" || $type === "checkbox") {
- // Radio ve Checkbox için benzersiz katılımcı sayısını hesaplamak için
- $uniqueParticipantIds = [];
-
- foreach ($question as $answerK => $answerV) {
- $count = count($answerV);
- $result[$title]["answers"][$answerK] = $count;
-
- // Radio ve Checkbox için benzersiz katılımcı ID'lerini topla
- foreach ($answerV as $participant) {
- // personalId veya id field'ını kontrol et
- $participantId = $participant->id ?? $participant->personalId ?? null;
- if ($participantId && !in_array($participantId, $uniqueParticipantIds)) {
- $uniqueParticipantIds[] = $participantId;
+ foreach ($question as $answerK => $answerV) {
+ $count = count($answerV);
+ $result[$displayTitle]["answers"][$answerK] = $count;
+
+ foreach ($answerV as $participant) {
+ $participantId = $participant->id ?? $participant->personalId ?? null;
+ if ($participantId && !in_array($participantId, $uniqueParticipantIds)) {
+ $uniqueParticipantIds[] = $participantId;
+ }
}
}
- }
-
- // Radio ve Checkbox için benzersiz katılımcı sayısını kullan
- $totalCount = count($uniqueParticipantIds);
- $result[$title]["total"] = $totalCount;
- } else {
- // Textarea için benzersiz katılımcı sayısını hesaplamak için
- $uniqueParticipantIds = [];
- $emptyCount = $fillCount = 0;
-
- foreach ($question as $answerK => $answerV) {
- // personalId veya id field'ını kontrol et
- $participantId = $answerV->id ?? $answerV->personalId ?? null;
-
- // Benzersiz katılımcı kontrolü
- if ($participantId && !in_array($participantId, $uniqueParticipantIds)) {
- $uniqueParticipantIds[] = $participantId;
-
- if (empty($answerV->value))
- $emptyCount++;
- else {
- $fillCount++;
- $result[$title]["list-json"][] = $answerV;
+ $totalCount = count($uniqueParticipantIds);
+ $result[$displayTitle]["total"] = $totalCount;
+ } else {
+ $uniqueParticipantIds = [];
+ $emptyCount = $fillCount = 0;
+
+ foreach ($question as $answerK => $answerV) {
+ $participantId = $answerV->id ?? $answerV->personalId ?? null;
+
+ if ($participantId && !in_array($participantId, $uniqueParticipantIds)) {
+ $uniqueParticipantIds[] = $participantId;
+
+ if (empty($answerV->value))
+ $emptyCount++;
+ else {
+ $fillCount++;
+ $result[$displayTitle]["list-json"][] = $answerV;
+ }
}
}
- }
- $result[$title]["answers"] = [
- "Dolu" => $fillCount,
- "Boş" => $emptyCount
- ];
+ $result[$displayTitle]["answers"] = [
+ lang("survey.report.filled") => $fillCount,
+ lang("survey.report.empty") => $emptyCount
+ ];
- $totalCount = count($uniqueParticipantIds);
+ $totalCount = count($uniqueParticipantIds);
+ $result[$displayTitle]["list-json"] = data_json($result[$displayTitle]["list-json"]);
+ }
- $result[$title]["list-json"] = data_json($result[$title]["list-json"]);
+ $result[$displayTitle]["total"] = $totalCount;
}
-
- $result[$title]["total"] = $totalCount;
}
return $result;
diff --git a/app/views/main.php b/app/views/main.php
index 2374f39..dba2112 100644
--- a/app/views/main.php
+++ b/app/views/main.php
@@ -37,11 +37,11 @@