8 Commits

Author SHA1 Message Date
3d4858bcbb version: v0.0.1 2025-04-15 11:26:10 +03:00
b2feaac3e1 feat: withTitle modif 2025-04-15 11:23:48 +03:00
db9132de4d feat: pseudo-auth 2025-04-14 21:10:04 +03:00
ae9bea6c7c feat: pseudo-login 2025-04-14 21:01:33 +03:00
7f80f4790d feat: input styles 2025-04-14 20:45:46 +03:00
5d11cf0dcd feat: button styles 2025-04-14 20:45:34 +03:00
3a64f039af feat: task styles 2025-04-14 20:45:18 +03:00
2e908d01f1 feat: login styles 2025-04-14 20:45:07 +03:00
17 changed files with 57 additions and 40 deletions

View File

@@ -1,7 +1,7 @@
{
"name": "anti-hvost",
"private": true,
"version": "0.0.0",
"version": "0.0.1",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -8,7 +8,7 @@ import { AppProvider, useAppContext } from "./providers/AuthProvider";
const HomePage: FunctionComponent = () => {
const { route } = useLocation();
const { isLoggedIn } = useAppContext();
if (isLoggedIn) route("/profile/tasks", true);
if (isLoggedIn.value) route("/profile/tasks", true);
else route("/login", true);
return <div>Redirecting...</div>;
};

View File

@@ -1,5 +1,5 @@
@reference "../index.scss";
.task {
@apply flex h-24 w-[300px] cursor-pointer flex-col items-center justify-center rounded-md border-2 text-xl transition-transform hover:scale-[1.05] active:scale-[1.05] md:w-[500px];
@apply flex h-24 w-[300px] cursor-pointer flex-row items-center justify-start gap-4 rounded-[39px] bg-[rgba(251,194,199,0.53)] px-5 py-6 text-xl shadow-[0px_4px_4px_0px_rgba(0,0,0,0.25)] transition-transform hover:scale-[1.05] hover:bg-[rgba(251,194,199,0.7)] active:scale-[1.05] md:w-[500px];
}

View File

@@ -9,7 +9,10 @@ const Task: FunctionComponent<TaskProps> = ({ name }: TaskProps) => {
return (
// Временное действие для тестирования
<button onClick={() => alert(name)}>
<div class={classes.task}>{name}</div>
<div class={classes.task}>
<div class="aspect-square h-full rounded-full border bg-white"></div>
{name}
</div>
</button>
);
};

View File

@@ -1,5 +1,5 @@
@reference '../../index.scss';
.button {
@apply rounded-2xl border-2 px-4 py-3 font-semibold text-white transition-colors hover:cursor-pointer;
@apply rounded-[23px] px-4 py-3 text-xl text-black shadow-[0px_4px_4px_0px_rgba(0,0,0,0.25)] transition-colors hover:cursor-pointer;
}

View File

@@ -5,8 +5,8 @@ const button = tv({
base: classes.button,
variants: {
color: {
primary: "bg-blue-400 hover:bg-blue-500",
secondary: "bg-red-400 hover:bg-red-500",
primary: "bg-[rgba(206,232,251,0.7)] hover:bg-[rgba(206,232,251,0.9)]",
secondary: "bg-[rgba(255,251,197,0.68)] hover:bg-[rgba(255,251,197,0.9)]",
},
},
});

View File

@@ -1,5 +1,5 @@
@reference "../../index.scss";
.input_field {
@apply rounded-md border border-gray-300 p-2 placeholder:transition focus:outline-0 focus:placeholder:opacity-25;
@apply rounded-[23px] border border-gray-300 bg-white p-2 leading-8 placeholder:transition focus:outline-0 focus:placeholder:opacity-25;
}

View File

@@ -0,0 +1,12 @@
import { FunctionComponent } from "preact";
import { useEffect } from "preact/hooks";
export const withTitle = <P,>(title: string, WrappedComponent: FunctionComponent<P>): FunctionComponent<P> => {
const ComponentWithTitle: FunctionComponent<P> = (props) => {
useEffect(() => {
document.title = title;
}, []);
return <WrappedComponent {...props} />;
};
return ComponentWithTitle;
};

View File

@@ -1,15 +1,12 @@
import Button from "@/components/ui/Button";
import { withTitle } from "@/constructors/Component";
import { UrlsTitle } from "@/enums/urls";
import { FunctionComponent } from "preact";
import { useLocation } from "preact-iso";
import { useEffect } from "preact/hooks";
import classes from "./404.module.scss";
const Page404: FunctionComponent = () => {
const { route } = useLocation();
useEffect(() => {
document.title = UrlsTitle.PAGE404;
}, []);
return (
<div id={classes.container}>
<div id={classes.main_container}>
@@ -27,4 +24,4 @@ const Page404: FunctionComponent = () => {
);
};
export default Page404;
export default withTitle(UrlsTitle.PAGE404, Page404);

View File

@@ -1,7 +1,8 @@
import { withTitle } from "@/constructors/Component";
import { UrlsTitle } from "@/enums/urls";
import { cn } from "@/utils/class-merge";
import { FunctionComponent, h } from "preact";
import { useEffect, useState } from "preact/hooks";
import { useState } from "preact/hooks";
type MarkedDateType = "event" | "holiday" | "important" | string;
type MarkedDates = Record<string, MarkedDateType>;
@@ -17,9 +18,6 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
markedDates = {},
className = "",
}: BigCalendarProps) => {
useEffect(() => {
document.title = UrlsTitle.CALENDAR;
}, []);
const [currentDate, setCurrentDate] = useState<Date>(new Date());
const [selectedDate, setSelectedDate] = useState<Date | null>(null);
@@ -251,4 +249,4 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
);
};
export default BigCalendar;
export default withTitle(UrlsTitle.CALENDAR, BigCalendar);

