Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
6f89ca8
Create CI workflow for Node.js application
Abviol Mar 23, 2026
81d2ee1
Rename CI workflow configuration file
Abviol Mar 23, 2026
5de3cf4
Replace pnpm installation with Corepack enable
Abviol Mar 23, 2026
20d9dc8
Replace Corepack enable with pnpm installation
Abviol Mar 23, 2026
09c9f37
Update pnpm installation step in CI workflow
Abviol Mar 23, 2026
303b972
Update CI workflow to use pnpm action setup
Abviol Mar 23, 2026
60d126f
Upgrade Node.js setup action and rename step
Abviol Mar 23, 2026
e4018a4
Refactor CI workflow for pull request checks
Abviol Mar 23, 2026
16ed0b7
Refactor CI workflow for improved checks
Abviol Mar 23, 2026
6ad74f0
Set up WebStorm
Abviol Mar 23, 2026
6367b91
fix(demo): eslint error
Abviol Mar 23, 2026
fbe54e6
Update page.tsx
Abviol Mar 23, 2026
991c472
fix(product page): eslint
Abviol Mar 23, 2026
8c9a007
fix(cartDrawerItem): eslint
Abviol Mar 23, 2026
835292e
fix(cartItem): eslint
Abviol Mar 23, 2026
1f95262
fix(commentCard): eslint
Abviol Mar 23, 2026
97b5ee9
fix(footer): eslint
Abviol Mar 23, 2026
db850d9
fix(header): eslint
Abviol Mar 23, 2026
a9c259a
fix(activeFilters): eslint
Abviol Mar 23, 2026
caf2699
fix(brandsContent): eslint
Abviol Mar 23, 2026
5bd1a3d
fix(productGallery): eslint
Abviol Mar 23, 2026
89c5ea6
fix(searchResultItem): eslint
Abviol Mar 23, 2026
bcb10d5
fix(marker): eslint
Abviol Mar 23, 2026
73356ac
fix(useCountdown): eslint
Abviol Mar 23, 2026
2c74834
fix(data): eslint
Abviol Mar 23, 2026
658f258
Update .gitignore
Abviol Mar 23, 2026
705d68c
Remove .idea/ from cache
Abviol Mar 23, 2026
54829e8
Merge branch 'feature/actions' of github.com:Abviol/scent into featur…
Abviol Mar 23, 2026
2a6ab87
fix(marker): always truthy expression
Abviol Mar 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: CI

'on':
pull_request:
branches:
- dev
- master

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: true

jobs:
check-dist:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1

- name: Setup pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
with:
run_install: true
version: 9

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Run ESLint
run: pnpm lint

- name: Build app
run: pnpm build
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,7 @@ yarn-error.log*
*.tsbuildinfo
next-env.d.ts

# webstorm
/.idea/

/app/generated/prisma-client
4 changes: 2 additions & 2 deletions app/demo/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export default function Page() {
];

// State for sorting
const [sorting, setSorting] = useState<SortingType>({ criteria: "name", order: "DESC" });
const [sorting] = useState<SortingType>({ criteria: "name", order: "DESC" });

