Merge pull request #400 from appwrite/refactor-feedback

refactor: feedback dropdown and wizard
This commit is contained in:
Torsten Dittmann
2023-07-20 14:51:04 +02:00
committed by GitHub
18 changed files with 609 additions and 209 deletions
@@ -1,40 +1,41 @@
<script lang="ts">
import { Button, Form } from '$lib/elements/forms';
import {
Form,
FormList,
InputTextarea,
Button,
InputText,
InputEmail
} from '$lib/elements/forms';
import { feedback } from '$lib/stores/app';
feedback,
selectedFeedback,
feedbackOptions,
feedbackData
} from '$lib/stores/feedback';
import { addNotification } from '$lib/stores/notifications';
let message: string;
let name: string;
let email: string;
async function handleSubmit() {
try {
await feedback.submitFeedback('feedback-general', message, name, email);
$: $selectedFeedback = feedbackOptions.find((option) => option.type === $feedback.type);
async function submit() {
try {
await feedback.submitFeedback(
`feedback-${$feedback.type}`,
$feedbackData.message,
$feedbackData.name,
$feedbackData.email
);
addNotification({
type: 'success',
message: 'Feedback submitted successfully'
});
feedback.toggleFeedback();
feedbackData.reset();
} catch (error) {
addNotification({
type: 'error',
message: error.message
});
} finally {
feedback.toggleFeedback();
}
}
</script>
<section class="drop-section">
<header class="u-flex u-main-space-between u-gap-16">
<h4 class="body-text-1 u-bold">How can we improve?</h4>
<h4 class="body-text-1 u-bold">{$selectedFeedback.title}</h4>
<button
type="button"
class="button is-text is-only-icon u-margin-inline-start-auto"
@@ -46,21 +47,11 @@
</button>
</header>
<div class="u-margin-block-start-8 u-line-height-1-5">
Your feedback is important to us. Please be honest and tell us what you think.
{$selectedFeedback.desc}
</div>
<Form onSubmit={handleSubmit}>
<FormList>
<InputText label="Name" id="name" bind:value={name} placeholder="Enter name" />
<InputEmail label="Email" id="email" bind:value={email} placeholder="Enter email" />
<InputTextarea
id="feedback"
placeholder="Your message here"
label="Message"
required
bind:value={message} />
</FormList>
<Form onSubmit={submit}>
<svelte:component this={$selectedFeedback.component} />
<div class="u-flex u-main-end u-gap-16 u-margin-block-start-24">
<Button text on:click={() => feedback.toggleFeedback()}>Cancel</Button>
<Button secondary submit>Submit</Button>
@@ -0,0 +1,19 @@
<script lang="ts">
import { FormList, InputTextarea, InputText, InputEmail } from '$lib/elements/forms';
import { feedbackData } from '$lib/stores/feedback';
</script>
<FormList>
<InputText label="Name" id="name" bind:value={$feedbackData.name} placeholder="Enter name" />
<InputEmail
label="Email"
id="email"
bind:value={$feedbackData.email}
placeholder="Enter email" />
<InputTextarea
id="feedback"
placeholder="Your message here"
label="Message"
required
bind:value={$feedbackData.message} />
</FormList>
@@ -0,0 +1,30 @@
<script lang="ts">
import { FormList, InputTextarea, InputText, InputEmail } from '$lib/elements/forms';
import { feedbackData } from '$lib/stores/feedback';
import Evaluation from './evaluation.svelte';
</script>
<Evaluation bind:value={$feedbackData.value}>
How likely are you to recommend Appwrite to a friend or colleague?
</Evaluation>
{#if $feedbackData.value}
<FormList>
<InputTextarea
id="feedback"
placeholder="Your message here"
label="Message"
required
bind:value={$feedbackData.message}
showLabel={false} />
<InputText
label="Name"
id="name"
bind:value={$feedbackData.name}
placeholder="Enter name" />
<InputEmail
label="Email"
id="email"
bind:value={$feedbackData.email}
placeholder="Enter email" />
</FormList>
{/if}
+3
View File
@@ -0,0 +1,3 @@
export { default as Feedback } from './feedback.svelte';
export { default as FeedbackGeneral } from './feedbackGeneral.svelte';
export { default as FeedbackNPS } from './feedbackNPS.svelte';
-78
View File
@@ -1,78 +0,0 @@
<script lang="ts">
import {
Form,
FormList,
InputTextarea,
Button,
InputText,
InputEmail
} from '$lib/elements/forms';
import { feedback } from '$lib/stores/app';
import { addNotification } from '$lib/stores/notifications';
import Evaluation from './evaluation.svelte';
let value: number = null;
let message: string;
let email: string;
let name: string;
async function handleSubmit() {
try {
await feedback.submitFeedback('feedback-nps', message, name, email, value);
feedback.switchType('general');
addNotification({
type: 'success',
message: 'Thank you for your feedback!'
});
} catch (error) {
feedback.switchType('general');
addNotification({
type: 'error',
message: error.message
});
} finally {
feedback.toggleFeedback();
}
}
</script>
<section class="drop-section">
<header class="u-flex u-main-space-between u-gap-16">
<h4 class="body-text-1 u-bold">How are we doing?</h4>
<button
type="button"
class="button is-text is-only-icon u-margin-inline-start-auto"
style="--button-size:1.5rem;"
aria-label="Close Modal"
title="Close Modal"
on:click={() => feedback.toggleFeedback()}>
<span class="icon-x" aria-hidden="true" />
</button>
</header>
<div class="u-margin-block-start-8 u-line-height-1-5">
At Appwrite, we value the feedback of our users. That means you! We'd love to hear what you
think.
</div>
<Form onSubmit={handleSubmit}>
<Evaluation bind:value>
How likely are you to recommend Appwrite to a friend or colleague?
</Evaluation>
{#if value}
<FormList>
<InputTextarea
id="feedback"
placeholder="Your message here"
label="Message"
required
bind:value={message}
showLabel={false} />
<InputText label="Name" id="name" bind:value={name} placeholder="Enter name" />
<InputEmail label="Email" id="email" bind:value={email} placeholder="Enter email" />
</FormList>
{/if}
<div class="u-flex u-main-end u-gap-16 u-margin-block-start-24">
<Button text on:click={() => feedback.toggleFeedback()}>No thanks</Button>
<Button disabled={!value} secondary submit>Submit</Button>
</div>
</Form>
</section>
-3
View File
@@ -31,9 +31,6 @@ export { default as Box } from './box.svelte';
export { default as Search } from './search.svelte';
export { default as SearchQuery } from './searchQuery.svelte';
export { default as GridItem1 } from './gridItem1.svelte';
export { default as FeedbackGeneral } from './feedbackGeneral.svelte';
export { default as FeedbackNPS } from './feedbackNPS.svelte';
export { default as Evaluation } from './evaluation.svelte';
export { default as Steps } from './steps.svelte';
export { default as Step } from './step.svelte';
export { default as Code } from './code.svelte';
+138
View File
@@ -0,0 +1,138 @@
<svg width="236" height="175" viewBox="0 0 236 175" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M57.4121 116.254C57.4121 140.493 88.4892 145.072 93.5568 119.917" stroke="url(#paint0_radial_571_90123)" stroke-width="12"/>
<path d="M107.204 44.209L35.9817 91.6489C30.5629 100.178 37.1467 119.049 45.0168 119.528C52.887 120.008 137.394 126.511 137.394 126.511L107.204 44.209Z" fill="url(#paint1_linear_571_90123)" fill-opacity="0.4"/>
<g filter="url(#filter0_d_571_90123)">
<path d="M108.82 33.6465L39.8891 88.9015C34.7605 98.6703 42.5145 119.368 49.9632 119.918C57.412 120.467 137.394 127.916 137.394 127.916L108.82 33.6465Z" fill="url(#paint2_linear_571_90123)"/>
</g>
<path d="M142.595 74.954C146.53 88.0347 148.092 100.432 147.467 109.883C147.154 114.613 146.297 118.55 144.956 121.454C143.615 124.36 141.847 126.123 139.755 126.752C137.664 127.381 135.217 126.886 132.495 125.202C129.775 123.519 126.888 120.709 124.018 116.936C118.283 109.398 112.747 98.1959 108.812 85.1152C104.878 72.0345 103.315 59.6372 103.941 50.1857C104.254 45.456 105.111 41.5194 106.451 38.6151C107.792 35.7094 109.561 33.9466 111.652 33.3175C113.744 32.6884 116.191 33.1832 118.912 34.8671C121.633 36.55 124.519 39.3605 127.389 43.1328C133.125 50.6711 138.661 61.8733 142.595 74.954Z" fill="url(#paint3_linear_571_90123)" stroke="url(#paint4_linear_571_90123)" stroke-width="2"/>
<path d="M114.593 98.8532C114.593 98.8532 121.351 95.3299 122.591 91.7119C123.832 88.0939 122.287 81.9135 120.565 76.1934C118.843 70.4732 105.786 69.9484 105.786 69.9484C108.725 83.3674 110.852 89.2767 114.593 98.8532Z" fill="url(#paint5_linear_571_90123)" fill-opacity="0.3"/>
<ellipse cx="120.194" cy="82.5991" rx="2.00454" ry="10.2947" transform="rotate(-14.7165 120.194 82.5991)" fill="url(#paint6_linear_571_90123)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M172.267 33.0303C159.653 27.4164 144.876 33.0914 139.262 45.7057L138.929 46.4536C133.316 59.0679 138.991 73.8448 151.605 79.4587L156.662 81.7093C156.179 82.3785 155.895 83.211 155.916 84.1363L155.978 86.7736C156.057 90.1179 159.961 91.8943 162.534 89.7561L164.563 88.0699C165.299 87.4579 165.745 86.6643 165.921 85.8298L170.525 87.8787C183.139 93.4926 197.916 87.8176 203.53 75.2033L203.862 74.4554C209.476 61.8411 203.801 47.0642 191.187 41.4503L172.267 33.0303Z" fill="url(#paint7_linear_571_90123)"/>
<path d="M165.517 87.4798L160.655 91.5071C159.16 92.7454 157.442 93.639 155.506 93.776C154.556 93.8432 154.265 93.1232 154 92.9993C155.828 92.8779 157.297 92.4752 157.68 91.9631L163.801 86.7594L165.517 87.4798Z" fill="#8B2A56"/>
<path d="M158.141 26.648C152.649 24.3428 146.941 27.6001 144.975 29.3993C149.627 26.5875 154.943 27.6946 157.019 28.5997L202.118 48.1322C208.529 51.7113 207.777 59.0198 206.599 62.2266L194.603 88.8868C191.478 94.6007 186.913 95.5851 185.021 95.3631C191.256 96.2841 195.705 91.8728 197.15 89.552L209.506 62.0336C212.455 53.6616 208.162 49.1214 205.648 47.8979C191.967 41.8535 163.634 28.9532 158.141 26.648Z" fill="url(#paint8_linear_571_90123)"/>
<mask id="path-10-inside-1_571_90123" fill="white">
<path fill-rule="evenodd" clip-rule="evenodd" d="M155.683 27.5397C150.638 25.2942 144.727 27.5642 142.481 32.6099L129.951 60.7661C127.705 65.8118 129.975 71.7225 135.021 73.9681L152.971 81.9568L153.195 91.517C153.235 93.1892 155.187 94.0774 156.473 93.0083L163.912 86.8257L181.349 94.5859C186.395 96.8315 192.305 94.5615 194.551 89.5158L207.082 61.3596C209.327 56.3139 207.057 50.4031 202.011 48.1576L155.683 27.5397Z"/>
</mask>
<path fill-rule="evenodd" clip-rule="evenodd" d="M155.683 27.5397C150.638 25.2942 144.727 27.5642 142.481 32.6099L129.951 60.7661C127.705 65.8118 129.975 71.7225 135.021 73.9681L152.971 81.9568L153.195 91.517C153.235 93.1892 155.187 94.0774 156.473 93.0083L163.912 86.8257L181.349 94.5859C186.395 96.8315 192.305 94.5615 194.551 89.5158L207.082 61.3596C209.327 56.3139 207.057 50.4031 202.011 48.1576L155.683 27.5397Z" fill="url(#paint9_linear_571_90123)"/>
<path d="M142.481 32.6099L141.568 32.2033L142.481 32.6099ZM155.683 27.5397L156.09 26.6261L155.683 27.5397ZM129.951 60.7661L129.037 60.3595L129.951 60.7661ZM135.021 73.9681L135.428 73.0545L135.021 73.9681ZM152.971 81.9568L153.971 81.9333L153.956 81.3005L153.378 81.0431L152.971 81.9568ZM153.195 91.517L152.196 91.5405L153.195 91.517ZM156.473 93.0083L157.112 93.7773L156.473 93.0083ZM163.912 86.8257L164.318 85.9121L163.751 85.6594L163.273 86.0566L163.912 86.8257ZM181.349 94.5859L180.942 95.4995L181.349 94.5859ZM194.551 89.5158L193.637 89.1092L194.551 89.5158ZM207.082 61.3596L206.168 60.953L206.168 60.953L207.082 61.3596ZM202.011 48.1576L202.418 47.2439L202.418 47.2439L202.011 48.1576ZM143.395 33.0165C145.416 28.4753 150.736 26.4323 155.277 28.4533L156.09 26.6261C150.54 24.156 144.038 26.653 141.568 32.2033L143.395 33.0165ZM130.864 61.1727L143.395 33.0165L141.568 32.2033L129.037 60.3595L130.864 61.1727ZM135.428 73.0545C130.886 71.0335 128.843 65.7138 130.864 61.1727L129.037 60.3595C126.567 65.9098 129.064 72.4116 134.614 74.8817L135.428 73.0545ZM153.378 81.0431L135.428 73.0545L134.614 74.8817L152.565 82.8704L153.378 81.0431ZM154.195 91.4936L153.971 81.9333L151.972 81.9802L152.196 91.5405L154.195 91.4936ZM155.834 92.2392C155.191 92.7738 154.215 92.3297 154.195 91.4936L152.196 91.5405C152.254 94.0487 155.183 95.381 157.112 93.7773L155.834 92.2392ZM163.273 86.0566L155.834 92.2392L157.112 93.7773L164.551 87.5947L163.273 86.0566ZM181.756 93.6723L164.318 85.9121L163.505 87.7393L180.942 95.4995L181.756 93.6723ZM193.637 89.1092C191.616 93.6503 186.297 95.6933 181.756 93.6723L180.942 95.4995C186.493 97.9696 192.994 95.4727 195.465 89.9224L193.637 89.1092ZM206.168 60.953L193.637 89.1092L195.465 89.9224L207.995 61.7662L206.168 60.953ZM201.605 49.0712C206.146 51.0922 208.189 56.4118 206.168 60.953L207.995 61.7662C210.465 56.2159 207.968 49.7141 202.418 47.2439L201.605 49.0712ZM155.277 28.4533L201.605 49.0712L202.418 47.2439L156.09 26.6261L155.277 28.4533Z" fill="url(#paint10_linear_571_90123)" mask="url(#path-10-inside-1_571_90123)"/>
<ellipse cx="4.40454" cy="4.40454" rx="4.40454" ry="4.40454" transform="matrix(0.894697 0.397317 -0.36312 0.950578 149.662 47.835)" fill="#892450"/>
<ellipse cx="4.40454" cy="4.40454" rx="4.40454" ry="4.40454" transform="matrix(0.894697 0.397317 -0.36312 0.950578 148.198 47.8135)" fill="url(#paint11_linear_571_90123)"/>
<ellipse cx="4.40454" cy="4.40454" rx="4.40454" ry="4.40454" transform="matrix(0.894697 0.397317 -0.36312 0.950578 166.811 55.4512)" fill="#892450"/>
<ellipse cx="4.40454" cy="4.40454" rx="4.40454" ry="4.40454" transform="matrix(0.894697 0.397317 -0.36312 0.950578 165.348 55.4297)" fill="url(#paint12_linear_571_90123)"/>
<ellipse cx="4.40454" cy="4.40454" rx="4.40454" ry="4.40454" transform="matrix(0.894697 0.397317 -0.36312 0.950578 183.96 63.0664)" fill="#892450"/>
<ellipse cx="4.40454" cy="4.40454" rx="4.40454" ry="4.40454" transform="matrix(0.894697 0.397317 -0.36312 0.950578 182.498 63.0449)" fill="url(#paint13_linear_571_90123)"/>
<g filter="url(#filter1_f_571_90123)">
<path d="M63.2684 28.0889L65.3066 31.8156L69.0334 33.8538L65.3066 35.8921L63.2684 39.6188L61.2302 35.8921L57.5034 33.8538L61.2302 31.8156L63.2684 28.0889Z" fill="url(#paint14_radial_571_90123)" fill-opacity="0.6"/>
</g>
<g filter="url(#filter2_f_571_90123)">
<path d="M225.574 13.8984L228.553 19.3452L234 22.3242L228.553 25.3031L225.574 30.7499L222.595 25.3031L217.148 22.3242L222.595 19.3452L225.574 13.8984Z" fill="url(#paint15_radial_571_90123)" fill-opacity="0.6"/>
</g>
<g filter="url(#filter3_f_571_90123)">
<path d="M171.472 111.903L173.04 114.77L175.907 116.338L173.04 117.906L171.472 120.772L169.904 117.906L167.038 116.338L169.904 114.77L171.472 111.903Z" fill="url(#paint16_radial_571_90123)" fill-opacity="0.6"/>
</g>
<defs>
<filter id="filter0_d_571_90123" x="0.233643" y="0.646484" width="179.161" height="174.27" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="2" dy="7"/>
<feGaussianBlur stdDeviation="20"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.245833 0 0 0 0 0.255044 0 0 0 0 0.333333 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_571_90123"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_571_90123" result="shape"/>
</filter>
<filter id="filter1_f_571_90123" x="55.5034" y="26.0889" width="15.53" height="15.5303" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="1" result="effect1_foregroundBlur_571_90123"/>
</filter>
<filter id="filter2_f_571_90123" x="215.148" y="11.8984" width="20.8516" height="20.8516" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="1" result="effect1_foregroundBlur_571_90123"/>
</filter>
<filter id="filter3_f_571_90123" x="165.038" y="109.903" width="12.8691" height="12.8691" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="1" result="effect1_foregroundBlur_571_90123"/>
</filter>
<radialGradient id="paint0_radial_571_90123" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(78.2319 119.062) rotate(53.6887) scale(22.2166 32.3419)">
<stop stop-color="#202130"/>
<stop offset="0.317708" stop-color="#33374B"/>
<stop offset="0.484375" stop-color="#33374B"/>
<stop offset="0.905609" stop-color="#20202F"/>
</radialGradient>
<linearGradient id="paint1_linear_571_90123" x1="41.4436" y1="121.838" x2="52.7291" y2="75.4951" gradientUnits="userSpaceOnUse">
<stop stop-color="#292B3D"/>
<stop offset="0.630208" stop-color="#4B506A"/>
</linearGradient>
<linearGradient id="paint2_linear_571_90123" x1="71.3936" y1="52.3904" x2="98.8316" y2="131.923" gradientUnits="userSpaceOnUse">
<stop offset="0.274562" stop-color="#33364A"/>
<stop offset="1" stop-color="#13141D"/>
</linearGradient>
<linearGradient id="paint3_linear_571_90123" x1="121.215" y1="-12.9999" x2="137.25" y2="140.807" gradientUnits="userSpaceOnUse">
<stop offset="0.263084" stop-color="#101118"/>
<stop offset="0.562167" stop-color="#3E4156"/>
<stop offset="0.984375" stop-color="#303044"/>
</linearGradient>
<linearGradient id="paint4_linear_571_90123" x1="118.956" y1="-24.173" x2="206.164" y2="211.881" gradientUnits="userSpaceOnUse">
<stop offset="0.264071" stop-color="#33374B"/>
<stop offset="1" stop-color="#585B7A"/>
</linearGradient>
<linearGradient id="paint5_linear_571_90123" x1="115.07" y1="99.4437" x2="111.855" y2="69.0231" gradientUnits="userSpaceOnUse">
<stop offset="0.0252272" stop-color="#222332"/>
<stop offset="0.242539" stop-color="#424661"/>
<stop offset="0.588639" stop-color="#212230"/>
<stop offset="0.844082" stop-color="#363B58"/>
<stop offset="1" stop-color="#34374B"/>
</linearGradient>
<linearGradient id="paint6_linear_571_90123" x1="121.604" y1="109.753" x2="120.275" y2="67.1411" gradientUnits="userSpaceOnUse">
<stop stop-color="#222433"/>
<stop offset="1" stop-color="#767D9E"/>
</linearGradient>
<linearGradient id="paint7_linear_571_90123" x1="199.971" y1="95.4039" x2="141.478" y2="-6.07794" gradientUnits="userSpaceOnUse">
<stop stop-color="#E70041"/>
<stop offset="1" stop-color="white"/>
</linearGradient>
<linearGradient id="paint8_linear_571_90123" x1="147.137" y1="21.1212" x2="210.784" y2="96.99" gradientUnits="userSpaceOnUse">
<stop stop-color="#BE2764"/>
<stop offset="1" stop-color="#812A53"/>
</linearGradient>
<linearGradient id="paint9_linear_571_90123" x1="206.807" y1="129.438" x2="142.953" y2="21.5313" gradientUnits="userSpaceOnUse">
<stop stop-color="#823359"/>
<stop offset="1" stop-color="#D02E60"/>
</linearGradient>
<linearGradient id="paint10_linear_571_90123" x1="306.52" y1="53.9106" x2="132.142" y2="70.9057" gradientUnits="userSpaceOnUse">
<stop stop-color="#8A2A56"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint11_linear_571_90123" x1="4.40454" y1="0" x2="4.40454" y2="8.80908" gradientUnits="userSpaceOnUse">
<stop stop-color="#5B6074" stop-opacity="0.97"/>
<stop offset="1" stop-color="#373B4D"/>
</linearGradient>
<linearGradient id="paint12_linear_571_90123" x1="4.40454" y1="0" x2="4.40454" y2="8.80908" gradientUnits="userSpaceOnUse">
<stop stop-color="#5B6074" stop-opacity="0.97"/>
<stop offset="1" stop-color="#373B4D"/>
</linearGradient>
<linearGradient id="paint13_linear_571_90123" x1="4.40454" y1="0" x2="4.40454" y2="8.80908" gradientUnits="userSpaceOnUse">
<stop stop-color="#5B6074" stop-opacity="0.97"/>
<stop offset="1" stop-color="#373B4D"/>
</linearGradient>
<radialGradient id="paint14_radial_571_90123" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(63.2684 33.8538) rotate(90) scale(6.65188)">
<stop stop-color="#F02E65"/>
<stop offset="0.947917" stop-color="#282A3B"/>
<stop offset="1" stop-color="#F02E65"/>
</radialGradient>
<radialGradient id="paint15_radial_571_90123" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(225.574 22.3242) rotate(90) scale(15.0776)">
<stop stop-color="#DE2E62"/>
<stop offset="0.598958" stop-color="#282A3B"/>
<stop offset="0.75" stop-color="#282A3B"/>
<stop offset="1" stop-color="#F02E65"/>
</radialGradient>
<radialGradient id="paint16_radial_571_90123" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(171.472 116.338) rotate(90) scale(6.43015)">
<stop stop-color="#F02E65"/>
<stop offset="0.729167" stop-color="#282A3B"/>
<stop offset="1" stop-color="#F02E65"/>
</radialGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

+126
View File
@@ -0,0 +1,126 @@
<svg width="222" height="175" viewBox="0 0 222 175" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M43.4121 116.254C43.4121 140.493 74.4892 145.072 79.5568 119.917" stroke="url(#paint0_radial_537_80284)" stroke-width="12"/>
<path d="M93.2039 44.209L21.9817 91.6489C16.5629 100.178 23.1467 119.049 31.0168 119.528C38.887 120.008 123.394 126.511 123.394 126.511L93.2039 44.209Z" fill="url(#paint1_linear_537_80284)" fill-opacity="0.4"/>
<g filter="url(#filter0_d_537_80284)">
<path d="M94.8205 33.6465L25.8891 88.9015C20.7605 98.6703 28.5145 119.368 35.9632 119.918C43.412 120.467 123.394 127.916 123.394 127.916L94.8205 33.6465Z" fill="url(#paint2_linear_537_80284)"/>
</g>
<path d="M128.595 74.954C132.53 88.0347 134.092 100.432 133.467 109.883C133.154 114.613 132.297 118.55 130.956 121.454C129.615 124.36 127.847 126.123 125.755 126.752C123.664 127.381 121.217 126.886 118.495 125.202C115.775 123.519 112.888 120.709 110.018 116.936C104.283 109.398 98.7468 98.1959 94.8124 85.1152C90.878 72.0345 89.3155 59.6372 89.9408 50.1857C90.2537 45.456 91.111 41.5194 92.4513 38.6151C93.7924 35.7094 95.5605 33.9466 97.6521 33.3175C99.7437 32.6884 102.191 33.1832 104.912 34.8671C107.633 36.55 110.519 39.3605 113.389 43.1328C119.125 50.6711 124.661 61.8733 128.595 74.954Z" fill="url(#paint3_linear_537_80284)" stroke="url(#paint4_linear_537_80284)" stroke-width="2"/>
<path d="M100.593 98.8532C100.593 98.8532 107.351 95.3299 108.591 91.7119C109.831 88.0939 108.286 81.9135 106.565 76.1934C104.843 70.4732 91.7854 69.9484 91.7854 69.9484C94.7244 83.3674 96.8517 89.2767 100.593 98.8532Z" fill="url(#paint5_linear_537_80284)" fill-opacity="0.3"/>
<ellipse cx="106.194" cy="82.5991" rx="2.00454" ry="10.2947" transform="rotate(-14.7165 106.194 82.5991)" fill="url(#paint6_linear_537_80284)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M158.267 33.0303C145.653 27.4164 130.876 33.0914 125.262 45.7057L124.929 46.4536C119.316 59.0679 124.991 73.8448 137.605 79.4587L142.662 81.7093C142.179 82.3785 141.895 83.211 141.916 84.1363L141.978 86.7736C142.057 90.1179 145.961 91.8943 148.534 89.7561L150.563 88.0699C151.299 87.4579 151.745 86.6643 151.921 85.8298L156.525 87.8787C169.139 93.4926 183.916 87.8176 189.53 75.2033L189.862 74.4554C195.476 61.8411 189.801 47.0642 177.187 41.4503L158.267 33.0303Z" fill="url(#paint7_linear_537_80284)"/>
<path d="M151.516 87.4798L146.655 91.5071C145.16 92.7454 143.442 93.639 141.506 93.776C140.556 93.8432 140.264 93.1232 140 92.9993C141.827 92.8779 143.296 92.4752 143.68 91.9631L149.8 86.7594L151.516 87.4798Z" fill="#EB2B62"/>
<path d="M144.141 26.648C138.649 24.3428 132.941 27.6001 130.975 29.3993C135.627 26.5875 140.943 27.6946 143.019 28.5997L188.118 48.1322C194.529 51.7113 193.777 59.0198 192.599 62.2266L180.603 88.8868C177.478 94.6007 172.913 95.5851 171.021 95.3631C177.256 96.2841 181.705 91.8728 183.15 89.552L195.506 62.0336C198.455 53.6616 194.162 49.1214 191.648 47.8979C177.967 41.8535 149.634 28.9532 144.141 26.648Z" fill="url(#paint8_linear_537_80284)"/>
<mask id="path-10-inside-1_537_80284" fill="white">
<path fill-rule="evenodd" clip-rule="evenodd" d="M141.683 27.5397C136.638 25.2942 130.727 27.5642 128.481 32.6099L115.951 60.7661C113.705 65.8118 115.975 71.7225 121.021 73.9681L138.971 81.9568L139.195 91.517C139.234 93.1892 141.187 94.0774 142.473 93.0083L149.912 86.8257L167.349 94.5859C172.394 96.8315 178.305 94.5615 180.551 89.5158L193.081 61.3596C195.327 56.3139 193.057 50.4031 188.011 48.1576L141.683 27.5397Z"/>
</mask>
<path fill-rule="evenodd" clip-rule="evenodd" d="M141.683 27.5397C136.638 25.2942 130.727 27.5642 128.481 32.6099L115.951 60.7661C113.705 65.8118 115.975 71.7225 121.021 73.9681L138.971 81.9568L139.195 91.517C139.234 93.1892 141.187 94.0774 142.473 93.0083L149.912 86.8257L167.349 94.5859C172.394 96.8315 178.305 94.5615 180.551 89.5158L193.081 61.3596C195.327 56.3139 193.057 50.4031 188.011 48.1576L141.683 27.5397Z" fill="url(#paint9_linear_537_80284)"/>
<path d="M128.481 32.6099L127.568 32.2033L128.481 32.6099ZM141.683 27.5397L142.09 26.6261L141.683 27.5397ZM115.951 60.7661L115.037 60.3595L115.951 60.7661ZM121.021 73.9681L121.427 73.0545L121.021 73.9681ZM138.971 81.9568L139.971 81.9333L139.956 81.3005L139.378 81.0431L138.971 81.9568ZM139.195 91.517L138.195 91.5405L139.195 91.517ZM142.473 93.0083L143.112 93.7773L142.473 93.0083ZM149.912 86.8257L150.318 85.9121L149.75 85.6594L149.272 86.0566L149.912 86.8257ZM167.349 94.5859L166.942 95.4995L167.349 94.5859ZM180.551 89.5158L179.637 89.1092L180.551 89.5158ZM193.081 61.3596L192.168 60.953L192.168 60.953L193.081 61.3596ZM188.011 48.1576L188.418 47.2439L188.418 47.2439L188.011 48.1576ZM129.395 33.0165C131.416 28.4753 136.735 26.4323 141.277 28.4533L142.09 26.6261C136.54 24.156 130.038 26.653 127.568 32.2033L129.395 33.0165ZM116.864 61.1727L129.395 33.0165L127.568 32.2033L115.037 60.3595L116.864 61.1727ZM121.427 73.0545C116.886 71.0335 114.843 65.7138 116.864 61.1727L115.037 60.3595C112.567 65.9098 115.064 72.4116 120.614 74.8817L121.427 73.0545ZM139.378 81.0431L121.427 73.0545L120.614 74.8817L138.565 82.8704L139.378 81.0431ZM140.195 91.4936L139.971 81.9333L137.971 81.9802L138.195 91.5405L140.195 91.4936ZM141.834 92.2392C141.191 92.7738 140.214 92.3297 140.195 91.4936L138.195 91.5405C138.254 94.0487 141.183 95.381 143.112 93.7773L141.834 92.2392ZM149.272 86.0566L141.834 92.2392L143.112 93.7773L150.551 87.5947L149.272 86.0566ZM167.755 93.6723L150.318 85.9121L149.505 87.7393L166.942 95.4995L167.755 93.6723ZM179.637 89.1092C177.616 93.6503 172.296 95.6933 167.755 93.6723L166.942 95.4995C172.492 97.9696 178.994 95.4727 181.464 89.9224L179.637 89.1092ZM192.168 60.953L179.637 89.1092L181.464 89.9224L193.995 61.7662L192.168 60.953ZM187.605 49.0712C192.146 51.0922 194.189 56.4118 192.168 60.953L193.995 61.7662C196.465 56.2159 193.968 49.7141 188.418 47.2439L187.605 49.0712ZM141.277 28.4533L187.605 49.0712L188.418 47.2439L142.09 26.6261L141.277 28.4533Z" fill="url(#paint10_linear_537_80284)" mask="url(#path-10-inside-1_537_80284)"/>
<ellipse cx="4.40454" cy="4.40454" rx="4.40454" ry="4.40454" transform="matrix(0.894697 0.397317 -0.36312 0.950578 135.661 47.835)" fill="#F3779A"/>
<ellipse cx="4.40454" cy="4.40454" rx="4.40454" ry="4.40454" transform="matrix(0.894697 0.397317 -0.36312 0.950578 134.198 47.8135)" fill="#F2F2F8"/>
<ellipse cx="4.40454" cy="4.40454" rx="4.40454" ry="4.40454" transform="matrix(0.894697 0.397317 -0.36312 0.950578 152.811 55.4512)" fill="#F3779A"/>
<ellipse cx="4.40454" cy="4.40454" rx="4.40454" ry="4.40454" transform="matrix(0.894697 0.397317 -0.36312 0.950578 151.348 55.4297)" fill="#F2F2F8"/>
<ellipse cx="4.40454" cy="4.40454" rx="4.40454" ry="4.40454" transform="matrix(0.894697 0.397317 -0.36312 0.950578 169.96 63.0664)" fill="#F3779A"/>
<ellipse cx="4.40454" cy="4.40454" rx="4.40454" ry="4.40454" transform="matrix(0.894697 0.397317 -0.36312 0.950578 168.497 63.0449)" fill="#F2F2F8"/>
<g filter="url(#filter1_f_537_80284)">
<path d="M49.2684 28.0889L51.3066 31.8156L55.0334 33.8538L51.3066 35.8921L49.2684 39.6188L47.2302 35.8921L43.5034 33.8538L47.2302 31.8156L49.2684 28.0889Z" fill="url(#paint11_radial_537_80284)" fill-opacity="0.6"/>
</g>
<g filter="url(#filter2_f_537_80284)">
<path d="M211.574 13.8984L214.553 19.3452L220 22.3242L214.553 25.3031L211.574 30.7499L208.595 25.3031L203.148 22.3242L208.595 19.3452L211.574 13.8984Z" fill="url(#paint12_radial_537_80284)" fill-opacity="0.6"/>
</g>
<g filter="url(#filter3_f_537_80284)">
<path d="M157.472 111.903L159.04 114.77L161.907 116.338L159.04 117.906L157.472 120.772L155.904 117.906L153.038 116.338L155.904 114.77L157.472 111.903Z" fill="url(#paint13_radial_537_80284)" fill-opacity="0.6"/>
</g>
<defs>
<filter id="filter0_d_537_80284" x="-13.7664" y="0.646484" width="179.161" height="174.27" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="2" dy="7"/>
<feGaussianBlur stdDeviation="20"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.768627 0 0 0 0 0.768627 0 0 0 0 0.768627 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_537_80284"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_537_80284" result="shape"/>
</filter>
<filter id="filter1_f_537_80284" x="41.5034" y="26.0889" width="15.53" height="15.5303" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="1" result="effect1_foregroundBlur_537_80284"/>
</filter>
<filter id="filter2_f_537_80284" x="201.148" y="11.8984" width="20.8516" height="20.8516" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="1" result="effect1_foregroundBlur_537_80284"/>
</filter>
<filter id="filter3_f_537_80284" x="151.038" y="109.903" width="12.8691" height="12.8691" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="1" result="effect1_foregroundBlur_537_80284"/>
</filter>
<radialGradient id="paint0_radial_537_80284" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(64.2319 119.062) rotate(53.6887) scale(22.2166 32.3419)">
<stop stop-color="#A3A8BD"/>
<stop offset="0.317708" stop-color="#F4F4F8"/>
<stop offset="0.484375" stop-color="white"/>
<stop offset="0.905609" stop-color="#A3A8BD"/>
</radialGradient>
<linearGradient id="paint1_linear_537_80284" x1="27.4436" y1="121.838" x2="38.7291" y2="75.4951" gradientUnits="userSpaceOnUse">
<stop stop-color="#A3A8BD"/>
<stop offset="0.633096" stop-color="white"/>
</linearGradient>
<linearGradient id="paint2_linear_537_80284" x1="57.3936" y1="52.3904" x2="84.8316" y2="131.923" gradientUnits="userSpaceOnUse">
<stop offset="0.274562" stop-color="white"/>
<stop offset="1" stop-color="#D0D0E3"/>
</linearGradient>
<linearGradient id="paint3_linear_537_80284" x1="107.215" y1="-12.9999" x2="123.25" y2="140.807" gradientUnits="userSpaceOnUse">
<stop offset="0.263084" stop-color="#A3A8BD"/>
<stop offset="0.562167" stop-color="#E8E8F1"/>
<stop offset="0.984375" stop-color="white"/>
</linearGradient>
<linearGradient id="paint4_linear_537_80284" x1="104.956" y1="-24.173" x2="192.164" y2="211.881" gradientUnits="userSpaceOnUse">
<stop offset="0.264071" stop-color="#FCFCFF"/>
<stop offset="1" stop-color="#A3A8BD"/>
</linearGradient>
<linearGradient id="paint5_linear_537_80284" x1="101.07" y1="99.4437" x2="97.8544" y2="69.0231" gradientUnits="userSpaceOnUse">
<stop offset="0.0252272" stop-color="#B5B8C7"/>
<stop offset="0.242539" stop-color="white"/>
<stop offset="0.588639" stop-color="#BFC2CF"/>
<stop offset="0.844082" stop-color="white"/>
<stop offset="1" stop-color="#CACCD8"/>
</linearGradient>
<linearGradient id="paint6_linear_537_80284" x1="107.604" y1="109.753" x2="106.275" y2="67.1411" gradientUnits="userSpaceOnUse">
<stop stop-color="#A3A8BD"/>
<stop offset="1" stop-color="white"/>
</linearGradient>
<linearGradient id="paint7_linear_537_80284" x1="185.971" y1="95.4039" x2="127.478" y2="-6.07794" gradientUnits="userSpaceOnUse">
<stop stop-color="#E70041"/>
<stop offset="1" stop-color="white"/>
</linearGradient>
<linearGradient id="paint8_linear_537_80284" x1="133.137" y1="21.1212" x2="196.784" y2="96.99" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="#E90043"/>
</linearGradient>
<linearGradient id="paint9_linear_537_80284" x1="192.807" y1="129.438" x2="128.953" y2="21.5313" gradientUnits="userSpaceOnUse">
<stop stop-color="#F02E65"/>
<stop offset="1" stop-color="white"/>
</linearGradient>
<linearGradient id="paint10_linear_537_80284" x1="292.52" y1="53.9106" x2="118.141" y2="70.9057" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
</linearGradient>
<radialGradient id="paint11_radial_537_80284" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(49.2684 33.8538) rotate(90) scale(6.65188)">
<stop stop-color="#F02E65"/>
<stop offset="0.947917" stop-color="white"/>
<stop offset="1" stop-color="#F02E65"/>
</radialGradient>
<radialGradient id="paint12_radial_537_80284" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(211.574 22.3242) rotate(90) scale(15.0776)">
<stop stop-color="#F02E65"/>
<stop offset="0.598958" stop-color="white"/>
<stop offset="0.75" stop-color="white"/>
<stop offset="1" stop-color="#F02E65"/>
</radialGradient>
<radialGradient id="paint13_radial_537_80284" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(157.472 116.338) rotate(90) scale(6.43015)">
<stop stop-color="#F02E65"/>
<stop offset="0.729167" stop-color="white"/>
<stop offset="1" stop-color="#F02E65"/>
</radialGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

+5 -15
View File
@@ -1,26 +1,20 @@
<script lang="ts">
import { base } from '$app/paths';
import {
AvatarInitials,
DropList,
DropListItem,
DropListLink,
FeedbackGeneral
} from '$lib/components';
import { app, feedback } from '$lib/stores/app';
import { AvatarInitials, DropList, DropListItem, DropListLink } from '$lib/components';
import { app } from '$lib/stores/app';
import { user } from '$lib/stores/user';
import { organizationList, organization, newOrgModal } from '$lib/stores/organization';
import AppwriteLogo from '$lib/images/appwrite-gray-light.svg';
import LightMode from '$lib/images/mode/light-mode.svg';
import DarkMode from '$lib/images/mode/dark-mode.svg';
import SystemMode from '$lib/images/mode/system-mode.svg';
import { FeedbackNPS } from '$lib/components';
import { slide } from 'svelte/transition';
import { page } from '$app/stores';
import { Submit, trackEvent } from '$lib/actions/analytics';
import { sdk } from '$lib/stores/sdk';
import { goto } from '$app/navigation';
import { feedback } from '$lib/stores/feedback';
import { Feedback } from '$lib/components/feedback';
let showDropdown = false;
let droplistElement: HTMLDivElement;
@@ -77,11 +71,7 @@
<span class="text">Feedback</span>
</button>
<svelte:fragment slot="other">
{#if $feedback.type === 'nps'}
<FeedbackNPS />
{:else}
<FeedbackGeneral />
{/if}
<Feedback />
</svelte:fragment>
</DropList>
<a
+40 -1
View File
@@ -1,10 +1,15 @@
<script lang="ts">
import { beforeNavigate } from '$app/navigation';
import { base } from '$app/paths';
import { page } from '$app/stores';
import { trackEvent } from '$lib/actions/analytics';
import { tooltip } from '$lib/actions/tooltip';
import { isMac } from '$lib/helpers/platform';
import { slide } from '$lib/helpers/transition';
import { wizard } from '$lib/stores/wizard';
import Create from '$routes/console/feedbackWizard.svelte';
export let isOpen = false;
$: project = $page.params.project;
$: projectPath = `${base}/console/project-${project}`;
@@ -27,6 +32,15 @@
narrow = !narrow;
}
}
function openWizard() {
isOpen = false;
wizard.start(Create);
}
beforeNavigate(() => {
wizard.hide();
});
</script>
<svelte:window on:keydown={handleKeyDown} />
@@ -122,6 +136,24 @@
<span class="text">Storage</span>
</a>
</li>
<li class="drop-list-item is-only-mobile">
<a
class="drop-button"
href={`${projectPath}/settings`}
on:click={() => trackEvent('click_menu_settings')}
class:is-selected={$page.url.pathname.startsWith(
`${projectPath}/settings`
)}
title="Settings"
use:tooltip={{
content: 'Settings',
placement: 'right',
disabled: !narrow
}}>
<span class="icon-cog" aria-hidden="true" />
<span class="text">Settings</span>
</a>
</li>
</ul>
</section>
</div>
@@ -129,7 +161,7 @@
<div class="side-nav-bottom">
<section class="drop-section">
<a
class="drop-button"
class="drop-button is-only-desktop"
href={`${projectPath}/settings`}
on:click={() => trackEvent('click_menu_settings')}
class:is-selected={$page.url.pathname.startsWith(`${projectPath}/settings`)}
@@ -142,6 +174,13 @@
<span class="icon-cog" aria-hidden="true" />
<span class="text">Settings</span>
</a>
<ul class="drop-list is-only-mobile">
<li class="drop-list-item">
<button class="drop-button" on:click={openWizard}>
<span class="text">Feedback</span>
</button>
</li>
</ul>
</section>
</div>
{/if}
-79
View File
@@ -1,5 +1,4 @@
import { browser } from '$app/environment';
import { VARS } from '$lib/system';
import { writable } from 'svelte/store';
export type AppStore = {
@@ -7,89 +6,11 @@ export type AppStore = {
themeInUse: 'light' | 'dark';
};
export type Feedback = {
elapsed: number;
visualized: number;
notification: boolean;
type: 'nps' | 'general';
show: boolean;
};
export const app = writable<AppStore>({
theme: 'auto',
themeInUse: 'light'
});
function createFeedbackStore() {
const { subscribe, update } = writable<Feedback>({
elapsed: browser ? parseInt(localStorage.getItem('feedbackElapsed')) : 0,
visualized: browser ? parseInt(localStorage.getItem('feedbackVisualized')) : 0,
notification: false,
type: 'general',
show: false
});
return {
subscribe,
update,
toggleFeedback: () => {
update((feedback) => {
feedback.show = !feedback.show;
return feedback;
});
},
toggleNotification: () =>
update((feedback) => {
feedback.notification = !feedback.notification;
return feedback;
}),
switchType: (feedType: Feedback['type']) =>
update((feedback) => {
feedback.type = feedType;
return feedback;
}),
addVisualization: () =>
update((feedback) => {
feedback.visualized += 1;
localStorage.setItem('feedbackVisualized', feedback.visualized.toString());
return feedback;
}),
increaseElapsed: (time: number) => {
update((feedback) => {
feedback.elapsed += time;
localStorage.setItem('feedbackElapsed', feedback.elapsed.toString());
return feedback;
});
},
submitFeedback: async (
subject: string,
message: string,
firstname?: string,
email?: string,
value?: number
) => {
if (!VARS.GROWTH_ENDPOINT) return;
const response = await fetch(`${VARS.GROWTH_ENDPOINT}/feedback`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
subject,
message,
email,
firstname: firstname ? firstname : undefined,
customFields: value ? [{ id: '40655', value }] : undefined
})
});
if (response.status >= 400) {
throw new Error('Failed to submit feedback');
}
}
};
}
export const feedback = createFeedbackStore();
if (browser) {
app.update((n) => ({
...n,
+139
View File
@@ -0,0 +1,139 @@
import { browser } from '$app/environment';
import { VARS } from '$lib/system';
import { writable } from 'svelte/store';
import type { SvelteComponent } from 'svelte';
import FeedbackGeneral from '$lib/components/feedback/feedbackGeneral.svelte';
import FeedbackNps from '$lib/components/feedback/feedbackNPS.svelte';
export type Feedback = {
elapsed: number;
visualized: number;
notification: boolean;
type: 'nps' | 'general';
show: boolean;
};
export type FeedbackData = {
message: string;
name?: string;
email?: string;
value?: number;
};
export type FeedbackOption = {
type: Feedback['type'];
title: string;
desc: string;
component: typeof SvelteComponent;
};
export const feedbackOptions: FeedbackOption[] = [
{
type: 'general',
title: 'How can we improve?',
desc: 'Your feedback is important to us. Please be honest and tell us what you think.',
component: FeedbackGeneral
},
{
type: 'nps',
title: 'How are we doing?',
desc: "At Appwrite, we value the feedback of our users. That means you! We'd love to hear what you think.",
component: FeedbackNps
}
];
export const selectedFeedback = writable<FeedbackOption>();
function createFeedbackDataStore() {
const { subscribe, update } = writable<FeedbackData>({
message: '',
name: '',
email: '',
value: 0
});
return {
subscribe,
update,
reset: () => {
update((feedbackData) => {
feedbackData.message = '';
feedbackData.name = '';
feedbackData.email = '';
feedbackData.value = 0;
return feedbackData;
});
}
};
}
export const feedbackData = createFeedbackDataStore();
function createFeedbackStore() {
const { subscribe, update } = writable<Feedback>({
elapsed: browser ? parseInt(localStorage.getItem('feedbackElapsed')) : 0,
visualized: browser ? parseInt(localStorage.getItem('feedbackVisualized')) : 0,
notification: false,
type: 'general',
show: false
});
return {
subscribe,
update,
toggleFeedback: () => {
update((feedback) => {
feedback.show = !feedback.show;
return feedback;
});
},
toggleNotification: () =>
update((feedback) => {
feedback.notification = !feedback.notification;
return feedback;
}),
switchType: (feedType: Feedback['type']) =>
update((feedback) => {
feedback.type = feedType;
return feedback;
}),
addVisualization: () =>
update((feedback) => {
feedback.visualized += 1;
localStorage.setItem('feedbackVisualized', feedback.visualized.toString());
return feedback;
}),
increaseElapsed: (time: number) => {
update((feedback) => {
feedback.elapsed += time;
localStorage.setItem('feedbackElapsed', feedback.elapsed.toString());
return feedback;
});
},
submitFeedback: async (
subject: string,
message: string,
firstname?: string,
email?: string,
value?: number
) => {
if (!VARS.GROWTH_ENDPOINT) return;
const response = await fetch(`${VARS.GROWTH_ENDPOINT}/feedback`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
subject,
message,
email,
firstname: firstname ? firstname : undefined,
customFields: value ? [{ id: '40655', value }] : undefined
})
});
if (response.status >= 400) {
throw new Error('Failed to submit feedback');
}
}
};
}
export const feedback = createFeedbackStore();
+5 -2
View File
@@ -7,7 +7,7 @@
import Header from '$lib/layout/header.svelte';
import SideNavigation from '$lib/layout/navigation.svelte';
import Shell from '$lib/layout/shell.svelte';
import { feedback } from '$lib/stores/app';
import { feedback } from '$lib/stores/feedback';
import { log } from '$lib/stores/logs';
import { newOrgModal } from '$lib/stores/organization';
import { wizard } from '$lib/stores/wizard';
@@ -15,6 +15,8 @@
import { loading } from '../store';
import Create from './createOrganization.svelte';
let isOpen = false;
onMount(() => {
loading.set(false);
@@ -47,12 +49,13 @@
</script>
<Shell
bind:isOpen
showSideNavigation={$page.url.pathname !== '/console' &&
!$page?.params.organization &&
!$page.url.pathname.includes('/console/account') &&
!$page.url.pathname.includes('/console/onboarding')}>
<Header slot="header" />
<SideNavigation slot="side" />
<SideNavigation slot="side" bind:isOpen />
<slot />
<Footer slot="footer" />
</Shell>
+25
View File
@@ -0,0 +1,25 @@
<script lang="ts">
import { Wizard } from '$lib/layout';
import { onDestroy } from 'svelte';
import type { WizardStepsType } from '$lib/layout/wizard.svelte';
import { feedbackData } from '$lib/stores/feedback';
import Step1 from './wizardFeedback/step1.svelte';
import Step2 from './wizardFeedback/step2.svelte';
onDestroy(() => {
feedbackData.reset();
});
const stepsComponents: WizardStepsType = new Map();
stepsComponents.set(1, {
label: 'Feedback',
component: Step1
});
stepsComponents.set(2, {
label: 'Thank you',
component: Step2,
optional: true
});
</script>
<Wizard title="Feedback" steps={stepsComponents} finalAction="Close" />
@@ -10,7 +10,7 @@
import type { Attributes } from './store';
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
import { preferences } from '$lib/stores/preferences';
import { feedback } from '$lib/stores/app';
import { feedback } from '$lib/stores/feedback';
export let showCreate = false;
export let selectedOption: string = null;
@@ -0,0 +1,39 @@
<script lang="ts">
import { WizardStep } from '$lib/layout';
import {
selectedFeedback,
feedbackData,
feedbackOptions,
feedback
} from '$lib/stores/feedback';
import { addNotification } from '$lib/stores/notifications';
$: $selectedFeedback = feedbackOptions.find((option) => option.type === $feedback.type);
async function beforeSubmit() {
try {
await feedback.submitFeedback(
`feedback-${$feedback.type}`,
$feedbackData.message,
$feedbackData.name,
$feedbackData.email
);
addNotification({
type: 'success',
message: 'Feedback submitted successfully'
});
} catch (error) {
addNotification({
type: 'error',
message: error.message
});
}
}
</script>
<WizardStep {beforeSubmit}>
<svelte:fragment slot="title">{$selectedFeedback.title}</svelte:fragment>
<svelte:fragment slot="subtitle">{$selectedFeedback.desc}</svelte:fragment>
<svelte:component this={$selectedFeedback.component} />
</WizardStep>
@@ -0,0 +1,18 @@
<script lang="ts">
import { WizardStep } from '$lib/layout';
import { app } from '$lib/stores/app';
import imgDark from '$lib/images/feedback/feedback-dark.svg';
import imgLight from '$lib/images/feedback/feedback-light.svg';
</script>
<WizardStep>
<svelte:fragment slot="title">Thanks for the feedback!</svelte:fragment>
<div class="u-flex u-main-center">
{#if $app.themeInUse === 'dark'}
<img src={imgDark} alt="" class="u-only-dark" />
{:else}
<img src={imgLight} alt="" class="u-only-light" />
{/if}
</div>
</WizardStep>