Skip to content
Extraits de code Groupes Projets
typingbox.svelte 3,4 ko
Newer Older
  • Learn to ignore specific revisions
  • <script lang="ts">
    	import { onMount } from 'svelte';
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    	import { t } from '$lib/services/i18n';
    
    	import config from '$lib/config';
    
    	export let initialDuration: number;
    	export let exerciceId: number;
    	export let explications: string;
    	export let text: string;
    	export let data: {
    		exerciceId: number;
    		position: number;
    		downtime: number;
    		uptime: number;
    		keyCode: number;
    		keyValue: string;
    	}[];
    	export let inProgress = false;
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    	export let onFinish: Function;
    	let duration = initialDuration >= 0 ? initialDuration : 0;
    
    	let lastInput = '';
    	let input = '';
    	let textArea: HTMLTextAreaElement;
    	let startTime = new Date().getTime();
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    	let isDone = false;
    
    
    	onMount(async () => {
    		textArea.focus();
    	});
    
    	function start() {
    		inProgress = true;
    		startTime = new Date().getTime();
    		const interval = setInterval(() => {
    			duration += initialDuration >= 0 ? -1 : 1;
    			if ((duration <= 0 && initialDuration > 0) || !inProgress) {
    				clearInterval(interval);
    				inProgress = false;
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    				isDone = true;
    				onFinish();
    
    			}
    		}, 1000);
    	}
    </script>
    
    <div class=" w-full max-w-5xl m-auto mt-8">
    	<div>{explications}</div>
    	<div class="flex justify-between my-2 p-2">
    		<button
    			class="button"
    			on:click={() => {
    				input = '';
    				duration = initialDuration >= 0 ? initialDuration : 0;
    				start();
    			}}
    			disabled={inProgress}
    		>
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    			{$t('button.start')}
    
    		</button>
    		<div class="text-2xl font-bold">
    			{duration}s
    		</div>
    	</div>
    	<ul class="h-10 flex justify-around border-t-2 rounded-t-lg border-x-2 divide-x-2 text-center">
    		{#each config.SPECIAL_CHARS as char (char)}
    			<button
    				class="flex-grow"
    				on:click={() => {
    					input += char;
    				}}
    				on:mousedown={(e) => e.preventDefault()}
    			>
    				{char}
    			</button>
    		{/each}
    	</ul>
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    	<div
    		class="relative border-2 rounded-b-lg text-xl select-none"
    		class:border-green-500={isDone}
    		class:bg-green-100={isDone}
    	>
    
    		<div class="font-mono p-4 break-words">
    			<span class="text-inherit p-0 m-0 whitespace-pre-wrap break-words"
    				><!--
    			-->{#each text.slice(0, input.length) as char, i}
    					<span
    						class="text-gray-800 p-0 m-0"
    						class:text-red-500={char !== input[i]}
    						class:bg-red-100={char !== input[i]}>{input[i]}</span
    					><!--
    					-->{/each}<!--
    					--></span
    			><span
    				class="text-gray-400 p-0 m-0 underline decoration-2 underline-offset-6 decoration-black whitespace-pre-wrap"
    				>{text[input.length] ?? ''}</span
    			><span class="text-gray-400 p-0 m-0 whitespace-pre-wrap"
    				>{text.slice(input.length + 1) ?? ''}</span
    			>
    		</div>
    		<textarea
    			bind:value={input}
    			bind:this={textArea}
    			spellcheck="false"
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    			disabled={isDone}
    
    			on:keyup={(e) => {
    				if (inProgress) {
    					data[data.length - 1].uptime = new Date().getTime() - startTime;
    				}
    			}}
    			on:keydown={(e) => {
    				if (
    					!inProgress &&
    					((duration > 0 && initialDuration > 0) || (duration >= 0 && initialDuration < 0))
    				) {
    					start();
    				}
    				if (inProgress) {
    					lastInput = input;
    
    					data.push({
    						exerciceId,
    						position: input.length,
    						downtime: new Date().getTime() - startTime,
    						uptime: 0,
    						keyCode: e.keyCode,
    						keyValue: e.key
    					});
    
    					if (input === text || input.split('\n').length >= text.split('\n').length + 1) {
    						inProgress = false;
    					}
    				} else {
    					input = lastInput;
    				}
    			}}
    			class="absolute top-0 resize-none font-mono p-4 w-full h-full bg-transparent select-none text-transparent"
    		/>
    	</div>
    </div>