Skip to content

Commit

Permalink
feat: add docs
Browse files Browse the repository at this point in the history
  • Loading branch information
yjose committed Sep 30, 2024
1 parent 5850ff7 commit f44abe5
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 6 deletions.
101 changes: 101 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,103 @@ pnpm dev

Your website is now running at `http://localhost:4321`

## How the survey works

The survey form submission process is designed to be secure, anonymous, and user-friendly. Here's an overview of how it works:

1. **Session Initialization (Before Start Page)**

- When the user clicks the `Take part in the survey` button from the home page, they are redirected to the `/before-start` page where they find important information about the survey.
- A CAPTCHA is displayed to prevent spam submissions(using Cloudflare Turnstile).
- When the user clicks "Start":
- An anonymous Firebase authentication session is created.
- The session token and CAPTCHA token are sent to the server (actions/initialize-session.ts).
- The server (actions/initialize-session.ts) validates the Firebase session and the CAPTCHA, initializes the session, and sets a session cookie.
- Upon successful initialization, the user is redirected to the `/survey` page.

2. **Survey Page**

- The page checks for an active session before displaying the survey form.
- If no valid session is found, the user is redirected back to the `/before-start` page.
- With a valid session, the SurveyForm component is rendered.

3. **Survey Form Component**

- Questions are loaded from YAML files and presented to the user in sections.
- Based on the question type, the form changes (radio, checkbox, etc.) and shows a text area if the user selects an option that contains "other".
- At the end of each section, answers are validated and sent to the server (actions/submit-answers.ts).

```js
// example of the data sent to the server
const answers = {
"profile-q-0": 1,
"profile-q-1": 2,
"profile-q-2": [3, 2], // multiple choice question
"profile-q-3": 6, // single choice question
"profile-q-3-other": "text", // other text
"profile-q-4": null // null if the question is not answered (skip button)
};
```

For every question, we send the index of choices selected by the user. It should be a number if the question is single choice, and an array of numbers if the question is multiple choice. We also send "other" text if the user selects an option that contains "other" and adds custom text to the text area.

- The server (actions/submit-answers.ts) verifies the session, processes the answers, and saves them to the Firestore database with the user ID as the document ID. This way, we can avoid duplicate submissions, and in case of a repeat submission, we will only update the existing document.

4. **Completion and Thanks Page**

- After completing all sections, the user is redirected to the "Thanks" page.
- A thank you message is displayed along with social sharing options.

## How the results works

Every day at 12:00 AM UTC we run a github action that export data from firestore and the file should look like this:

```json
{
"results": [
{
"profile-q-0": 1,
"profile-q-1": 2,
"profile-q-2": [3, 2],
"profile-q-3": 6,
"profile-q-3-other": "text",
"lastSignInTime": "Tue, 17 Sep 2024 11:57:46 GMT",
"creationTime": "Tue, 17 Sep 2024 11:57:46 GMT",
"userId": "..."
},
...
]
}
```

Then we generate a json file for survey questions with their choices and ids.

```json
{
"profile-q-0": {
"label": "What is your gender?",
"required": true,
"multiple": false,
"choices": ["Male", "Female"]
},
"profile-q-1": {
"label": "What is your age?",
"required": true,
"choices": [
"Younger than 18 years",
"18 to 24 years",
"25 to 34 years",
"35 to 44 years",
"45 or older"
],
"multiple": false
},
...
}
```

Now that we have the results and the questions. we use `getQuestion` in `components/chart/utils.ts` file to get data for any question id then render it using `Chart` component.

## 🧐 Want to contribute ?

If you want to contribute check out the [help wanted](https://github.com/geeksblabla/stateofdev.ma/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22+sort%3Aupdated-desc) issues for things that need fixing, or suggest some new features by opening new issues.
Expand Down Expand Up @@ -133,3 +230,7 @@ This project is inspired by :

- [Stack Overflow Survey ](https://insights.stackoverflow.com/survey/2020)
- [State of Front-end Survey](https://tsh.io/state-of-frontend/)

```
```
4 changes: 2 additions & 2 deletions src/components/header-link.astro
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ const { label, href, external = false, isActive = false } = Astro.props;
href={href}
class={`block cursor-pointer items-center pt-2 border-b-2 border-dashed pb-0 transition-colors duration-200 ${
isActive
? "text-emerald-700 border-emerald-700"
: "text-black hover:text-emerald-700 border-current"
? "text-emerald-800 border-emerald-800"
: "text-black hover:text-emerald-800 border-current"
}`}
target={external ? "_blank" : undefined}
>
Expand Down
2 changes: 1 addition & 1 deletion src/components/header.astro
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const currentPath = Astro.url.pathname;
class="z-[99] relative bg-transparent max-w-screen-xl w-full px-4 py-4 text-emerald-900 md:mx-auto"
>
<div class="flex justify-between items-center">
<a href="/" class="z-10">
<a href="/" class="z-10" aria-label="state of dev logo">
<div
class="flex cursor-pointer items-center whitespace-nowrap text-2xl font-black"
>
Expand Down
8 changes: 8 additions & 0 deletions src/components/social-media-card.astro
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,14 @@ const shareLinks = {
href={shareLinks.twitter}
class="text-gray-400 hover:text-emerald-500"
title="Share on Twitter"
aria-label="Share on Twitter"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
viewBox="0 0 24 24"
fill="currentColor"
aria-hidden="true"
>
<path
d="M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z"
Expand All @@ -68,12 +70,14 @@ const shareLinks = {
href={shareLinks.linkedin}
class="text-gray-400 hover:text-emerald-500"
title="Share on LinkedIn"
aria-label="Share on LinkedIn"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
viewBox="0 0 24 24"
fill="currentColor"
aria-hidden="true"
>
<path
d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.065 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"
Expand All @@ -84,12 +88,14 @@ const shareLinks = {
href={shareLinks.facebook}
class="text-gray-400 hover:text-emerald-500"
title="Share on Facebook"
aria-label="Share on Facebook"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
viewBox="0 0 24 24"
fill="currentColor"
aria-hidden="true"
>
<path
d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"
Expand All @@ -99,6 +105,7 @@ const shareLinks = {
<button
class="text-gray-400 hover:text-emerald-500 relative"
title="Copy Content"
aria-label="Copy Content"
data-id="copyButton"
data-content={post.content}
>
Expand All @@ -111,6 +118,7 @@ const shareLinks = {
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"
Expand Down
6 changes: 3 additions & 3 deletions src/components/survey/exit-popup.astro
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ import finImage from "@/assets/fin.jpeg";
</div>

<script>
const surveyForm = document.getElementById("survey-form") as HTMLDivElement;
const body = document.body;
let popupShownCount = 0;
const maxPopupShows = 2;

if (surveyForm) {
surveyForm.addEventListener("mouseleave", function (e: MouseEvent) {
if (body) {
body.addEventListener("mouseleave", function (e: MouseEvent) {
if (popupShownCount < maxPopupShows) {
// Show the custom modal
const modal = document.getElementById("exitModal") as HTMLDivElement;
Expand Down

0 comments on commit f44abe5

Please sign in to comment.