Skip to content

Commit

Permalink
Merge pull request #88 from xerosanyam/alpha
Browse files Browse the repository at this point in the history
Alpha
  • Loading branch information
xerosanyam authored Aug 20, 2024
2 parents 5112d7b + 93779a3 commit 0340f4d
Show file tree
Hide file tree
Showing 23 changed files with 437 additions and 66 deletions.
Binary file modified bun.lockb
Binary file not shown.
5 changes: 5 additions & 0 deletions essays/turso.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Turso commands

```
turso db shell <libsql://db-url.io>
```
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"@zerodevx/svelte-toast": "^0.9.5",
"arctic": "1.9.2",
"autoprefixer": "10.4.19",
"cal-heatmap": "^4.2.4",
"cypress": "^13.13.1",
"date-fns": "3.6.0",
"dotenv": "16.4.5",
Expand Down
50 changes: 50 additions & 0 deletions scripts/fill-activity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { drizzle } from 'drizzle-orm/libsql';
import { createClient } from '@libsql/client';

// picks value from .env
export const turso_client = createClient({
url: process.env.TURSO_CONNECTION_URL!,
authToken: process.env.TURSO_AUTH_TOKEN!,
});

export const db = drizzle(turso_client,
// { logger: true }
);

import { activityTable, cardTable } from "$lib/db/turso.schema";

async function insertActivityFromCards() {
// Fetch all rows from the card table
const cards = await db.select().from(cardTable).all();

// Loop through each card and insert rows into the activity table
for (const card of cards) {
const activityInsertData = {
userId: card.userId,
cardId: card.id,
};

// Insert activity for creation
await db.insert(activityTable).values({
id: crypto.randomUUID(),
action: 'INSERT',
createdAt: card.createdAt,
...activityInsertData,
});

// If createdAt and updatedAt are different, insert activity for update
if (card.createdAt !== card.updatedAt) {
await db.insert(activityTable).values({
id: crypto.randomUUID(),
action: 'UPDATE',
createdAt: card.updatedAt,
...activityInsertData,
});
}
}
}

// Run the script
insertActivityFromCards()
.then(() => console.log('Activity records inserted successfully.'))
.catch((error) => console.error('Error inserting activity records:', error));
46 changes: 46 additions & 0 deletions src/lib/algo.util.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { calculateMaxStreak, calculateStreak, type info } from "$lib/algo.utils";
import { describe, expect, test } from "vitest";

describe('streak algo', () => {
test('should calculate current streak', () => {
const inputArray = [
{ date: '2021-01-01T00:00:00.000Z' },
{ date: '2021-01-02T00:00:00.000Z' },
{ date: '2021-01-03T00:00:00.000Z' },
{ date: '2021-01-04T00:00:00.000Z' },
//break
{ date: '2021-01-06T00:00:00.000Z' },
{ date: '2021-01-07T00:00:00.000Z' },
];
const streak = calculateStreak(inputArray, new Date('2021-01-07'));
expect(streak).toBe(2);
})

test.skip('should calculate max streak', () => {
const inputArray = [
{ date: '2021-01-01T00:00:00.000Z' },
{ date: '2021-01-02T00:00:00.000Z' },
{ date: '2021-01-03T00:00:00.000Z' },
{ date: '2021-01-04T00:00:00.000Z' },
//break
{ date: '2021-01-06T00:00:00.000Z' },
{ date: '2021-01-07T00:00:00.000Z' },
];
const streak = calculateMaxStreak(inputArray)
expect(streak).toHaveProperty('maxStreak', 4)
expect(streak).toHaveProperty('startDate', '2020-12-31')
expect(streak).toHaveProperty('endDate', '2021-01-03');
})
test('should calculate max streak', () => {
const inputArray: info = [];
const streak = calculateMaxStreak(inputArray)
expect(streak).toHaveProperty('maxStreak', 0);
})
test('should calculate max streak', () => {
const inputArray = [
{ date: '2021-01-01' }
];
const streak = calculateMaxStreak(inputArray)
expect(streak).toHaveProperty('maxStreak', 1);
})
})
57 changes: 57 additions & 0 deletions src/lib/algo.utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
export type info = {
date: string;
}[]