View File

@@ -5,7 +5,7 @@
}
.login_card {
@apply flex w-[95%] min-w-[300px] flex-col justify-center gap-2 rounded-md border-gray-400 p-5 shadow-md md:w-[350px];
@apply flex min-h-[50vh] w-[95%] min-w-[300px] flex-col justify-around gap-2 rounded-[103px] bg-[linear-gradient(180.00deg,_rgba(239,251,194,0.53),rgb(206,232,251)_100%)] p-7 shadow-[0px_4px_4px_0px_rgba(0,0,0,0.25)] md:w-[350px];
}
.login_card_name {

View File

@@ -1,34 +1,33 @@
import Button from "@/components/ui/Button";
import Input from "@/components/ui/Input";
import { withTitle } from "@/constructors/Component";
import { UrlsTitle } from "@/enums/urls";
import { useAppContext } from "@/providers/AuthProvider";
import { FunctionComponent } from "preact";
import { useLocation } from "preact-iso";
import { useEffect } from "preact/hooks";
import classes from "./login.module.scss";
const LoginPage: FunctionComponent = () => {
const { isLoggedIn } = useAppContext();
const { route } = useLocation();
useEffect(() => {
document.title = UrlsTitle.LOGIN;
}, []);
return (
<div class={classes.login_container}>
<div class={classes.login_card}>
<p class={classes.login_card_name}>Антихвост</p>
<Input placeholder="Login" textAlign="center" />
<Input isPassword placeholder="Password" textAlign="center" />
<Input placeholder="Логин" textAlign="center" />
<Input isPassword placeholder="Пароль" textAlign="center" />
<Button
color="secondary"
onClick={() => {
isLoggedIn.value = true;
localStorage.setItem("loggedIn", "true");
route("/profile/tasks", true);
}}
>
Login
Войти
</Button>
</div>
</div>
);
};
export default LoginPage;
export default withTitle(UrlsTitle.LOGIN, LoginPage);

View File

@@ -1,11 +1,14 @@
import Menu from "@/components/menu";
import { useAppContext } from "@/providers/AuthProvider";
import { FunctionComponent } from "preact";
import { lazy, Route, Router, useLocation } from "preact-iso";
import ids from "./profile.module.scss";
const ProfilePage: FunctionComponent = () => {
const { route } = useLocation();
return (
const { isLoggedIn } = useAppContext();
if (!isLoggedIn.value) route("/login", true);
return isLoggedIn.value ? (
<div id={ids.main_container}>
<div id={ids.router_container}>
<Router>
@@ -25,6 +28,8 @@ const ProfilePage: FunctionComponent = () => {
<Menu />
</div>
</div>
) : (
<p>Redirecting...</p>
);
};

View File

@@ -1,17 +1,14 @@
import Button from "@/components/ui/Button";
import { withTitle } from "@/constructors/Component";
import { UrlsTitle } from "@/enums/urls";
import { useAppContext } from "@/providers/AuthProvider";
import { FunctionComponent } from "preact";
import { useLocation } from "preact-iso";
import { useEffect } from "preact/hooks";
import classes from "./profile_settings.module.scss";
const ProfileSettings: FunctionComponent = () => {
const { isLoggedIn } = useAppContext();
const { route } = useLocation();
useEffect(() => {
document.title = UrlsTitle.PROFILE;
}, []);
return (
<div class={classes.container}>
<div id={classes.avatar}>Аватар</div>
@@ -29,6 +26,7 @@ const ProfileSettings: FunctionComponent = () => {
color="secondary"
onClick={() => {
isLoggedIn.value = false;
localStorage.setItem("loggedIn", "false");
route("/login", true);
}}
>
@@ -41,4 +39,4 @@ const ProfileSettings: FunctionComponent = () => {
);
};
export default ProfileSettings;
export default withTitle(UrlsTitle.PROFILE, ProfileSettings);

View File

@@ -1,7 +1,8 @@
import Task from "@/components/task";
import { withTitle } from "@/constructors/Component";
import { UrlsTitle } from "@/enums/urls";
import { FunctionComponent } from "preact";
import { useEffect, useMemo } from "preact/hooks";
import { useMemo } from "preact/hooks";
import classes from "./profile_tasks.module.scss";
const example_tasks = ["Test 1", "Test 2", "Test 3", "Test 4", "Test 5", "Test 6", "Test 7", "Test 8"];
@@ -12,9 +13,6 @@ const ProfileTasks: FunctionComponent = () => {
const formatter = new Intl.DateTimeFormat("ru-RU", { month: "long", day: "numeric" });
return formatter.format(date);
}, []);
useEffect(() => {
document.title = UrlsTitle.TASKS;
}, []);
return (
<div class={classes.container}>
<div class={classes.header}>Сегодня: {getDate}</div>
@@ -27,4 +25,4 @@ const ProfileTasks: FunctionComponent = () => {
);
};
export default ProfileTasks;
export default withTitle(UrlsTitle.TASKS, ProfileTasks);

View File

@@ -1,3 +1,4 @@
import { stringToBoolean } from "@/utils/converter";
import { signal, Signal } from "@preact/signals";
import { createContext, JSX } from "preact";
import { useContext } from "preact/hooks";
@@ -5,14 +6,15 @@ import { useContext } from "preact/hooks";
interface AppContextValue {
isLoggedIn: Signal<boolean>;
}
const ininitialValue = stringToBoolean(localStorage.getItem("loggedIn"));
const AppContext = createContext<AppContextValue>({
isLoggedIn: signal(false),
isLoggedIn: signal(ininitialValue),
});
const AppProvider = ({ children }: { children: JSX.Element }) => {
const value: AppContextValue = {
isLoggedIn: signal(false),
isLoggedIn: signal(ininitialValue),
};
return <AppContext.Provider value={value}>{children}</AppContext.Provider>;

5
src/utils/converter.ts Normal file
View File

@@ -0,0 +1,5 @@
export const stringToBoolean = (value: string | null): boolean => {
if (value === "true") return true;
if (value === "false") return false;
return false;
};