Skip to content

Commit 997aef9

Browse files
committed
feat: 0.0.6 realease
1 parent 05bec4a commit 997aef9

File tree

10 files changed

+157
-23
lines changed

10 files changed

+157
-23
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"match-sorter": "^6.3.1",
2222
"moment": "^2.29.4",
2323
"react": "^18.2.0",
24+
"react-confetti": "^6.1.0",
2425
"react-dom": "^18.2.0",
2526
"react-github-contribution-calendar": "^2.2.0",
2627
"react-router-dom": "^6.4.3",

src-tauri/tauri.conf.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
},
88
"package": {
99
"productName": "Habit Watcher",
10-
"version": "0.0.5"
10+
"version": "0.0.6"
1111
},
1212
"tauri": {
1313
"allowlist": {

src/App.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,31 @@
1+
import { Center, Modal, Text } from "@mantine/core";
2+
import { useViewportSize } from "@mantine/hooks";
3+
import ReactConfetti from "react-confetti";
14
import { AddBtn } from "./components/Home/AddBtn";
25
import { HabbitList } from "./components/Home/HabbitList";
6+
import { useConfetti } from "./hooks/useConfetti";
37
function App() {
8+
const { height, width } = useViewportSize()
9+
10+
const { show, setShowing } = useConfetti()
11+
412
return (
513
<>
14+
<Center hidden={!show}>
15+
<ReactConfetti
16+
height={height}
17+
width={width * 0.95}
18+
/>
19+
20+
</Center>
621
<AddBtn />
722
<HabbitList />
23+
<Modal opened={show} onClose={() => setShowing(false)} centered={true}
24+
title="You did it! 🎉">
25+
<Text align="center">
26+
You have completed all your habbits for today! Good job!
27+
</Text>
28+
</Modal>
829
</>
930
);
1031
}

src/components/Home/HabbitCard.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { showNotification } from "@mantine/notifications";
33
import { useMutation, useQueryClient } from "@tanstack/react-query";
44
import React from "react";
55
import Calendar from "react-github-contribution-calendar";
6+
import { useConfetti } from "../../hooks/useConfetti";
67
import { Habbit, HabbitView } from "../../models/habbit";
78
import { checkHabbit, deleteHabbit } from "../../services/storage";
89

@@ -42,7 +43,9 @@ interface HabbitCardProps extends HabbitView {
4243
}
4344

4445
export const HabbitCard = (view: HabbitCardProps) => {
45-
46+
const {
47+
setShowing,
48+
} = useConfetti()
4649
const client = useQueryClient()
4750
const { classes } = useStyles();
4851

@@ -53,9 +56,10 @@ export const HabbitCard = (view: HabbitCardProps) => {
5356
const { mutate: checkHabbitMutation } = useMutation(checkHabbit, {
5457
onSuccess: (data) => {
5558
client.invalidateQueries(["fetchAllHabbits"])
59+
setShowing(data.confetti)
5660
showNotification({
5761
title: "Success",
58-
message: data,
62+
message: data.message,
5963
color: "teal",
6064
})
6165
},

src/components/Home/HabbitList.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { useQuery } from "@tanstack/react-query";
55
import { Habbit } from "../../models/habbit";
66
import React from "react";
77
import { UpdaetHabit } from "./UpdateHabit";
8+
89
export const HabbitList = () => {
910
const fetchHabbit = async () => {
1011
const result = await getAllhabbitsWithStats();
@@ -17,8 +18,10 @@ export const HabbitList = () => {
1718
const [habbit, setHabbit] = React.useState<Habbit | null>(null)
1819
const [open, setOpen] = React.useState(false);
1920

21+
2022
return (
2123
<>
24+
2225
{
2326
status === "loading" ? (<div>
2427
<Skeleton height={40} />
@@ -29,6 +32,7 @@ export const HabbitList = () => {
2932
}
3033
{
3134
status === "success" ? <ScrollArea mt="lg">
35+
3236
<SimpleGrid
3337
cols={2}
3438
spacing="lg"

src/hooks/useConfetti.tsx

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import React from "react";
2+
3+
export interface ConfettiType {
4+
show: boolean;
5+
visible: boolean;
6+
setShowing: (show: boolean) => void;
7+
}
8+
9+
export const ConfettiContext = React.createContext<ConfettiType>({
10+
show: false,
11+
visible: false,
12+
setShowing: () => {}
13+
})
14+
15+
export const useConfetti = () => {
16+
const context = React.useContext(ConfettiContext)
17+
if (context === undefined) {
18+
throw new Error('useConfetti must be used within a ConfettiProvider')
19+
}
20+
return context
21+
}
22+
23+
export const ConfettiProvider = (props: {
24+
children: React.ReactNode
25+
}) => {
26+
const [show, setShow] = React.useState(false)
27+
const [visible, setVisible] = React.useState(false)
28+
29+
const setShowing = (show: boolean) => {
30+
setShow(show)
31+
}
32+
33+
34+
const value = React.useMemo(() => {
35+
return {
36+
show,
37+
visible,
38+
setShowing,
39+
}
40+
}, [show, visible])
41+
42+
return (
43+
<ConfettiContext.Provider value={value}>
44+
{props.children}
45+
</ConfettiContext.Provider>
46+
)
47+
}
48+
49+

src/main.tsx

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { Layout } from "./Layout";
99
import { NewHabitPage } from "./new-habit";
1010
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
1111
import { NotificationsProvider } from "@mantine/notifications";
12+
import { ConfettiProvider } from "./hooks/useConfetti";
1213
const queryClient = new QueryClient();
1314
const router = createBrowserRouter([
1415
{
@@ -27,19 +28,21 @@ const router = createBrowserRouter([
2728

2829
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
2930
<React.StrictMode>
30-
<QueryClientProvider client={queryClient}>
31-
<MantineProvider
32-
withGlobalStyles={true}
33-
withNormalizeCSS={true}
34-
theme={{
35-
colorScheme: "dark",
36-
fontFamily: "poppins",
37-
}}
38-
>
39-
<NotificationsProvider>
40-
<RouterProvider router={router} />
41-
</NotificationsProvider>
42-
</MantineProvider>
43-
</QueryClientProvider>
31+
<ConfettiProvider>
32+
<QueryClientProvider client={queryClient}>
33+
<MantineProvider
34+
withGlobalStyles={true}
35+
withNormalizeCSS={true}
36+
theme={{
37+
colorScheme: "dark",
38+
fontFamily: "poppins",
39+
}}
40+
>
41+
<NotificationsProvider>
42+
<RouterProvider router={router} />
43+
</NotificationsProvider>
44+
</MantineProvider>
45+
</QueryClientProvider>
46+
</ConfettiProvider>
4447
</React.StrictMode>,
4548
);

src/services/storage.ts

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export async function getAllhabbitsWithStats() {
3030
const result: HabbitView[] = [];
3131
const habbits: Habbit[] = await db.select("SELECT * FROM habbit", []);
3232
for (const habbit of habbits) {
33-
const habbitCreated = moment(habbit.created_at);
33+
const yesterday = moment().toISOString();
3434
const logs: HabbitLog[] = await db.select(
3535
"SELECT * FROM habbit_log WHERE habbit_id = ?",
3636
[habbit.id],
@@ -54,7 +54,15 @@ export async function getAllhabbitsWithStats() {
5454
value: logs.length,
5555
});
5656
// find the number of missing days between the habbit creation and last log
57-
const missingDays = moment().diff(habbitCreated, "days") - logs.length;
57+
const days =
58+
Math.abs(
59+
moment(habbit.created_at, "YYYY-MM-DD")
60+
.startOf("day")
61+
.diff(moment(yesterday, "YYYY-MM-DD").startOf("day"), "days"),
62+
) + 1;
63+
64+
const missingDays = days - logs.length;
65+
5866
stats.push({
5967
name: "Missed",
6068
value: missingDays > 0 ? missingDays : 0,
@@ -93,25 +101,36 @@ export async function getAllhabbitsWithStats() {
93101

94102
export async function checkHabbit(id: number) {
95103
await load;
96-
const today = moment(new Date()).format("YYYY-MM-DD")
104+
const today = moment(new Date()).format("YYYY-MM-DD");
97105
const isAlreadyChecked: HabbitLog[] = await db.select(
98106
"SELECT * FROM habbit_log WHERE habbit_id = ? AND date(created_at) = ?",
99-
[id,today ],
107+
[id, today],
100108
);
101109
if (isAlreadyChecked.length > 0) {
102110
isAlreadyChecked.forEach(async (log) => {
103111
await db.execute("DELETE FROM habbit_log WHERE id = ?", [log.id]);
104112
});
105-
return "You have unchecked the habit";
113+
return {
114+
message: "You have unchecked the habit",
115+
confetti: false,
116+
}
106117
}
107118
// kinda weird but it works
108119
const created_at = moment(new Date()).format("YYYY-MM-DD HH:mm:ss");
109120
await db.execute(
110121
"INSERT INTO habbit_log (habbit_id, created_at) VALUES (?, ?)",
111122
[id, created_at],
112123
);
124+
// check all habbits completed today
125+
const allHabbits = await getAllhabbitsWithStats();
126+
const allHabbitsCompleted = allHabbits.every(habbit => habbit.isChecked);
127+
113128

114-
return "Awesome! You have checked the habit";
129+
130+
return {
131+
message: "Awesome! You have checked the habit",
132+
confetti: allHabbitsCompleted,
133+
}
115134
}
116135

117136
export async function deleteHabbit(id: number) {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// vite.config.ts
2+
import { defineConfig } from "file:///C:/Users/n4ze3/playground/dtoolz/node_modules/vite/dist/node/index.js";
3+
import react from "file:///C:/Users/n4ze3/playground/dtoolz/node_modules/@vitejs/plugin-react/dist/index.mjs";
4+
var vite_config_default = defineConfig({
5+
plugins: [react()],
6+
clearScreen: false,
7+
server: {
8+
port: 1420,
9+
strictPort: true
10+
},
11+
envPrefix: ["VITE_", "TAURI_"],
12+
build: {
13+
target: ["es2021", "chrome100", "safari13"],
14+
minify: !process.env.TAURI_DEBUG ? "esbuild" : false,
15+
sourcemap: !!process.env.TAURI_DEBUG
16+
}
17+
});
18+
export {
19+
vite_config_default as default
20+
};
21+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJDOlxcXFxVc2Vyc1xcXFxuNHplM1xcXFxwbGF5Z3JvdW5kXFxcXGR0b29selwiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiQzpcXFxcVXNlcnNcXFxcbjR6ZTNcXFxccGxheWdyb3VuZFxcXFxkdG9vbHpcXFxcdml0ZS5jb25maWcudHNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsID0gXCJmaWxlOi8vL0M6L1VzZXJzL240emUzL3BsYXlncm91bmQvZHRvb2x6L3ZpdGUuY29uZmlnLnRzXCI7aW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSBcInZpdGVcIjtcclxuaW1wb3J0IHJlYWN0IGZyb20gXCJAdml0ZWpzL3BsdWdpbi1yZWFjdFwiO1xyXG5cclxuLy8gaHR0cHM6Ly92aXRlanMuZGV2L2NvbmZpZy9cclxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKHtcclxuICBwbHVnaW5zOiBbcmVhY3QoKV0sXHJcblxyXG4gIC8vIFZpdGUgb3B0aW9ucyB0YWlsb3JlZCBmb3IgVGF1cmkgZGV2ZWxvcG1lbnQgYW5kIG9ubHkgYXBwbGllZCBpbiBgdGF1cmkgZGV2YCBvciBgdGF1cmkgYnVpbGRgXHJcbiAgLy8gcHJldmVudCB2aXRlIGZyb20gb2JzY3VyaW5nIHJ1c3QgZXJyb3JzXHJcbiAgY2xlYXJTY3JlZW46IGZhbHNlLFxyXG4gIC8vIHRhdXJpIGV4cGVjdHMgYSBmaXhlZCBwb3J0LCBmYWlsIGlmIHRoYXQgcG9ydCBpcyBub3QgYXZhaWxhYmxlXHJcbiAgc2VydmVyOiB7XHJcbiAgICBwb3J0OiAxNDIwLFxyXG4gICAgc3RyaWN0UG9ydDogdHJ1ZSxcclxuICB9LFxyXG4gIC8vIHRvIG1ha2UgdXNlIG9mIGBUQVVSSV9ERUJVR2AgYW5kIG90aGVyIGVudiB2YXJpYWJsZXNcclxuICAvLyBodHRwczovL3RhdXJpLnN0dWRpby92MS9hcGkvY29uZmlnI2J1aWxkY29uZmlnLmJlZm9yZWRldmNvbW1hbmRcclxuICBlbnZQcmVmaXg6IFtcIlZJVEVfXCIsIFwiVEFVUklfXCJdLFxyXG4gIGJ1aWxkOiB7XHJcbiAgICAvLyBUYXVyaSBzdXBwb3J0cyBlczIwMjFcclxuICAgIHRhcmdldDogW1wiZXMyMDIxXCIsIFwiY2hyb21lMTAwXCIsIFwic2FmYXJpMTNcIl0sXHJcbiAgICAvLyBkb24ndCBtaW5pZnkgZm9yIGRlYnVnIGJ1aWxkc1xyXG4gICAgbWluaWZ5OiAhcHJvY2Vzcy5lbnYuVEFVUklfREVCVUcgPyBcImVzYnVpbGRcIiA6IGZhbHNlLFxyXG4gICAgLy8gcHJvZHVjZSBzb3VyY2VtYXBzIGZvciBkZWJ1ZyBidWlsZHNcclxuICAgIHNvdXJjZW1hcDogISFwcm9jZXNzLmVudi5UQVVSSV9ERUJVRyxcclxuICB9LFxyXG59KTtcclxuIl0sCiAgIm1hcHBpbmdzIjogIjtBQUE0UixTQUFTLG9CQUFvQjtBQUN6VCxPQUFPLFdBQVc7QUFHbEIsSUFBTyxzQkFBUSxhQUFhO0FBQUEsRUFDMUIsU0FBUyxDQUFDLE1BQU0sQ0FBQztBQUFBLEVBSWpCLGFBQWE7QUFBQSxFQUViLFFBQVE7QUFBQSxJQUNOLE1BQU07QUFBQSxJQUNOLFlBQVk7QUFBQSxFQUNkO0FBQUEsRUFHQSxXQUFXLENBQUMsU0FBUyxRQUFRO0FBQUEsRUFDN0IsT0FBTztBQUFBLElBRUwsUUFBUSxDQUFDLFVBQVUsYUFBYSxVQUFVO0FBQUEsSUFFMUMsUUFBUSxDQUFDLFFBQVEsSUFBSSxjQUFjLFlBQVk7QUFBQSxJQUUvQyxXQUFXLENBQUMsQ0FBQyxRQUFRLElBQUk7QUFBQSxFQUMzQjtBQUNGLENBQUM7IiwKICAibmFtZXMiOiBbXQp9Cg==

yarn.lock

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,6 +1175,13 @@ prop-types@^15.6.2:
11751175
object-assign "^4.1.1"
11761176
react-is "^16.13.1"
11771177

1178+
react-confetti@^6.1.0:
1179+
version "6.1.0"
1180+
resolved "https://registry.yarnpkg.com/react-confetti/-/react-confetti-6.1.0.tgz#03dc4340d955acd10b174dbf301f374a06e29ce6"
1181+
integrity sha512-7Ypx4vz0+g8ECVxr88W9zhcQpbeujJAVqL14ZnXJ3I23mOI9/oBVTQ3dkJhUmB0D6XOtCZEM6N0Gm9PMngkORw==
1182+
dependencies:
1183+
tween-functions "^1.2.0"
1184+
11781185
react-dom@^18.2.0:
11791186
version "18.2.0"
11801187
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
@@ -1361,6 +1368,11 @@ tslib@^2.0.0:
13611368
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e"
13621369
integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==
13631370

1371+
tween-functions@^1.2.0:
1372+
version "1.2.0"
1373+
resolved "https://registry.yarnpkg.com/tween-functions/-/tween-functions-1.2.0.tgz#1ae3a50e7c60bb3def774eac707acbca73bbc3ff"
1374+
integrity sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA==
1375+
13641376
typescript@^4.6.4:
13651377
version "4.8.4"
13661378
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.4.tgz#c464abca159669597be5f96b8943500b238e60e6"

0 commit comments

Comments
 (0)