export const calculateStreak = (inputArray: info, currentDate: Date) => {
const dateSet = new Set(
inputArray.map((item) => new Date(item.date).toLocaleDateString('en-CA'))
);

let streak = 0;

while (dateSet.has(currentDate.toLocaleDateString('en-CA'))) {
streak++;
currentDate.setDate(currentDate.getDate() - 1);
}

return streak;
}

function isOneDayDifference(date1: string, date2: string) {
const d1 = new Date(date1);
const d2 = new Date(date2);

d1.setHours(0, 0, 0, 0);
d2.setHours(0, 0, 0, 0);

const diffInDays = (d2.getTime() - d1.getTime()) / (1000 * 60 * 60 * 24);

return Math.abs(diffInDays) === 1;
}



export const calculateMaxStreak = (inputArray: info) => {
const dateSet = new Set(
inputArray.map((item) => new Date(item.date).toLocaleDateString('en-CA'))
);
let maxStreak = dateSet.size >= 1 ? 1 : 0;
let startDate = '';
let endDate = '';

let sortedDates = [...dateSet].toSorted((item1, item2) => (new Date(item1).getTime() - new Date(item2).getTime()))
let left = 0;
for (let right = 1; right < sortedDates.length; right++) {
if (isOneDayDifference(sortedDates[right], sortedDates[right - 1])) {
if (maxStreak < (right - left + 1)) {
maxStreak = right - left + 1;
startDate = sortedDates[left];
endDate = sortedDates[right];
}

} else {
left = right
}
}
return { maxStreak, startDate, endDate };
}
7 changes: 4 additions & 3 deletions src/lib/components/Cards/Card.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import Trash from '~icons/arcticons/trashcan';
import ReviewOptions from './ReviewOptions.svelte';
import { enhance } from '$app/forms';
import ContentRenderer from '$lib/components/ContentRenderer.svelte';
export let card: CardRevisePage;
export let customEnhance;
Expand All @@ -13,15 +14,15 @@
<div class="group relative rounded-md border border-gray-100 bg-white sm:h-96">
<div class={`flex h-full w-full flex-col ${modifyingCardId === card.id ? 'blur-sm' : ''}`}>
<div
class="flex h-fit max-h-48 w-full justify-center overflow-y-auto rounded-md border-input ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
class="flex h-fit max-h-48 min-h-16 w-full justify-center overflow-y-auto rounded-md border-input ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
id="question"
>
<div class="w-full whitespace-break-spaces p-6">
{card.front}
<ContentRenderer text={card.front} />
</div>
</div>

<div class="relative flex grow min-h-48 border-t border-dashed">
<div class="relative flex min-h-48 grow border-t border-dashed">
<form
class="absolute -top-5 right-0 z-10 bg-white"
method="post"
Expand Down
4 changes: 2 additions & 2 deletions src/lib/components/Cards/CardReview.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
$: {
remainingCards = cards.filter((card) => !revisedCards.includes(card.id));
groupedCards = groupCards(remainingCards);
dates = Object.keys(groupedCards).sort((a, b) => new Date(a).getTime() - new Date(b).getTime());
dates = Object.keys(groupedCards).sort((b, a) => new Date(a).getTime() - new Date(b).getTime());
firstCardId = groupCards(remainingCards)[dates[0]]?.[0]?.id;
}
Expand Down Expand Up @@ -52,7 +52,7 @@
}
</script>

<div class="relative mx-auto mt-10 max-w-lg space-y-4 rounded-lg">
<div class="relative mx-auto max-w-lg rounded-lg">
<ReviewProgress {remainingCards} {revisedCards} {cards} />

