copy base dmenu to dkala

This commit is contained in:
hamid zarghami
2026-02-07 15:31:22 +03:30
commit c9e37f6177
521 changed files with 57786 additions and 0 deletions
+14
View File
@@ -0,0 +1,14 @@
import { checkUserExists } from "@/lib/api/auth/user-exists"
import { useQueryClient } from "@tanstack/react-query"
export const useCheckUserExistsLazy = () => {
const queryClient = useQueryClient()
const run = (phone: string) =>
queryClient.fetchQuery({
queryKey: ['checkUserExists', phone],
queryFn: () => checkUserExists({ phone }),
})
return { run }
}
+11
View File
@@ -0,0 +1,11 @@
import { useMutation } from '@tanstack/react-query'
import { useAuthStore } from '@/zustand/authStore'
import { login } from '@/lib/api/auth/login'
export const useLogin = () =>
useMutation({
mutationFn: login,
onSuccess: (data) => {
useAuthStore.getState().login(data)
},
})
+14
View File
@@ -0,0 +1,14 @@
import { requestOtp } from "@/lib/api/auth/request-otp"
import { useQueryClient } from "@tanstack/react-query"
export const useOtpRequest = () => {
const queryClient = useQueryClient()
const run = (phone: string) =>
queryClient.fetchQuery({
queryKey: ['requestOtp', phone],
queryFn: () => requestOtp({ phone }),
})
return { run }
}
+14
View File
@@ -0,0 +1,14 @@
import { OtpValidationRequestModel, validateOtp } from "@/lib/api/auth/validate-otp"
import { useQueryClient } from "@tanstack/react-query"
export const useOtpValidation = () => {
const queryClient = useQueryClient()
const run = (model: OtpValidationRequestModel) =>
queryClient.fetchQuery({
queryKey: ['requestOtpValidation', model],
queryFn: () => validateOtp(model),
})
return { run }
}
+11
View File
@@ -0,0 +1,11 @@
import { useMutation } from '@tanstack/react-query'
import { useAuthStore } from '@/zustand/authStore'
import { fetchMe } from '@/lib/api/auth/me'
export const useProfile = () =>
useMutation({
mutationFn: fetchMe,
onSuccess: (data) => {
useAuthStore.getState().update(data)
},
})
+15
View File
@@ -0,0 +1,15 @@
import { refreshToken } from "@/lib/api/auth/refresh-token"
import { useAuthStore } from "@/zustand/authStore"
import { useMutation } from "@tanstack/react-query"
export const useOtpRequest = () => {
useMutation({
mutationFn: refreshToken,
onSuccess: (data) => {
useAuthStore.getState().setToken(data.accessToken)
},
onError: () => {
useAuthStore.getState().logout();
}
})
}
+20
View File
@@ -0,0 +1,20 @@
import { useQueryClient } from '@tanstack/react-query'
import { useAuthStore } from '@/zustand/authStore'
import { resetPassword, ResetPasswordRequestModel } from '@/lib/api/auth/reset-password';
export const useResetPassword = () =>
{
const queryClient = useQueryClient()
const run = (model: ResetPasswordRequestModel) =>
queryClient.fetchQuery({
queryKey: ['resetPassword', model],
queryFn: () => resetPassword(model),
}).then(() => {
useAuthStore.getState().logout();
}).catch((ex) => {
throw ex;
})
return { run }
}
+11
View File
@@ -0,0 +1,11 @@
import { useMutation } from '@tanstack/react-query'
import { signup } from '@/lib/api/auth/signup'
import { useAuthStore } from '@/zustand/authStore'
export const useSignup = () =>
useMutation({
mutationFn: signup,
onSuccess: (data) => {
useAuthStore.getState().login(data)
},
})
+31
View File
@@ -0,0 +1,31 @@
import { useState, useEffect } from 'react';
import { usePreferencesStore } from '@/zustand/preferencesStore';
function usePreference<T>(key: string, initial?: T) {
const value = usePreferencesStore((s) => s.items[key]?.value as T);
const setValue = usePreferencesStore((s) => s.set);
const toggleValue = usePreferencesStore((s) => s.toggle);
const [hydrated, setHydrated] = useState(false);
useEffect(() => {
setHydrated(true);
}, []);
useEffect(() => {
if (hydrated && value === undefined) {
setValue(key, initial ?? null);
}
}, [hydrated, value, key, initial, setValue]);
const toggle = (e?: React.MouseEvent | null) => {
if (e) {
e.preventDefault();
e.stopPropagation();
}
toggleValue(key);
};
return { state: value, toggle, set: setValue, hydrated };
}
export default usePreference;
+43
View File
@@ -0,0 +1,43 @@
"use client";
import { useEffect } from "react";
import { hexToOklch, calculateBrightness } from "@/lib/helpers/colorUtils";
interface UseThemeColorProps {
primaryColor?: string | null;
enabled?: boolean;
}
/**
* هوک برای تغییر دینامیک رنگ primary بر اساس رنگ دریافتی از about
*/
export function useThemeColor({
primaryColor,
enabled = true,
}: UseThemeColorProps) {
useEffect(() => {
if (!enabled || !primaryColor) return;
try {
const root = document.documentElement;
// اگر رنگ hex هست، آن را به oklch تبدیل می‌کنیم
if (primaryColor.startsWith("#")) {
const oklchColor = hexToOklch(primaryColor);
if (oklchColor) {
// اعمال رنگ primary
root.style.setProperty("--primary", oklchColor);
// محاسبه رنگ foreground متناسب
const brightness = calculateBrightness(primaryColor);
const foregroundOklch =
brightness > 0.5 ? "oklch(0 0 0)" : "oklch(1 0 0)";
root.style.setProperty("--primary-foreground", foregroundOklch);
}
}
} catch (error) {
console.error("Error setting theme color:", error);
}
}, [primaryColor, enabled]);
}
+21
View File
@@ -0,0 +1,21 @@
import { useState } from 'react'
const useToggle = (initial?: boolean) => {
const [state, setState] = useState<boolean>(initial ?? false);
const toggle = (e?: React.MouseEvent | null) => {
if (e) {
e.preventDefault();
e.stopPropagation();
}
setState((prev) => !prev);
}
const set = (value: boolean) => {
setState(value);
}
return { state, toggle, set }
}
export default useToggle
+51
View File
@@ -0,0 +1,51 @@
import { useEffect, useRef, useState } from 'react';
export const useCountdown = (shouldStart: boolean, duration: number = 30, delay: number = 1000) => {
const [timerRunning, setTimerRunning] = useState(false);
const [secondsLeft, setSecondsLeft] = useState(duration);
const intervalRef = useRef<NodeJS.Timeout | null>(null);
useEffect(() => {
if (shouldStart) {
setSecondsLeft(duration);
setTimerRunning(true);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [shouldStart]);
const stop = () => {
if (intervalRef.current) {
clearInterval(intervalRef.current);
intervalRef.current = null;
}
}
const restart = () => {
stop();
setSecondsLeft(duration);
setTimerRunning(true);
}
useEffect(() => {
if (timerRunning && intervalRef.current === null) {
intervalRef.current = setInterval(() => {
setSecondsLeft((prev) => {
if (prev <= 1) {
setTimerRunning(false);
clearInterval(intervalRef.current!);
intervalRef.current = null;
return 0;
}
return prev - 1;
});
}, delay);
}
return () => {
stop();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [timerRunning]);
return { timerRunning, secondsLeft, setTimerRunning, setSecondsLeft, stop, restart };
};