// const handleSave = (e: ProductCardOnSaveEvent) => {
// console.log(
Expand Down Expand Up @@ -355,7 +355,7 @@ export default function Page() {
<DemoSection title="Sorting Dropdown">
<div className="flex justify-end h-[220px]">
<Suspense>
{/* <Sorting criteria={sorting.criteria} order={sorting.order} /> */}
<Sorting criteria={sorting.criteria} order={sorting.order} />
</Suspense>
</div>
</DemoSection>
Expand Down
10 changes: 3 additions & 7 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export default function Home() {
productLink="/shop/product/111"
color="#32665A"
promotionDeadline={
new Date("2026-03-01T23:59:59Z")
new Date("2026-06-01T23:59:59Z")
}
/>
<BannerCard
Expand All @@ -143,7 +143,7 @@ export default function Home() {
productLink="/shop/product/222"
color="#86804C"
promotionDeadline={
new Date("2026-03-01T23:59:59Z")
new Date("2026-05-04T23:59:59Z")
}
/>
</div>
Expand Down Expand Up @@ -218,11 +218,7 @@ function BannerCard(props: BannerCardProps) {
</div>
<p className="mt-5 text-center">
<i>
&quot;Until the end of the promotion:{" "}
{cd.isMounted
? `${cd.d} days ${formatTime(cd.h)}:${formatTime(cd.m)}:${formatTime(cd.s)}`
: "0 days 00:00:00"}
&quot;
&quot;Until the end of the promotion: {cd.d} days {formatTime(cd.h)}:{formatTime(cd.m)}:{formatTime(cd.s)}&quot;
</i>
</p>
</div>
Expand Down
1 change: 1 addition & 0 deletions app/shop/product/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type ProductPageProps = {
// Mimic a DB-request
async function getProduct(id: string): Promise<ProductType> {
await new Promise((resolve) => setTimeout(resolve, 0));
console.log("Got product with id ", id);

return PRODUCTS[0];
}
Expand Down
3 changes: 1 addition & 2 deletions components/cartDrawerItem/cartDrawerItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import { AvailabilityType } from "@/lib/types";
import {
getAvailability,
getAvailabilityClass,
getEuro,
} from "@/lib/utils";
import { Trash2 } from "lucide-react";
Expand Down Expand Up @@ -36,7 +35,7 @@ export default function CartDrawerItem({
onDelete,
}: CartDrawerItemProps) {
const [isDeleted, setIsDeleted] = useState<boolean>(false);
const [availability, setAvailability] = useState<AvailabilityType>(
const [availability] = useState<AvailabilityType>(
getAvailability(quantityInStock)
);
const availabilityClass: string =
Expand Down
2 changes: 1 addition & 1 deletion components/cartItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default function CartItem({
onDelete,
}: CartItemProps) {
const [isDeleted, setIsDeleted] = useState<boolean>(false);
const [availability, setAvailability] = useState<AvailabilityType>(
const [availability] = useState<AvailabilityType>(
getAvailability(quantityInStock)
);
const availabilityClass: string = getAvailabilityClass(availability);
Expand Down
3 changes: 1 addition & 2 deletions components/commentCard/commentCard.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Image from "next/image";
import Rating from "../ui/rating";
import Rating from "../ui/rating";
import Avatar from "../ui/avatar";

export interface CommentCardProps {
Expand Down
2 changes: 1 addition & 1 deletion components/layout/footer.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import Link from "next/link";
import { Facebook, Instagram, Twitter, Send } from "lucide-react";
import { Send } from "lucide-react";
import { Input } from "../ui/input";
import { Button } from "../ui/button";
import { TelegramIcon } from "../icons/telegram";
Expand Down
8 changes: 4 additions & 4 deletions components/layout/header.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import React, { useEffect, useRef, useState } from "react";
import React, { useEffect, useRef, useState, useCallback } from "react";
import Link from "next/link";
import { Bookmark, Mail, Search, ShoppingCartIcon, X } from "lucide-react";

Expand Down Expand Up @@ -34,12 +34,12 @@ export default function Header() {
const closeSearch = () => setIsSearchOpen(false);
const handleSearchFocus = () => setIsSearchOpen(true);
const clearSearch = () => setSearchQuery("");
const handleBlur = (e: PointerEvent) => {
const handleBlur = useCallback((e: PointerEvent) => {
const target = e.target as HTMLElement;
if (!target.closest(".search-bar")) {
closeSearch();
}
};
}, []);
const applySearchQuery = () => {
router.push(`/shop?q=${encodeURIComponent(searchQuery.trim())}`);
closeSearch();
Expand All @@ -59,7 +59,7 @@ export default function Header() {
useEffect(() => {
document.body.addEventListener("click", handleBlur);
return () => document.body.removeEventListener("click", handleBlur);
}, []);
}, [handleBlur]);

return (
<>
Expand Down
2 changes: 1 addition & 1 deletion components/pages/shop/activeFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export function ActiveFilters({ filters }: ActiveFiltersProps) {

return (
<div className="selected-filters flex flex-row flex-wrap gap-5 mb-6">
{tags.map((tag, idx) => (
{tags.map((tag) => (
<Tag
key={`${tag.id}-${tag.value}`}
label={tag.label}
Expand Down
4 changes: 2 additions & 2 deletions components/pages/shop/brands/brandsContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default function BrandsContent({ selectedChar = "ALL", brandGroups }: Bra

return (
<div className="px-40 flex flex-col gap-20">
{groupsToShow.map((b, i) => (
{groupsToShow.map((b) => (
<BrandsGroup key={`${b.char}-set`} {...b} />
))}
</div>
Expand All @@ -33,7 +33,7 @@ function BrandsGroup({ char, brands }: BrandGroupType) {
</h2>
</div>
<ul className="grid grid-cols-3 gap-x-8 gap-y-2">
{brands.map((b, i) => (
{brands.map((b) => (
<li key={b.id}>
<Link href={`/shop?brands=${b.id}`} className="text-xl hover:text-accent">{b.name}</Link>
</li>
Expand Down
2 changes: 1 addition & 1 deletion components/pages/shop/product/productGallery.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import Image from "next/image";
import { KeyboardEventHandler, ReactNode, useState } from "react";
import { ReactNode, useState } from "react";
import { ChevronDown, ChevronUp } from "lucide-react";

import { Swiper, SwiperSlide } from "swiper/react";
Expand Down
2 changes: 1 addition & 1 deletion components/searchResultItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export default function SearchResultItem({
imageUrl,
}: SearchResultItemProps) {
const productLink = `/shop/product/${productId}`;
const [availability, setAvailability] = useState<AvailabilityType>(getAvailability(quantityInStock));
const [availability] = useState<AvailabilityType>(getAvailability(quantityInStock));
const availabilityClass: string = getAvailabilityClass(availability);

return (
Expand Down
7 changes: 5 additions & 2 deletions components/ui/marker.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { FireIcon } from "../icons/fireIcon";
import { cn } from "@/lib/utils";
import { FireIcon } from "../icons/fireIcon";

export interface MarkerProps {
name: 'hit' | undefined;
Expand All @@ -7,7 +8,9 @@ export interface MarkerProps {

export default function Marker({name, size}: MarkerProps) {
return (
<div className="size-6 flex justify-center items-center rounded-[8px] bg-red-600">
<div className={cn("flex justify-center items-center rounded-[8px] bg-red-600",
size === 'sm' ? "size-5" : size === 'md' ? "size-6" : "size-6",
)}>
{name == 'hit' && (
<FireIcon size={16} color="#ffffff"></FireIcon>
)}
Expand Down
24 changes: 8 additions & 16 deletions hooks/use-countdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,15 @@
import { useEffect, useState } from "react";

export function useCountdown(deadline: Date) {
const [isMounted, setIsMounted] = useState(false);
const [timeLeft, setTimeLeft] = useState({ d: 0, h: 0, m: 0, s: 0 });
const [, forceUpdate] = useState(0);

useEffect(() => {
setIsMounted(true);
useEffect(() => {
const interval = setInterval(() => {
forceUpdate(t => t + 1);
}, 1000);

setTimeLeft(getTimeRemaining(deadline));
return () => clearInterval(interval);
}, []);

const interval = setInterval(() => {
setTimeLeft(getTimeRemaining(deadline));
}, 1000);

return () => clearInterval(interval);
}, [deadline])

return {
...timeLeft,
isMounted,
};
return getTimeRemaining(deadline);
}
2 changes: 1 addition & 1 deletion lib/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,6 @@ const BRANDS: BrandType[] = [
"2million",
"3million",
"1hundred"
].map((b, i) => ({id: b, name: b}));
].map((b) => ({id: b, name: b}));

export { PRODUCTS, MOCK_SHOP_FILTERS, HOME_COMMENTS, BRANDS };
Loading