<div class="mx-4 mt-10">
Expand Down
29 changes: 19 additions & 10 deletions src/lib/components/Cards/ReviewProgress.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,28 @@
export let cards: CardRevisePage[];
export let revisedCards: string[];
export let remainingCards: CardRevisePage[];
let reviseCards = 5;
let progress = '0';
$: {
if (cards.length === 0) {
progress = '100%';
} else {
progress = `${((revisedCards.length * 100) / cards.length).toFixed(2)}%`;
}
}
</script>

{#if remainingCards.length === 0}
<div class="text-center">
You have revised all the cards. Go to <a href="/record" class="underline">Record</a> to create more
<div>
<div class="h-2 w-full bg-gray-200">
<div style={`width:${progress}`} class={`h-full w-0 bg-gray-400`}></div>
</div>
{:else if revisedCards.length > 0 && revisedCards.length % reviseCards === 0}
<div class="text-center text-lg text-gray-500">
Hurray. You revised {revisedCards.length} cards. Take a break or keep going.
<div class="flex justify-between text-gray-400">
<div>{progress}</div>
<div>Reviewed: {revisedCards.length}/{cards.length}</div>
</div>
{:else}
<div class="text-center text-lg text-gray-400">
cards reviewed: {revisedCards.length}/{cards.length}
</div>

{#if remainingCards.length === 0}
<div class="mt-20 text-center">
You have revised all the cards. Go to <a href="/record" class="underline">Record</a> to create more
</div>
{/if}
43 changes: 43 additions & 0 deletions src/lib/components/ContentRenderer.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<script lang="ts">
import { onMount } from 'svelte';
export let text = '';
let isUrl = false;
let isImageUrl = false;
onMount(() => {
isUrl = isValidUrl(text);
if (isUrl) {
checkIfImageUrl(text).then((result: boolean) => {
isImageUrl = result;
});
}
});
function isValidUrl(string: string) {
try {
new URL(string);
return true;
} catch (_) {
return false;
}
}
function checkIfImageUrl(url: string): Promise<boolean> {
return new Promise((resolve) => {
const img = new Image();
img.onload = () => resolve(true);
img.onerror = () => resolve(false);
img.src = url;
});
}
</script>

{#if isImageUrl}
<img src={text} alt="content" />
{:else if isUrl}
<a class="underline" href={text} target="_blank" rel="noopener noreferrer">{text}</a>
{:else}
{text}
{/if}
59 changes: 59 additions & 0 deletions src/lib/components/Heatmap/Heatmap.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<script lang="ts">
import { onMount } from 'svelte';
import CalHeatmap from 'cal-heatmap';
import Tooltip from 'cal-heatmap/plugins/Tooltip';
import 'cal-heatmap/cal-heatmap.css';
export let data;
let cal;
let divElement: HTMLDivElement;
const currentDate = new Date();
currentDate.setMonth(currentDate.getMonth() - 12);
onMount(() => {
cal = new CalHeatmap();
cal.paint(
{
itemSelector: divElement,
range: 13, // show 13 months (current month + 12 months back)
domain: {
type: 'month',
gutter: 4,
label: { text: 'MMM', textAlign: 'start', position: 'top' }
},
subDomain: { type: 'ghDay', radius: 2, width: 8, height: 8, gutter: 2 },
date: {
start: currentDate,
highlight: [
new Date() // Highlight today
],
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
},
data: {
source: data,
x: 'date',
y: (d) => +d['count']
},
scale: {
color: {
type: 'threshold',
range: ['#4dd05a', '#37a446', '#166b34', '#14432a'],
domain: [10, 20, 30]
}
}
},
[
[
Tooltip,
{
text: function (date, value, dayjsDate) {
return (value ? value + ' items' : 'No data') + ' on ' + dayjsDate.format('LL');
}
}
]
]
);
});
</script>

<div bind:this={divElement}></div>
1 change: 1 addition & 0 deletions src/lib/components/Heatmap/heatmap.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
declare module 'cal-heatmap';
Loading

0 comments on commit 0340f4d

Please sign in to comment.