├── .yarnrc.yml ├── apps └── web │ ├── .yarnrc.yml │ ├── src │ ├── app │ │ ├── icon.ico │ │ ├── apple-icon.png │ │ ├── (pages) │ │ │ ├── (user) │ │ │ │ └── settings │ │ │ │ │ ├── page.tsx │ │ │ │ │ └── layout.metadata.ts │ │ │ ├── (auth) │ │ │ │ ├── layout.tsx │ │ │ │ ├── login │ │ │ │ │ └── page.tsx │ │ │ │ ├── signup │ │ │ │ │ └── page.tsx │ │ │ │ └── reset │ │ │ │ │ ├── page.tsx │ │ │ │ │ └── [token] │ │ │ │ │ └── page.tsx │ │ │ ├── edit │ │ │ │ ├── layout.tsx │ │ │ │ ├── [editId] │ │ │ │ │ ├── update │ │ │ │ │ │ └── page.tsx │ │ │ │ │ └── page.tsx │ │ │ │ └── content │ │ │ │ │ └── page.tsx │ │ │ └── (content) │ │ │ │ ├── anime │ │ │ │ ├── sitemap.ts │ │ │ │ └── (anime-list) │ │ │ │ │ └── page.tsx │ │ │ │ ├── manga │ │ │ │ ├── sitemap.ts │ │ │ │ └── (manga-list) │ │ │ │ │ └── page.tsx │ │ │ │ └── novel │ │ │ │ ├── sitemap.ts │ │ │ │ └── (novel-list) │ │ │ │ └── page.tsx │ │ └── (api) │ │ │ └── auth │ │ │ └── reset │ │ │ └── [token] │ │ │ └── route.ts │ ├── features │ │ ├── schedule │ │ │ └── index.ts │ │ ├── collections │ │ │ ├── index.ts │ │ │ ├── collection-list │ │ │ │ └── index.ts │ │ │ ├── collection-view │ │ │ │ └── index.ts │ │ │ └── collection-edit │ │ │ │ └── index.ts │ │ ├── manga │ │ │ ├── index.ts │ │ │ └── components │ │ │ │ └── manga-list-skeleton.tsx │ │ ├── novel │ │ │ ├── index.ts │ │ │ └── components │ │ │ │ └── novel-list-skeleton.tsx │ │ ├── modals │ │ │ ├── edit-modals │ │ │ │ └── index.ts │ │ │ ├── utility-modals │ │ │ │ ├── index.ts │ │ │ │ └── search-modal │ │ │ │ │ └── hooks │ │ │ │ │ ├── useUserSearchList.ts │ │ │ │ │ ├── useAnimeSearchList.ts │ │ │ │ │ ├── useMangaSearchList.ts │ │ │ │ │ ├── useNovelSearchList.ts │ │ │ │ │ ├── usePersonSearchList.ts │ │ │ │ │ └── useCharacterSearchList.ts │ │ │ ├── oauth-modals │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── filter-preset-modal │ │ │ │ └── index.ts │ │ │ ├── user-modals │ │ │ │ └── index.ts │ │ │ └── filter-modals │ │ │ │ └── index.ts │ │ ├── anime │ │ │ ├── index.ts │ │ │ └── components │ │ │ │ └── anime-list-skeleton.tsx │ │ ├── oauth │ │ │ ├── index.ts │ │ │ ├── components │ │ │ │ └── scope.tsx │ │ │ └── oauth-header.tsx │ │ ├── users │ │ │ ├── user-profile │ │ │ │ ├── index.ts │ │ │ │ └── user-statistics.tsx │ │ │ ├── userlist │ │ │ │ ├── index.ts │ │ │ │ └── components │ │ │ │ │ └── table-view │ │ │ │ │ ├── volumes-cell.tsx │ │ │ │ │ ├── chapters-cell.tsx │ │ │ │ │ ├── episodes-cell.tsx │ │ │ │ │ └── media-cell.tsx │ │ │ └── index.ts │ │ ├── comments │ │ │ └── index.ts │ │ ├── people │ │ │ ├── index.ts │ │ │ └── cover.tsx │ │ ├── common │ │ │ ├── scroll-top.tsx │ │ │ ├── index.ts │ │ │ └── login-button.tsx │ │ ├── characters │ │ │ ├── index.ts │ │ │ └── cover.tsx │ │ ├── home │ │ │ └── index.ts │ │ ├── filters │ │ │ ├── index.ts │ │ │ └── hooks │ │ │ │ └── use-change-param.ts │ │ ├── auth │ │ │ ├── password-confirm-header.tsx │ │ │ ├── index.ts │ │ │ ├── login-header.tsx │ │ │ ├── signup-header.tsx │ │ │ └── forgot-password-header.tsx │ │ ├── articles │ │ │ ├── article-edit │ │ │ │ └── article-title.tsx │ │ │ └── article-view │ │ │ │ ├── article-author.tsx │ │ │ │ ├── article-document.tsx │ │ │ │ └── article-tags.tsx │ │ ├── content │ │ │ ├── index.ts │ │ │ └── hooks │ │ │ │ └── use-staff.ts │ │ └── edit │ │ │ ├── components │ │ │ └── edit-list │ │ │ │ ├── edit-skeleton.tsx │ │ │ │ └── edit-head.tsx │ │ │ └── edit-actions │ │ │ ├── close-action.tsx │ │ │ └── accept-action.tsx │ ├── components │ │ ├── plate │ │ │ ├── editor │ │ │ │ ├── plugins │ │ │ │ │ ├── basic-marks-base-kit.tsx │ │ │ │ │ ├── basic-marks-kit.tsx │ │ │ │ │ ├── basic-nodes-kit.tsx │ │ │ │ │ ├── link-base-kit.tsx │ │ │ │ │ ├── exit-break-kit.tsx │ │ │ │ │ ├── emoji-kit.tsx │ │ │ │ │ ├── link-kit.tsx │ │ │ │ │ ├── image-base-kit.tsx │ │ │ │ │ ├── video-base-kit.tsx │ │ │ │ │ ├── spoiler-base-kit.tsx │ │ │ │ │ ├── basic-blocks-kit.tsx │ │ │ │ │ └── image-group-base-kit.tsx │ │ │ │ └── static-kit.tsx │ │ │ └── ui │ │ │ │ ├── paragraph-node-static.tsx │ │ │ │ ├── blockquote-node-static.tsx │ │ │ │ ├── paragraph-node.tsx │ │ │ │ ├── blockquote-node.tsx │ │ │ │ ├── spoiler-node.tsx │ │ │ │ ├── mark-toolbar-button.tsx │ │ │ │ ├── link-node-static.tsx │ │ │ │ └── link-toolbar-button.tsx │ │ ├── ui │ │ │ ├── aspect-ratio.tsx │ │ │ ├── skeleton.tsx │ │ │ ├── collapsible.tsx │ │ │ ├── block.tsx │ │ │ ├── card.tsx │ │ │ └── label.tsx │ │ ├── markdown │ │ │ └── viewer │ │ │ │ ├── components │ │ │ │ └── no-spoiler.tsx │ │ │ │ └── plugins │ │ │ │ └── remark-disable-tokenizer.tsx │ │ ├── typography │ │ │ ├── li.tsx │ │ │ ├── large.tsx │ │ │ ├── p.tsx │ │ │ ├── ul.tsx │ │ │ ├── ol.tsx │ │ │ ├── lead.tsx │ │ │ ├── muted.tsx │ │ │ ├── small.tsx │ │ │ ├── h3.tsx │ │ │ ├── h4.tsx │ │ │ ├── h5.tsx │ │ │ ├── h1.tsx │ │ │ ├── h2.tsx │ │ │ ├── blockquote.tsx │ │ │ └── inline-code.tsx │ │ ├── icons │ │ │ ├── iconamoon │ │ │ │ ├── IconamoonSignDivisionSlashThin.tsx │ │ │ │ └── IconamoonCommentFill.tsx │ │ │ ├── bx │ │ │ │ ├── BxBxsUpvote.tsx │ │ │ │ ├── BxBxsDownvote.tsx │ │ │ │ ├── BxUpvote.tsx │ │ │ │ ├── BxDownvote.tsx │ │ │ │ ├── BxBxlTelegram.tsx │ │ │ │ ├── BxBxlGoogle.tsx │ │ │ │ ├── BxShareAlt.tsx │ │ │ │ └── BxBxsDonateHeart.tsx │ │ │ ├── fe │ │ │ │ ├── FeMention.tsx │ │ │ │ └── FeRandom.tsx │ │ │ ├── material-symbols │ │ │ │ ├── MaterialSymbolsRemoveRounded.tsx │ │ │ │ ├── MaterialSymbolsBookmarkOutline.tsx │ │ │ │ ├── MaterialSymbolsArticle.tsx │ │ │ │ ├── MaterialSymbolsCheckRounded.tsx │ │ │ │ ├── MaterialSymbolsSecurity.tsx │ │ │ │ ├── MaterialSymbolsContentCopy.tsx │ │ │ │ ├── MaterialSymbolsCheckSmallRounded.tsx │ │ │ │ ├── MaterialSymbolsKeyboardArrowUpRounded.tsx │ │ │ │ ├── MaterialSymbolsAddRounded.tsx │ │ │ │ ├── MaterialSymbolsDeleteForever.tsx │ │ │ │ ├── MaterialSymbolsDraftRounded.tsx │ │ │ │ ├── MaterialSymbolsShortTextRounded.tsx │ │ │ │ ├── MaterialSymbolsInfoIRounded.tsx │ │ │ │ ├── MaterialSymbolsPerson.tsx │ │ │ │ ├── MaterialSymbolsStack.tsx │ │ │ │ ├── MaterialSymbolsPlayArrowRounded.tsx │ │ │ │ ├── MaterialSymbolsArrowDropDownRounded.tsx │ │ │ │ ├── MaterialSymbolsKeyboardArrowDownRounded.tsx │ │ │ │ ├── MaterialSymbolsShieldRounded.tsx │ │ │ │ ├── MaterialSymbolsEventList.tsx │ │ │ │ ├── MaterialSymbolsMoreHoriz.tsx │ │ │ │ ├── MaterialSymbolsMoreVert.tsx │ │ │ │ ├── MaterialSymbolsCloseRounded.tsx │ │ │ │ ├── MaterialSymbolsEditRounded.tsx │ │ │ │ ├── MaterialSymbolsComputerOutlineRounded.tsx │ │ │ │ ├── MaterialSymbolsHomeRounded.tsx │ │ │ │ ├── MaterialSymbolsSortRounded.tsx │ │ │ │ ├── MaterialSymbolsReplyRounded.tsx │ │ │ │ ├── MaterialSymbolsAccountBox.tsx │ │ │ │ ├── MaterialSymbolsArrowRightAltRounded.tsx │ │ │ │ ├── MaterialSymbolsFavoriteRounded.tsx │ │ │ │ ├── MaterialSymbolsNotificationsRounded.tsx │ │ │ │ ├── MaterialSymbolsSearchRounded.tsx │ │ │ │ ├── MaterialSymbolsLiveTvRounded.tsx │ │ │ │ ├── MaterialSymbolsClockLoader10.tsx │ │ │ │ ├── MaterialSymbolsImageOutlineRounded.tsx │ │ │ │ ├── MaterialSymbolsShieldPerson.tsx │ │ │ │ ├── MaterialSymbolsAnimatedImages.tsx │ │ │ │ ├── MaterialSymbolsAddCommentRounded.tsx │ │ │ │ ├── MaterialSymbolsCloseSmallRounded.tsx │ │ │ │ ├── MaterialSymbolsBarChartRounded.tsx │ │ │ │ ├── MaterialSymbolsKidStar.tsx │ │ │ │ ├── MaterialSymbolsCheckCircleRounded.tsx │ │ │ │ ├── MaterialSymbolsInfoRounded.tsx │ │ │ │ ├── MaterialSymbolsWarningRounded.tsx │ │ │ │ ├── MaterialSymbolsDriveFileRenameOutlineRounded.tsx │ │ │ │ ├── MaterialSymbolsOpenInNewRounded.tsx │ │ │ │ ├── MaterialSymbolsBookmarkFlagOutlineRounded.tsx │ │ │ │ ├── MaterialSymbolsLoginRounded.tsx │ │ │ │ ├── MaterialSymbolsLogoutRounded.tsx │ │ │ │ ├── MaterialSymbolsRefreshRounded.tsx │ │ │ │ ├── MaterialSymbolsDynamicFeedRounded.tsx │ │ │ │ ├── MaterialSymbolsLockOpenRounded.tsx │ │ │ │ ├── MaterialSymbolsZoomOutRounded.tsx │ │ │ │ ├── MaterialSymbolsPublishRounded.tsx │ │ │ │ ├── MaterialSymbolsUploadRounded.tsx │ │ │ │ ├── MaterialSymbolsWarningOutlineRounded.tsx │ │ │ │ ├── MaterialSymbolsEventListRounded.tsx │ │ │ │ ├── MaterialSymbolsHourglassEmptyRounded.tsx │ │ │ │ ├── MaterialSymbolsFlagCircleRounded.tsx │ │ │ │ ├── MaterialSymbolsImageNotSupportedOutlineRounded.tsx │ │ │ │ ├── MaterialSymbolsLockOpenRightOutlineRounded.tsx │ │ │ │ ├── MaterialSymbolsLibraryMusicRounded.tsx │ │ │ │ ├── MaterialSymbolsFeatureSearch.tsx │ │ │ │ ├── MaterialSymbolsLinkRounded.tsx │ │ │ │ ├── MaterialSymbolsVisibilityOutline.tsx │ │ │ │ ├── MaterialSymbolsGridViewRounded.tsx │ │ │ │ ├── MaterialSymbolsPersonAddRounded.tsx │ │ │ │ ├── MaterialSymbolsStarRateOutlineRounded.tsx │ │ │ │ ├── MaterialSymbolsDeleteForeverRounded.tsx │ │ │ │ ├── MaterialSymbolsHeartMinusRounded.tsx │ │ │ │ ├── MaterialSymbolsErrorCircleRounded.tsx │ │ │ │ ├── MaterialSymbolsNotificationImportantRounded.tsx │ │ │ │ ├── MaterialSymbolsNightlightOutlineRounded.tsx │ │ │ │ ├── MaterialSymbolsDragIndicator.tsx │ │ │ │ ├── MaterialSymbolsNewsmodeRounded.tsx │ │ │ │ ├── MaterialSymbolsZoomInRounded.tsx │ │ │ │ ├── MaterialSymbolsCustomTypographyRounded.tsx │ │ │ │ ├── MaterialSymbolsPerson2OutlineRounded.tsx │ │ │ │ └── MaterialSymbolsCalendarClockRounded.tsx │ │ │ ├── ant-design │ │ │ │ ├── AntDesignFilterFilled.tsx │ │ │ │ ├── AntDesignArrowLeftOutlined.tsx │ │ │ │ ├── AntDesignArrowRightOutlined.tsx │ │ │ │ ├── AntDesignArrowDownOutlined.tsx │ │ │ │ └── AntDesignClearOutlined.tsx │ │ │ ├── ep │ │ │ │ └── EpSuccessFilled.tsx │ │ │ ├── watch-status │ │ │ │ ├── dropped.tsx │ │ │ │ ├── completed.tsx │ │ │ │ └── planned.tsx │ │ │ ├── mdi │ │ │ │ └── MdiPuzzle.tsx │ │ │ └── ph │ │ │ │ └── PhTipJarFill.tsx │ │ ├── content-card │ │ │ └── content-card-skeleton.tsx │ │ ├── tailwind-indicator.tsx │ │ ├── snowfall-manager.tsx │ │ ├── character-card.tsx │ │ ├── navigation │ │ │ └── sub-nav.tsx │ │ └── comments │ │ │ └── comments.tsx │ ├── types │ │ └── index.d.ts │ ├── utils │ │ ├── get-api-error-message.ts │ │ ├── constants │ │ │ └── banners.ts │ │ ├── truncate-text.ts │ │ ├── zod.ts │ │ ├── adapters │ │ │ ├── convert-activity-stats.ts │ │ │ └── convert-activity │ │ │ │ └── convert-favorite-activity.tsx │ │ ├── get-hikka-client-config.ts │ │ └── cookies.ts │ └── services │ │ ├── providers │ │ └── theme-provider.tsx │ │ └── hooks │ │ ├── use-media-query.ts │ │ ├── use-size.ts │ │ ├── use-on-screen.ts │ │ └── use-debounce.ts │ ├── public │ ├── hikka.art.jpg │ ├── logo-icon.png │ ├── hikka.notfound.png │ ├── hikka.art.summer.jpg │ └── robots.txt │ ├── .env.production │ ├── .env.development │ ├── next-env.d.ts │ ├── .gitignore │ └── components.json ├── packages ├── client │ ├── .yarnrc.yml │ ├── index.ts │ ├── .eslintrc.json │ ├── types │ │ ├── upload.ts │ │ ├── stats.ts │ │ ├── vote.ts │ │ ├── related.ts │ │ ├── follow.ts │ │ ├── companies.ts │ │ └── schedule.ts │ ├── modules │ │ ├── genres.ts │ │ ├── related.ts │ │ ├── stats.ts │ │ ├── index.ts │ │ └── base.ts │ ├── errors.ts │ ├── tsconfig.json │ ├── tsup.config.ts │ ├── tsconfig.build.json │ └── .gitignore └── react │ ├── utils │ └── index.ts │ ├── types │ ├── history.ts │ ├── stats.ts │ ├── schedule.ts │ ├── companies.ts │ ├── related.ts │ ├── articles.ts │ ├── collections.ts │ ├── auth.ts │ ├── manga.ts │ ├── novel.ts │ ├── vote.ts │ ├── favourite.ts │ ├── edit.ts │ ├── follow.ts │ ├── characters.ts │ ├── user.ts │ ├── client.ts │ ├── comments.ts │ ├── people.ts │ ├── read.ts │ ├── anime.ts │ ├── watch.ts │ └── index.ts │ ├── client │ ├── provider │ │ ├── index.ts │ │ ├── context.ts │ │ └── useHikkaClient.ts │ └── hooks │ │ ├── api │ │ ├── genres.ts │ │ ├── related.ts │ │ └── upload.ts │ │ └── utils │ │ └── useTitleUtils.ts │ ├── tsconfig.build.json │ ├── .eslintrc.json │ ├── jest.config.cjs │ ├── core │ ├── index.ts │ └── createHikkaClient.ts │ ├── setupTests.ts │ ├── server │ └── prefetch │ │ └── api │ │ ├── genres.ts │ │ ├── vote.ts │ │ ├── related.ts │ │ └── settings.ts │ └── .gitignore ├── postcss.config.js ├── .dockerignore ├── .vscode └── settings.json ├── tsconfig.base.json └── .prettierrc.json /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules -------------------------------------------------------------------------------- /apps/web/.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | -------------------------------------------------------------------------------- /packages/client/.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules -------------------------------------------------------------------------------- /packages/react/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './titleUtils'; 2 | -------------------------------------------------------------------------------- /apps/web/src/app/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hikka-io/hikka-next/HEAD/apps/web/src/app/icon.ico -------------------------------------------------------------------------------- /packages/react/types/history.ts: -------------------------------------------------------------------------------- 1 | export interface UseUserHistoryParams { 2 | username: string; 3 | } 4 | -------------------------------------------------------------------------------- /apps/web/public/hikka.art.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hikka-io/hikka-next/HEAD/apps/web/public/hikka.art.jpg -------------------------------------------------------------------------------- /apps/web/public/logo-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hikka-io/hikka-next/HEAD/apps/web/public/logo-icon.png -------------------------------------------------------------------------------- /apps/web/src/app/apple-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hikka-io/hikka-next/HEAD/apps/web/src/app/apple-icon.png -------------------------------------------------------------------------------- /apps/web/public/hikka.notfound.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hikka-io/hikka-next/HEAD/apps/web/public/hikka.notfound.png -------------------------------------------------------------------------------- /apps/web/public/hikka.art.summer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hikka-io/hikka-next/HEAD/apps/web/public/hikka.art.summer.jpg -------------------------------------------------------------------------------- /apps/web/src/features/schedule/index.ts: -------------------------------------------------------------------------------- 1 | // Schedule Components 2 | export { default as ScheduleList } from './schedule-list'; 3 | -------------------------------------------------------------------------------- /packages/react/client/provider/index.ts: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | export * from './HikkaProvider'; 3 | export * from './useHikkaClient'; 4 | -------------------------------------------------------------------------------- /packages/react/types/stats.ts: -------------------------------------------------------------------------------- 1 | // No parameters needed for the stats module hooks 2 | 3 | export interface UseTopEditorsListParams {} 4 | -------------------------------------------------------------------------------- /apps/web/src/features/collections/index.ts: -------------------------------------------------------------------------------- 1 | export * from './collection-edit'; 2 | export * from './collection-list'; 3 | export * from './collection-view'; 4 | -------------------------------------------------------------------------------- /packages/react/types/schedule.ts: -------------------------------------------------------------------------------- 1 | import { AnimeScheduleArgs } from '@hikka/client'; 2 | 3 | export interface UseAnimeScheduleParams { 4 | args?: AnimeScheduleArgs; 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/public/robots.txt: -------------------------------------------------------------------------------- 1 | # * 2 | User-agent: * 3 | Allow: / 4 | 5 | # Host 6 | Host: https://hikka.io 7 | 8 | # Sitemaps 9 | Sitemap: https://hikka.io/sitemap.xml 10 | -------------------------------------------------------------------------------- /packages/react/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "incremental": false, 5 | "composite": false 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/react/types/companies.ts: -------------------------------------------------------------------------------- 1 | import { CompaniesSearchArgs } from '@hikka/client'; 2 | 3 | export interface UseCompaniesSearchParams { 4 | args?: CompaniesSearchArgs; 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/features/collections/collection-list/index.ts: -------------------------------------------------------------------------------- 1 | export { default as CollectionList } from './collection-list'; 2 | export { default as CollectionSort } from './collection-sort'; 3 | -------------------------------------------------------------------------------- /apps/web/src/features/manga/index.ts: -------------------------------------------------------------------------------- 1 | // Main Manga Components 2 | export { default as MangaList } from './manga-list'; 3 | export { default as MangaListNavbar } from './manga-list-navbar'; 4 | -------------------------------------------------------------------------------- /apps/web/src/features/novel/index.ts: -------------------------------------------------------------------------------- 1 | // Main Novel Components 2 | export { default as NovelList } from './novel-list'; 3 | export { default as NovelListNavbar } from './novel-list-navbar'; 4 | -------------------------------------------------------------------------------- /apps/web/src/features/modals/edit-modals/index.ts: -------------------------------------------------------------------------------- 1 | // Edit Modals 2 | export { default as ReadEditModal } from './read-edit-modal'; 3 | export { default as WatchEditModal } from './watch-edit-modal'; 4 | -------------------------------------------------------------------------------- /packages/react/types/related.ts: -------------------------------------------------------------------------------- 1 | import { RelatedContentType } from '@hikka/client'; 2 | 3 | export interface UseFranchiseParams { 4 | contentType: RelatedContentType; 5 | slug: string; 6 | } 7 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | 'postcss-import': {}, 4 | 'tailwindcss/nesting': {}, 5 | tailwindcss: {}, 6 | autoprefixer: {}, 7 | } 8 | } -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | Dockerfile.prod 2 | .dockerignore 3 | node_modules 4 | npm-debug.log 5 | README.md 6 | .next 7 | !.next/static 8 | !.next/standalone 9 | .git 10 | .github 11 | .vscode 12 | .yarn 13 | -------------------------------------------------------------------------------- /apps/web/src/features/modals/utility-modals/index.ts: -------------------------------------------------------------------------------- 1 | // Utility Modals 2 | export { default as CropEditorModal } from './crop-editor-modal'; 3 | export { default as SearchModal } from './search-modal/search-modal'; 4 | -------------------------------------------------------------------------------- /apps/web/src/components/plate/editor/plugins/basic-marks-base-kit.tsx: -------------------------------------------------------------------------------- 1 | import { BaseBoldPlugin, BaseItalicPlugin } from '@platejs/basic-nodes'; 2 | 3 | export const BaseBasicMarksKit = [BaseBoldPlugin, BaseItalicPlugin]; 4 | -------------------------------------------------------------------------------- /apps/web/src/components/plate/editor/plugins/basic-marks-kit.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { BoldPlugin, ItalicPlugin } from '@platejs/basic-nodes/react'; 4 | 5 | export const BasicMarksKit = [BoldPlugin, ItalicPlugin]; 6 | -------------------------------------------------------------------------------- /apps/web/src/features/anime/index.ts: -------------------------------------------------------------------------------- 1 | export { default as AnimeList } from './anime-list'; 2 | export { default as AnimeListNavbar } from './anime-list-navbar'; 3 | export { default as MovieBanner } from './movie-banner'; 4 | -------------------------------------------------------------------------------- /packages/client/index.ts: -------------------------------------------------------------------------------- 1 | // Main entry point that re-exports everything 2 | export * from './client'; 3 | export * from './constants'; 4 | export * from './errors'; 5 | export * from './modules'; 6 | export * from './types'; 7 | -------------------------------------------------------------------------------- /apps/web/src/components/ui/aspect-ratio.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import * as AspectRatioPrimitive from '@radix-ui/react-aspect-ratio'; 4 | 5 | const AspectRatio = AspectRatioPrimitive.Root; 6 | 7 | export { AspectRatio }; 8 | -------------------------------------------------------------------------------- /apps/web/src/features/modals/oauth-modals/index.ts: -------------------------------------------------------------------------------- 1 | // OAuth Modals 2 | export { default as ClientCreateModal } from './client-modal/client-create-modal'; 3 | export { default as ClientEditModal } from './client-modal/client-edit-modal'; 4 | -------------------------------------------------------------------------------- /packages/react/types/articles.ts: -------------------------------------------------------------------------------- 1 | import { ArticlesListArgs } from '@hikka/client'; 2 | 3 | export interface UseArticleParams { 4 | slug: string; 5 | } 6 | export interface UseArticlesListParams { 7 | args?: ArticlesListArgs; 8 | } 9 | -------------------------------------------------------------------------------- /apps/web/.env.production: -------------------------------------------------------------------------------- 1 | NEXT_PUBLIC_API_URL=https://api.hikka.io 2 | API_URL=http://backend:8000 3 | SITE_URL=https://hikka.io 4 | NEXT_PUBLIC_SITE_URL=https://hikka.io 5 | COOKIE_HTTP_ONLY=true 6 | COOKIE_DOMAIN=.hikka.io 7 | NEXT_PUBLIC_DEV=false 8 | -------------------------------------------------------------------------------- /apps/web/src/app/(pages)/(user)/settings/page.tsx: -------------------------------------------------------------------------------- 1 | import { permanentRedirect } from 'next/navigation'; 2 | 3 | const SettingsPage = async () => { 4 | return permanentRedirect('settings/profile'); 5 | }; 6 | 7 | export default SettingsPage; 8 | -------------------------------------------------------------------------------- /apps/web/.env.development: -------------------------------------------------------------------------------- 1 | NEXT_PUBLIC_API_URL=https://api.hikka.io 2 | API_URL=https://api.hikka.io 3 | SITE_URL=http://localhost:3000 4 | NEXT_PUBLIC_SITE_URL=http://localhost:3000 5 | COOKIE_HTTP_ONLY=false 6 | COOKIE_DOMAIN=localhost 7 | NEXT_PUBLIC_DEV=true -------------------------------------------------------------------------------- /packages/client/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "extends": ["../../.eslintrc.json"], 4 | "parserOptions": { 5 | "project": "./tsconfig.json" 6 | }, 7 | "ignorePatterns": ["dist/", "node_modules/"], 8 | "rules": {} 9 | } 10 | -------------------------------------------------------------------------------- /apps/web/src/components/plate/editor/plugins/basic-nodes-kit.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { BasicBlocksKit } from './basic-blocks-kit'; 4 | import { BasicMarksKit } from './basic-marks-kit'; 5 | 6 | export const BasicNodesKit = [...BasicBlocksKit, ...BasicMarksKit]; 7 | -------------------------------------------------------------------------------- /packages/react/types/collections.ts: -------------------------------------------------------------------------------- 1 | import { CollectionsListArgs } from '@hikka/client'; 2 | 3 | export interface UseCollectionParams { 4 | reference: string; 5 | } 6 | 7 | export interface UseCollectionsListParams { 8 | args: CollectionsListArgs; 9 | } 10 | -------------------------------------------------------------------------------- /packages/react/types/auth.ts: -------------------------------------------------------------------------------- 1 | import { PaginationArgs } from '@hikka/client'; 2 | 3 | export interface UseOAuthProviderUrlParams { 4 | provider: string; 5 | } 6 | 7 | export interface UseThirdPartyTokenListParams { 8 | paginationArgs?: PaginationArgs; 9 | } 10 | -------------------------------------------------------------------------------- /apps/web/src/components/plate/editor/plugins/link-base-kit.tsx: -------------------------------------------------------------------------------- 1 | import { BaseLinkPlugin } from '@platejs/link'; 2 | 3 | import { LinkElementStatic } from '@/components/plate/ui/link-node-static'; 4 | 5 | export const BaseLinkKit = [BaseLinkPlugin.withComponent(LinkElementStatic)]; 6 | -------------------------------------------------------------------------------- /apps/web/src/features/oauth/index.ts: -------------------------------------------------------------------------------- 1 | // OAuth Components 2 | export { default as OAuthClient } from './client'; 3 | export { default as OAuthConfirm } from './confirm'; 4 | export { default as OAuthHeader } from './oauth-header'; 5 | export { default as OAuthProfile } from './profile'; 6 | -------------------------------------------------------------------------------- /packages/react/client/provider/context.ts: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { createContext } from 'react'; 4 | 5 | import { HikkaProviderValue } from './HikkaProvider'; 6 | 7 | export const HikkaContext = createContext( 8 | undefined, 9 | ); 10 | -------------------------------------------------------------------------------- /apps/web/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | import "./.next/dev/types/routes.d.ts"; 4 | 5 | // NOTE: This file should not be edited 6 | // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. 7 | -------------------------------------------------------------------------------- /apps/web/src/types/index.d.ts: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | declare global { 4 | namespace JSX { 5 | interface IntrinsicElements { 6 | spoiler: { children: ReactNode }; 7 | div: { children: ReactNode }; 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /apps/web/src/features/modals/index.ts: -------------------------------------------------------------------------------- 1 | // Re-export modal groups (for organized access) 2 | export * from './edit-modals'; 3 | export * from './filter-modals'; 4 | export * from './filter-preset-modal'; 5 | export * from './oauth-modals'; 6 | export * from './user-modals'; 7 | export * from './utility-modals'; 8 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.snippetSuggestions": "top", 3 | "editor.formatOnSave": true, 4 | "editor.codeActionsOnSave": { 5 | "source.organizeImports": "explicit" 6 | }, 7 | "eslint.workingDirectories": [ 8 | { 9 | "mode": "auto" 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /packages/react/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": false, 3 | "extends": ["../../.eslintrc.json"], 4 | "parserOptions": { 5 | "project": "./tsconfig.json" 6 | }, 7 | "ignorePatterns": ["dist/", "node_modules/"], 8 | "rules": { 9 | "@tanstack/query/exhaustive-deps": "off" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /apps/web/src/components/markdown/viewer/components/no-spoiler.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | interface Props { 4 | children: ReactNode; 5 | } 6 | 7 | const NoSpoiler = ({ children }: Props) => { 8 | return {children}; 9 | }; 10 | 11 | export default NoSpoiler; 12 | -------------------------------------------------------------------------------- /apps/web/src/utils/get-api-error-message.ts: -------------------------------------------------------------------------------- 1 | import { ERRORS } from './constants/common'; 2 | 3 | export default function getApiErrorMessage(error: any) { 4 | const splittedCode = error.code.split(':'); 5 | 6 | if (splittedCode.length === 2) { 7 | return ERRORS[splittedCode[0]][splittedCode[1]]; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/react/types/manga.ts: -------------------------------------------------------------------------------- 1 | import { MangaSearchArgs } from '@hikka/client'; 2 | 3 | export interface UseMangaInfoParams { 4 | slug: string; 5 | } 6 | 7 | export interface UseMangaCharactersParams { 8 | slug: string; 9 | } 10 | 11 | export interface UseSearchMangasParams { 12 | args: MangaSearchArgs; 13 | } 14 | -------------------------------------------------------------------------------- /packages/react/types/novel.ts: -------------------------------------------------------------------------------- 1 | import { NovelSearchArgs } from '@hikka/client'; 2 | 3 | export interface UseNovelInfoParams { 4 | slug: string; 5 | } 6 | 7 | export interface UseNovelCharactersParams { 8 | slug: string; 9 | } 10 | 11 | export interface UseSearchNovelsParams { 12 | args: NovelSearchArgs; 13 | } 14 | -------------------------------------------------------------------------------- /packages/react/types/vote.ts: -------------------------------------------------------------------------------- 1 | import { VoteContentType } from '@hikka/client'; 2 | 3 | export interface UseVoteStatusParams { 4 | contentType: VoteContentType; 5 | slug: string; 6 | } 7 | 8 | export interface UseVoteMutationParams { 9 | contentType: VoteContentType; 10 | slug: string; 11 | score: number; 12 | } 13 | -------------------------------------------------------------------------------- /packages/react/jest.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'jsdom', 4 | setupFilesAfterEnv: ['/setupTests.ts'], 5 | testMatch: ['**/__tests__/**/*.test.ts?(x)'], 6 | transform: { 7 | '^.+\\.(ts|tsx)$': ['ts-jest', { 8 | tsconfig: 'tsconfig.json', 9 | }], 10 | }, 11 | }; -------------------------------------------------------------------------------- /packages/react/types/favourite.ts: -------------------------------------------------------------------------------- 1 | import { FavouriteContentType } from '@hikka/client'; 2 | 3 | export interface UseFavouriteStatusParams { 4 | contentType: FavouriteContentType; 5 | slug: string; 6 | } 7 | 8 | export interface UseFavouriteListParams { 9 | contentType: FavouriteContentType; 10 | username: string; 11 | } 12 | -------------------------------------------------------------------------------- /apps/web/src/features/modals/filter-preset-modal/index.ts: -------------------------------------------------------------------------------- 1 | export { default as FilterPresetButton } from './filter-preset-button'; 2 | export { default as FilterPresetEditModal } from './filter-preset-edit-modal'; 3 | export { default as FilterPresetModal } from './filter-preset-modal'; 4 | export { default as FilterPresets } from './filter-presets'; 5 | -------------------------------------------------------------------------------- /packages/react/types/edit.ts: -------------------------------------------------------------------------------- 1 | import { GetEditListArgs, TodoEditArgs } from '@hikka/client'; 2 | 3 | export interface UseEditParams { 4 | editId: number | string; 5 | } 6 | 7 | export interface UseEditListParams { 8 | args?: GetEditListArgs; 9 | } 10 | 11 | export interface UseTodoEditListParams { 12 | args: TodoEditArgs; 13 | } 14 | -------------------------------------------------------------------------------- /packages/react/types/follow.ts: -------------------------------------------------------------------------------- 1 | export interface UseFollowStatusParams { 2 | username: string; 3 | } 4 | 5 | export interface UseFollowersParams { 6 | username: string; 7 | } 8 | 9 | export interface UseFollowingsParams { 10 | username: string; 11 | } 12 | 13 | export interface UseFollowStatsParams { 14 | username: string; 15 | } 16 | -------------------------------------------------------------------------------- /apps/web/src/app/(api)/auth/reset/[token]/route.ts: -------------------------------------------------------------------------------- 1 | import { redirect } from 'next/navigation'; 2 | 3 | export async function GET( 4 | request: Request, 5 | props: { params: Promise<{ token: string }> }, 6 | ) { 7 | const params = await props.params; 8 | 9 | const { token } = params; 10 | 11 | return redirect('/reset/' + token); 12 | } 13 | -------------------------------------------------------------------------------- /packages/client/types/upload.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Upload related types 3 | */ 4 | 5 | /** 6 | * Upload type enum 7 | */ 8 | export enum UploadTypeEnum { 9 | ATTACHMENT = 'attachment', 10 | AVATAR = 'avatar', 11 | COVER = 'cover', 12 | } 13 | 14 | /** 15 | * Image response 16 | */ 17 | export interface ImageResponse { 18 | url: string; 19 | } 20 | -------------------------------------------------------------------------------- /apps/web/src/components/typography/li.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | import { cn } from '@/utils/utils'; 4 | 5 | interface Props { 6 | children: ReactNode | string; 7 | className?: string; 8 | } 9 | 10 | export default function Li({ children, className }: Props) { 11 | return
  • {children}
  • ; 12 | } 13 | -------------------------------------------------------------------------------- /apps/web/src/features/users/user-profile/index.ts: -------------------------------------------------------------------------------- 1 | export { default as UserArticles } from './user-articles'; 2 | export { default as UserCollections } from './user-collections'; 3 | export { default as UserFavorites } from './user-favorites'; 4 | export { default as UserHistoryProfile } from './user-history'; 5 | export { default as UserStatistics } from './user-statistics'; 6 | -------------------------------------------------------------------------------- /apps/web/src/components/plate/editor/plugins/exit-break-kit.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { ExitBreakPlugin } from 'platejs'; 4 | 5 | export const ExitBreakKit = [ 6 | ExitBreakPlugin.configure({ 7 | shortcuts: { 8 | insert: { keys: 'mod+enter' }, 9 | insertBefore: { keys: 'mod+shift+enter' }, 10 | }, 11 | }), 12 | ]; 13 | -------------------------------------------------------------------------------- /apps/web/src/features/comments/index.ts: -------------------------------------------------------------------------------- 1 | // Comment Components 2 | export { default as CommentList } from './comment-list'; 3 | export { default as LatestComments } from './latest-comments'; 4 | 5 | // Comment Hooks 6 | export { useContent } from './hooks/use-content'; 7 | 8 | // Comment Utils 9 | export { default as prefetchContent } from './utils/prefetch-content'; 10 | -------------------------------------------------------------------------------- /apps/web/src/features/people/index.ts: -------------------------------------------------------------------------------- 1 | // Person Components 2 | export { default as PersonAnime } from './anime'; 3 | export { default as PersonCharacters } from './characters'; 4 | export { default as PersonCover } from './cover'; 5 | export { default as PersonManga } from './manga'; 6 | export { default as PersonNovel } from './novel'; 7 | export { default as PersonTitle } from './title'; 8 | -------------------------------------------------------------------------------- /apps/web/src/services/providers/theme-provider.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { 4 | ThemeProvider as NextThemesProvider, 5 | ThemeProviderProps, 6 | } from 'next-themes'; 7 | 8 | export default function ThemeProvider({ 9 | children, 10 | ...props 11 | }: ThemeProviderProps) { 12 | return {children}; 13 | } 14 | -------------------------------------------------------------------------------- /apps/web/src/features/modals/user-modals/index.ts: -------------------------------------------------------------------------------- 1 | // User Modals 2 | export { default as EditTopStatsModal } from './edit-top-stats-modal'; 3 | export { default as EditListModal } from './editlist-modal'; 4 | export { default as Followings } from './followings'; 5 | export { default as FollowingsModal } from './followings-modal'; 6 | export { default as FollowListModal } from './followlist-modal'; 7 | -------------------------------------------------------------------------------- /apps/web/src/components/ui/skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from '@/utils/utils'; 2 | 3 | function Skeleton({ 4 | className, 5 | ...props 6 | }: React.HTMLAttributes) { 7 | return ( 8 |
    12 | ); 13 | } 14 | 15 | export { Skeleton }; 16 | -------------------------------------------------------------------------------- /packages/react/types/characters.ts: -------------------------------------------------------------------------------- 1 | import { PaginationArgs, QuerySearchArgs } from '@hikka/client'; 2 | 3 | export interface UseCharacterInfoParams { 4 | slug: string; 5 | } 6 | 7 | export interface UseCharacterContentParams { 8 | slug: string; 9 | paginationArgs?: PaginationArgs; 10 | } 11 | 12 | export interface UseCharactersSearchParams { 13 | args?: QuerySearchArgs; 14 | } 15 | -------------------------------------------------------------------------------- /apps/web/src/features/collections/collection-view/index.ts: -------------------------------------------------------------------------------- 1 | export { default as CollectionViewAuthor } from './collection-author'; 2 | export { default as CollectionViewGroups } from './collection-groups'; 3 | export { default as CollectionViewNavbar } from './collection-navbar'; 4 | export { default as CollectionViewTitle } from './collection-title'; 5 | export { default as TableOfContents } from './table-of-contents'; 6 | -------------------------------------------------------------------------------- /apps/web/src/features/users/userlist/index.ts: -------------------------------------------------------------------------------- 1 | // User Readlist Components 2 | export { default as UserlistHeader } from './components/userlist-header'; 3 | export { default as UserlistStatusCombobox } from './status-combobox'; 4 | export { default as UserlistToolsCombobox } from './tools-combobox'; 5 | export { default as Userlist } from './userlist'; 6 | export { default as UserlistViewCombobox } from './view-combobox'; 7 | -------------------------------------------------------------------------------- /apps/web/src/components/ui/collapsible.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import * as CollapsiblePrimitive from '@radix-ui/react-collapsible'; 4 | 5 | const Collapsible = CollapsiblePrimitive.Root; 6 | 7 | const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger; 8 | 9 | const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent; 10 | 11 | export { Collapsible, CollapsibleContent, CollapsibleTrigger }; 12 | -------------------------------------------------------------------------------- /apps/web/.gitignore: -------------------------------------------------------------------------------- 1 | # Next.js 2 | .next 3 | out 4 | build 5 | .next-env.d.ts 6 | *.tsbuildinfo 7 | 8 | # Docker 9 | .dockerignore 10 | Dockerfile* 11 | docker-compose* 12 | 13 | # Dependencies 14 | node_modules 15 | .yarn 16 | .pnp 17 | .pnp.js 18 | 19 | # Testing 20 | coverage 21 | 22 | # Debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | .pnpm-debug.log* 27 | 28 | # Misc 29 | .DS_Store 30 | *.pem -------------------------------------------------------------------------------- /apps/web/src/components/typography/large.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | import { cn } from '@/utils/utils'; 4 | 5 | interface Props { 6 | children: ReactNode | string; 7 | className?: string; 8 | } 9 | 10 | export default function Large({ children, className }: Props) { 11 | return ( 12 |
    {children}
    13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /apps/web/src/components/typography/p.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | import { cn } from '@/utils/utils'; 4 | 5 | interface Props { 6 | children?: ReactNode | string; 7 | className?: string; 8 | } 9 | 10 | export const P_CLASSNAME = 'break-words'; 11 | 12 | export default function P({ children, className }: Props) { 13 | return

    {children}

    ; 14 | } 15 | -------------------------------------------------------------------------------- /apps/web/src/features/collections/collection-edit/index.ts: -------------------------------------------------------------------------------- 1 | export { default as CollectionEditGrid } from './collection-grid'; 2 | export { default as CollectionEditGroups } from './collection-groups'; 3 | export { default as CollectionEditRulesAlert } from './collection-rules-alert'; 4 | export { default as CollectionEditSettings } from './collection-settings'; 5 | export { default as CollectionEditTitle } from './collection-title'; 6 | -------------------------------------------------------------------------------- /apps/web/src/features/modals/filter-modals/index.ts: -------------------------------------------------------------------------------- 1 | // Filter Modals 2 | export { default as AnimeFiltersModal } from './anime-filters-modal'; 3 | export { default as ArticleFiltersModal } from './article-filters-modal'; 4 | export { default as EditFiltersModal } from './edit-filters-modal'; 5 | export { default as ReadFiltersModal } from './read-filters-modal'; 6 | export { default as ScheduleFiltersModal } from './schedule-filters-modal'; 7 | -------------------------------------------------------------------------------- /apps/web/src/features/common/scroll-top.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { usePathname } from 'next/navigation'; 4 | import { useEffect } from 'react'; 5 | 6 | const ScrollTop = () => { 7 | const pathname = usePathname(); 8 | 9 | useEffect(() => { 10 | if (window && window.location.hash.length === 0) window.scroll(0, 0); 11 | }, [pathname]); 12 | 13 | return null; 14 | }; 15 | 16 | export default ScrollTop; 17 | -------------------------------------------------------------------------------- /apps/web/src/components/typography/ul.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | import { cn } from '@/utils/utils'; 4 | 5 | interface Props { 6 | children: ReactNode | string; 7 | className?: string; 8 | } 9 | 10 | export const UL_CLASSNAME = 'ml-6 list-disc [&>li]:mt-2'; 11 | 12 | export default function Ul({ children, className }: Props) { 13 | return
      {children}
    ; 14 | } 15 | -------------------------------------------------------------------------------- /apps/web/src/features/characters/index.ts: -------------------------------------------------------------------------------- 1 | export { default as CharacterAnime } from './anime'; 2 | export { default as CharacterCover } from './cover'; 3 | export { default as CharacterDescription } from './description'; 4 | export { default as CharacterManga } from './manga'; 5 | export { default as CharacterNovel } from './novel'; 6 | export { default as CharacterTitle } from './title'; 7 | export { default as CharacterVoices } from './voices'; 8 | -------------------------------------------------------------------------------- /apps/web/src/components/typography/ol.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | import { cn } from '@/utils/utils'; 4 | 5 | interface Props { 6 | children: ReactNode | string; 7 | className?: string; 8 | } 9 | 10 | export const OL_CLASSNAME = 'ml-6 list-decimal [&>li]:mt-2'; 11 | 12 | export default function Ol({ children, className }: Props) { 13 | return
      {children}
    ; 14 | } 15 | -------------------------------------------------------------------------------- /apps/web/src/components/typography/lead.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | import { cn } from '@/utils/utils'; 4 | 5 | interface Props { 6 | children: ReactNode | string; 7 | className?: string; 8 | } 9 | 10 | export default function Lead({ children, className }: Props) { 11 | return ( 12 |

    13 | {children} 14 |

    15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /apps/web/src/features/home/index.ts: -------------------------------------------------------------------------------- 1 | // Home Components 2 | export { default as HomeArticles } from './articles'; 3 | export { default as HomeCollections } from './collections'; 4 | export { default as HomeComments } from './comments'; 5 | export { default as HomeHistory } from './history'; 6 | export { default as HomeOngoings } from './ongoings'; 7 | export { default as HomeProfile } from './profile'; 8 | export { default as HomeSchedule } from './schedule'; 9 | -------------------------------------------------------------------------------- /apps/web/src/components/typography/muted.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | import { cn } from '@/utils/utils'; 4 | 5 | interface Props { 6 | children: ReactNode | string; 7 | className?: string; 8 | } 9 | 10 | export default function Muted({ children, className }: Props) { 11 | return ( 12 |

    13 | {children} 14 |

    15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /apps/web/src/components/typography/small.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | import { cn } from '@/utils/utils'; 4 | 5 | interface Props { 6 | children: ReactNode | string; 7 | className?: string; 8 | } 9 | 10 | export default function Small({ children, className }: Props) { 11 | return ( 12 | 13 | {children} 14 | 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /apps/web/src/features/filters/index.ts: -------------------------------------------------------------------------------- 1 | // Filter Components 2 | export { default as AnimeFilters } from './anime-filters'; 3 | export { default as ArticleFilters } from './article-filters'; 4 | export { default as EditFilters } from './edit-filters'; 5 | export { default as ReadFilters } from './read-filters'; 6 | export { default as ScheduleFilters } from './schedule-filters'; 7 | 8 | // Filter Hooks 9 | export { default as useChangeParam } from './hooks/use-change-param'; 10 | -------------------------------------------------------------------------------- /apps/web/src/components/plate/editor/plugins/emoji-kit.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import emojiMartData from '@emoji-mart/data'; 4 | import { EmojiInputPlugin, EmojiPlugin } from '@platejs/emoji/react'; 5 | 6 | import { EmojiInputElement } from '@/components/plate/ui/emoji-node'; 7 | 8 | export const EmojiKit = [ 9 | EmojiPlugin.configure({ 10 | options: { data: emojiMartData as any }, 11 | }), 12 | EmojiInputPlugin.withComponent(EmojiInputElement), 13 | ]; 14 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/iconamoon/IconamoonSignDivisionSlashThin.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function IconamoonSignDivisionSlashThin(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default IconamoonSignDivisionSlashThin -------------------------------------------------------------------------------- /apps/web/src/components/typography/h3.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | import { cn } from '@/utils/utils'; 4 | 5 | interface Props { 6 | children: ReactNode | string; 7 | className?: string; 8 | } 9 | 10 | export const H3_CLASSNAME = 11 | 'scroll-m-20 font-display text-lg font-bold tracking-normal'; 12 | 13 | export default function H3({ children, className }: Props) { 14 | return

    {children}

    ; 15 | } 16 | -------------------------------------------------------------------------------- /apps/web/src/components/typography/h4.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | import { cn } from '@/utils/utils'; 4 | 5 | interface Props { 6 | children: ReactNode | string; 7 | className?: string; 8 | } 9 | 10 | export const H4_CLASSNAME = 11 | 'scroll-m-20 font-display text-base font-bold tracking-normal'; 12 | 13 | export default function H4({ children, className }: Props) { 14 | return

    {children}

    ; 15 | } 16 | -------------------------------------------------------------------------------- /apps/web/src/components/typography/h5.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | import { cn } from '@/utils/utils'; 4 | 5 | interface Props { 6 | children: ReactNode | string; 7 | className?: string; 8 | } 9 | 10 | export const H5_CLASSNAME = 11 | 'scroll-m-20 font-display text-base font-bold tracking-normal'; 12 | 13 | export default function H5({ children, className }: Props) { 14 | return
    {children}
    ; 15 | } 16 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/bx/BxBxsUpvote.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function BxBxsUpvote(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default BxBxsUpvote -------------------------------------------------------------------------------- /apps/web/src/components/icons/fe/FeMention.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function FeMention(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default FeMention -------------------------------------------------------------------------------- /apps/web/src/components/icons/fe/FeRandom.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function FeRandom(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default FeRandom -------------------------------------------------------------------------------- /apps/web/src/components/ui/block.tsx: -------------------------------------------------------------------------------- 1 | import { ComponentPropsWithoutRef, memo } from 'react'; 2 | 3 | import { cn } from '@/utils/utils'; 4 | 5 | interface Props extends ComponentPropsWithoutRef<'section'> {} 6 | 7 | const Block = ({ children, className, ...props }: Props) => { 8 | return ( 9 |
    10 | {children} 11 |
    12 | ); 13 | }; 14 | 15 | export default memo(Block); 16 | -------------------------------------------------------------------------------- /apps/web/src/features/users/userlist/components/table-view/volumes-cell.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react'; 2 | 3 | import { TableCell } from '@/components/ui/table'; 4 | 5 | interface Props { 6 | volumes: number; 7 | total?: number | null; 8 | } 9 | 10 | const VolumesCell: FC = ({ volumes, total }) => ( 11 | 12 | {volumes} / {total || '?'} 13 | 14 | ); 15 | 16 | export default VolumesCell; 17 | -------------------------------------------------------------------------------- /apps/web/src/components/typography/h1.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | import { cn } from '@/utils/utils'; 4 | 5 | interface Props { 6 | children: ReactNode | string; 7 | className?: string; 8 | } 9 | 10 | export const H1_CLASSNAME = 11 | 'scroll-m-20 font-display text-4xl font-bold tracking-normal lg:text-5xl'; 12 | 13 | export default function H1({ children, className }: Props) { 14 | return

    {children}

    ; 15 | } 16 | -------------------------------------------------------------------------------- /apps/web/src/components/typography/h2.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | import { cn } from '@/utils/utils'; 4 | 5 | interface Props { 6 | children: ReactNode | string; 7 | className?: string; 8 | } 9 | 10 | export const H2_CLASSNAME = 11 | 'scroll-m-20 font-display text-2xl font-bold tracking-normal first:mt-0'; 12 | 13 | export default function H2({ children, className }: Props) { 14 | return

    {children}

    ; 15 | } 16 | -------------------------------------------------------------------------------- /apps/web/src/features/users/userlist/components/table-view/chapters-cell.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react'; 2 | 3 | import { TableCell } from '@/components/ui/table'; 4 | 5 | interface Props { 6 | chapters: number; 7 | total?: number | null; 8 | } 9 | 10 | const ChaptersCell: FC = ({ chapters, total }) => ( 11 | 12 | {chapters} / {total || '?'} 13 | 14 | ); 15 | 16 | export default ChaptersCell; 17 | -------------------------------------------------------------------------------- /apps/web/src/features/users/userlist/components/table-view/episodes-cell.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react'; 2 | 3 | import { TableCell } from '@/components/ui/table'; 4 | 5 | interface Props { 6 | episodes: number; 7 | total?: number | null; 8 | } 9 | 10 | const EpisodesCell: FC = ({ episodes, total }) => ( 11 | 12 | {episodes} / {total || '?'} 13 | 14 | ); 15 | 16 | export default EpisodesCell; 17 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsRemoveRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsRemoveRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsRemoveRounded -------------------------------------------------------------------------------- /apps/web/src/components/plate/editor/plugins/link-kit.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { LinkPlugin } from '@platejs/link/react'; 4 | 5 | import { LinkElement } from '@/components/plate/ui/link-node'; 6 | import { LinkFloatingToolbar } from '@/components/plate/ui/link-toolbar'; 7 | 8 | export const LinkKit = [ 9 | LinkPlugin.configure({ 10 | render: { 11 | node: LinkElement, 12 | afterEditable: () => , 13 | }, 14 | }), 15 | ]; 16 | -------------------------------------------------------------------------------- /apps/web/src/utils/constants/banners.ts: -------------------------------------------------------------------------------- 1 | type MovieBanner = { 2 | slug: string; 3 | title: string; 4 | description: string; 5 | image?: string; 6 | duration: [number, number]; 7 | }; 8 | 9 | export const MOVIE_BANNERS: MovieBanner[] = [ 10 | { 11 | slug: 'chainsaw-man-movie-reze-hen-c4febd', 12 | title: 'Вже ходили до кінотеатру?', 13 | description: 'Поділіться своїми враженнями!', 14 | duration: [1761166800, 1762387200], 15 | }, 16 | ]; 17 | -------------------------------------------------------------------------------- /apps/web/src/utils/truncate-text.ts: -------------------------------------------------------------------------------- 1 | export default function truncateText( 2 | str: string, 3 | n: number, 4 | useWordBoundary: boolean, 5 | ) { 6 | if (!str) return null; 7 | 8 | if (str.length <= n) { 9 | return str; 10 | } 11 | const subString = str.slice(0, n - 1); // the original check 12 | return ( 13 | (useWordBoundary 14 | ? subString.slice(0, subString.lastIndexOf(' ')) 15 | : subString) + '…' 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /packages/client/types/stats.ts: -------------------------------------------------------------------------------- 1 | import { PaginationResponse } from './common'; 2 | import { UserResponse } from './user'; 3 | 4 | /** 5 | * Edits top response 6 | */ 7 | export interface EditsTopResponse { 8 | user: UserResponse; 9 | accepted: number; 10 | closed: number; 11 | denied: number; 12 | } 13 | 14 | /** 15 | * Paginated edits top response 16 | */ 17 | export interface EditsTopPaginationResponse { 18 | pagination: PaginationResponse; 19 | list: EditsTopResponse[]; 20 | } 21 | -------------------------------------------------------------------------------- /apps/web/src/components/plate/editor/plugins/image-base-kit.tsx: -------------------------------------------------------------------------------- 1 | import { createSlatePlugin } from 'platejs'; 2 | 3 | import { ImageElementStatic } from '@/components/plate/ui/image-node-static'; 4 | 5 | export const ELEMENT_IMAGE = 'image'; 6 | 7 | export const BaseImagePlugin = createSlatePlugin({ 8 | key: ELEMENT_IMAGE, 9 | node: { 10 | isElement: true, 11 | isVoid: true, 12 | }, 13 | }); 14 | 15 | export const BaseImageKit = [BaseImagePlugin.withComponent(ImageElementStatic)]; 16 | -------------------------------------------------------------------------------- /apps/web/src/components/plate/editor/plugins/video-base-kit.tsx: -------------------------------------------------------------------------------- 1 | import { createSlatePlugin } from 'platejs'; 2 | 3 | import { VideoElementStatic } from '@/components/plate/ui/video-node-static'; 4 | 5 | export const ELEMENT_VIDEO = 'video'; 6 | 7 | export const BaseVideoPlugin = createSlatePlugin({ 8 | key: ELEMENT_VIDEO, 9 | node: { 10 | isElement: true, 11 | isVoid: true, 12 | }, 13 | }); 14 | 15 | export const BaseVideoKit = [BaseVideoPlugin.withComponent(VideoElementStatic)]; 16 | -------------------------------------------------------------------------------- /apps/web/src/features/anime/components/anime-list-skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { range } from '@antfu/utils'; 2 | 3 | import SkeletonCard from '@/components/content-card/content-card-skeleton'; 4 | 5 | const AnimeListSkeleton = () => { 6 | return ( 7 |
    8 | {range(1, 20).map((v) => ( 9 | 10 | ))} 11 |
    12 | ); 13 | }; 14 | 15 | export default AnimeListSkeleton; 16 | -------------------------------------------------------------------------------- /apps/web/src/features/manga/components/manga-list-skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { range } from '@antfu/utils'; 2 | 3 | import SkeletonCard from '@/components/content-card/content-card-skeleton'; 4 | 5 | const MangaListSkeleton = () => { 6 | return ( 7 |
    8 | {range(1, 20).map((v) => ( 9 | 10 | ))} 11 |
    12 | ); 13 | }; 14 | 15 | export default MangaListSkeleton; 16 | -------------------------------------------------------------------------------- /apps/web/src/features/novel/components/novel-list-skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { range } from '@antfu/utils'; 2 | 3 | import SkeletonCard from '@/components/content-card/content-card-skeleton'; 4 | 5 | const NovelListSkeleton = () => { 6 | return ( 7 |
    8 | {range(1, 20).map((v) => ( 9 | 10 | ))} 11 |
    12 | ); 13 | }; 14 | 15 | export default NovelListSkeleton; 16 | -------------------------------------------------------------------------------- /apps/web/src/utils/zod.ts: -------------------------------------------------------------------------------- 1 | import i18next from 'i18next'; 2 | import { z } from 'zod'; 3 | import { zodI18nMap } from 'zod-i18n-map'; 4 | // Import your language translation files 5 | import translation from 'zod-i18n-map/locales/uk-UA/zod.json'; 6 | 7 | // lng and resources key depend on your locale. 8 | i18next.init({ 9 | lng: 'uk', 10 | resources: { 11 | uk: { zod: translation }, 12 | }, 13 | }); 14 | z.setErrorMap(zodI18nMap); 15 | 16 | // export configured zod instance 17 | export { z }; 18 | -------------------------------------------------------------------------------- /packages/client/modules/genres.ts: -------------------------------------------------------------------------------- 1 | import { BaseRequestOptionsArgs, GenreListResponse } from '../types'; 2 | import { BaseModule } from './base'; 3 | 4 | /** 5 | * Module for handling genres 6 | */ 7 | export class GenresModule extends BaseModule { 8 | /** 9 | * Get all genres 10 | */ 11 | public async getGenres( 12 | options?: BaseRequestOptionsArgs, 13 | ): Promise { 14 | return this.client.get('/genres', options); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /apps/web/src/app/(pages)/(user)/settings/layout.metadata.ts: -------------------------------------------------------------------------------- 1 | import { Metadata } from 'next'; 2 | 3 | import _generateMetadata from '@/utils/generate-metadata'; 4 | 5 | export interface MetadataProps { 6 | searchParams: { [key: string]: string | string[] | undefined }; 7 | } 8 | 9 | export default async function generateMetadata(): Promise { 10 | return _generateMetadata({ 11 | title: 'Налаштування', 12 | robots: { 13 | index: false, 14 | }, 15 | }); 16 | } 17 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/bx/BxBxsDownvote.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function BxBxsDownvote(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default BxBxsDownvote -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsBookmarkOutline.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsBookmarkOutline(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsBookmarkOutline -------------------------------------------------------------------------------- /packages/client/errors.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Error class for Hikka API errors 3 | */ 4 | export class HikkaApiError extends Error { 5 | constructor( 6 | message: string, 7 | public status: number, 8 | public code: string, 9 | public data?: any, 10 | ) { 11 | super(message); 12 | this.name = 'HikkaApiError'; 13 | 14 | // This line is needed for proper inheritance in TypeScript 15 | Object.setPrototypeOf(this, HikkaApiError.prototype); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "module": "esnext", 5 | "outDir": "./dist", 6 | "rootDir": ".", 7 | "composite": true 8 | }, 9 | "include": [ 10 | "index.ts", 11 | "client.ts", 12 | "constants.ts", 13 | "errors.ts", 14 | "modules/**/*.ts", 15 | "types/**/*.ts" 16 | ], 17 | "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"] 18 | } 19 | -------------------------------------------------------------------------------- /packages/react/core/index.ts: -------------------------------------------------------------------------------- 1 | export * from './createHikkaClient'; 2 | export * from './createQueryClient'; 3 | export * from './queryKeys'; 4 | 5 | // Hikka client exports 6 | export * as HikkaClient from '@hikka/client'; 7 | 8 | // TanStack Query exports 9 | export { 10 | dehydrate, 11 | HydrationBoundary, 12 | MutationCache, 13 | QueryCache, 14 | QueryClient, 15 | useQueryClient, 16 | } from '@tanstack/react-query'; 17 | 18 | export type { QueryClientConfig } from '@tanstack/react-query'; 19 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/bx/BxUpvote.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function BxUpvote(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default BxUpvote -------------------------------------------------------------------------------- /apps/web/src/components/plate/editor/plugins/spoiler-base-kit.tsx: -------------------------------------------------------------------------------- 1 | import { createSlatePlugin } from 'platejs'; 2 | 3 | import { SpoilerElementStatic } from '@/components/plate/ui/spoiler-node-static'; 4 | 5 | export const ELEMENT_SPOILER = 'spoiler'; 6 | 7 | export const BaseSpoilerPlugin = createSlatePlugin({ 8 | key: ELEMENT_SPOILER, 9 | node: { 10 | isElement: true, 11 | }, 12 | }); 13 | 14 | export const BaseSpoilerKit = [ 15 | BaseSpoilerPlugin.withComponent(SpoilerElementStatic), 16 | ]; 17 | -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "module": "esnext", 5 | "moduleResolution": "bundler", 6 | "esModuleInterop": true, 7 | "strict": true, 8 | "skipLibCheck": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "isolatedModules": true, 11 | "resolveJsonModule": true, 12 | "declaration": true, 13 | "sourceMap": true, 14 | "lib": ["dom", "dom.iterable", "esnext"] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /apps/web/src/components/plate/ui/paragraph-node-static.tsx: -------------------------------------------------------------------------------- 1 | import type { SlateElementProps } from 'platejs/static'; 2 | import { SlateElement } from 'platejs/static'; 3 | 4 | import { P_CLASSNAME } from '@/components/typography/p'; 5 | 6 | import { cn } from '@/utils/utils'; 7 | 8 | export function ParagraphElementStatic(props: SlateElementProps) { 9 | return ( 10 | 11 | {props.children} 12 | 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/bx/BxDownvote.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function BxDownvote(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default BxDownvote -------------------------------------------------------------------------------- /apps/web/src/components/plate/ui/blockquote-node-static.tsx: -------------------------------------------------------------------------------- 1 | import { SlateElement, type SlateElementProps } from 'platejs/static'; 2 | 3 | import { BLOCKQUOTE_CLASSNAME } from '@/components/typography/blockquote'; 4 | 5 | import { cn } from '@/utils/utils'; 6 | 7 | export function BlockquoteElementStatic(props: SlateElementProps) { 8 | return ( 9 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsArticle.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsArticle(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsArticle -------------------------------------------------------------------------------- /apps/web/src/components/plate/ui/paragraph-node.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import type { PlateElementProps } from 'platejs/react'; 4 | import { PlateElement } from 'platejs/react'; 5 | 6 | import { P_CLASSNAME } from '@/components/typography/p'; 7 | 8 | import { cn } from '@/utils/utils'; 9 | 10 | export function ParagraphElement(props: PlateElementProps) { 11 | return ( 12 | 13 | {props.children} 14 | 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsCheckRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsCheckRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsCheckRounded -------------------------------------------------------------------------------- /apps/web/src/components/markdown/viewer/plugins/remark-disable-tokenizer.tsx: -------------------------------------------------------------------------------- 1 | export default function remarkDisableTokenizer() { 2 | // @ts-expect-error: TS is wrong about `this`. 3 | const self = /** @type {Processor} */ this; 4 | const data = self.data(); 5 | 6 | const micromarkExtensions = 7 | data.micromarkExtensions || (data.micromarkExtensions = []); 8 | 9 | micromarkExtensions.push({ 10 | disable: { 11 | null: ['codeIndented', 'codeFenced', 'codeText'], 12 | }, 13 | }); 14 | } 15 | -------------------------------------------------------------------------------- /apps/web/src/components/plate/ui/blockquote-node.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { PlateElement, type PlateElementProps } from 'platejs/react'; 4 | 5 | import { BLOCKQUOTE_CLASSNAME } from '@/components/typography/blockquote'; 6 | 7 | import { cn } from '@/utils/utils'; 8 | 9 | export function BlockquoteElement(props: PlateElementProps) { 10 | return ( 11 | 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /apps/web/src/components/typography/blockquote.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | import { cn } from '@/utils/utils'; 4 | 5 | interface Props { 6 | children: ReactNode | string; 7 | className?: string; 8 | } 9 | 10 | export const BLOCKQUOTE_CLASSNAME = 'border-l-2 pl-6 italic'; 11 | 12 | export default function Blockquote({ children, className }: Props) { 13 | return ( 14 |
    15 | {children} 16 |
    17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /apps/web/src/utils/adapters/convert-activity-stats.ts: -------------------------------------------------------------------------------- 1 | import { ActivityResponse } from '@hikka/client'; 2 | 3 | export const convertToDays = (data: ActivityResponse[]) => { 4 | if (data.length > 16) { 5 | return data.slice(data.length - 16, data.length); 6 | } 7 | 8 | if (data.length < 16) { 9 | const emplyArr = new Array(16 - data.length).fill({ 10 | actions: 0, 11 | timestamp: 0, 12 | }); 13 | return [...data, ...emplyArr]; 14 | } 15 | 16 | return data; 17 | }; 18 | -------------------------------------------------------------------------------- /apps/web/src/app/(pages)/(auth)/layout.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | import CoverImage from '@/components/cover-image'; 4 | 5 | interface AuthLayoutProps { 6 | children: ReactNode; 7 | } 8 | 9 | export default function AuthLayout({ children }: AuthLayoutProps) { 10 | return ( 11 |
    12 | 13 | {children} 14 |
    15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsSecurity.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsSecurity(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsSecurity -------------------------------------------------------------------------------- /packages/react/types/user.ts: -------------------------------------------------------------------------------- 1 | import { QuerySearchRequiredArgs, UserResponse } from '@hikka/client'; 2 | 3 | import { QueryParams } from '@/client/useQuery'; 4 | 5 | export interface UseUserByUsernameParams extends QueryParams { 6 | username: string; 7 | } 8 | 9 | export interface UseUserSearchParams { 10 | args: QuerySearchRequiredArgs; 11 | } 12 | 13 | export interface UseUserActivityParams { 14 | username: string; 15 | } 16 | 17 | // No parameters needed for useSession hook 18 | export interface UseSessionParams {} 19 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/ant-design/AntDesignFilterFilled.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function AntDesignFilterFilled(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default AntDesignFilterFilled -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsContentCopy.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsContentCopy(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsContentCopy -------------------------------------------------------------------------------- /apps/web/src/features/users/index.ts: -------------------------------------------------------------------------------- 1 | // Main User Components 2 | export { default as ActivationAlert } from './activation-alert'; 3 | export { default as FollowStats } from './follow-stats'; 4 | export { default as UserInfo } from './user-info'; 5 | export { default as UserTitle } from './user-title'; 6 | 7 | // User List Stats 8 | export { default as ListStats } from './user-list-stats'; 9 | 10 | // User History 11 | export { default as UserHistory } from './user-history'; 12 | 13 | export * from './user-profile'; 14 | export * from './userlist'; 15 | -------------------------------------------------------------------------------- /packages/client/types/vote.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Vote related types 3 | */ 4 | import { ContentTypeEnum } from './common'; 5 | 6 | /** 7 | * Content type for votable content 8 | */ 9 | export type VoteContentType = 10 | | ContentTypeEnum.COLLECTION 11 | | ContentTypeEnum.COMMENT 12 | | ContentTypeEnum.ARTICLE; 13 | 14 | /** 15 | * Vote arguments 16 | */ 17 | export interface VoteArgs { 18 | score: number; // -1, 0, or 1 19 | } 20 | 21 | /** 22 | * Vote response 23 | */ 24 | export interface VoteResponse { 25 | score: number; 26 | } 27 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/ep/EpSuccessFilled.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function EpSuccessFilled(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default EpSuccessFilled -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsCheckSmallRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsCheckSmallRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsCheckSmallRounded -------------------------------------------------------------------------------- /packages/react/types/client.ts: -------------------------------------------------------------------------------- 1 | import { ClientArgs, PaginationArgs } from '@hikka/client'; 2 | 3 | export interface UseClientByReferenceParams { 4 | reference: string; 5 | } 6 | 7 | export interface UseFullClientInfoParams { 8 | reference: string; 9 | } 10 | 11 | export interface UseClientListParams { 12 | paginationArgs?: PaginationArgs; 13 | } 14 | 15 | export interface UseUpdateClientParams { 16 | reference: string; 17 | args: ClientArgs; 18 | } 19 | 20 | export interface UseVerifyClientParams { 21 | reference: string; 22 | } 23 | -------------------------------------------------------------------------------- /packages/react/types/comments.ts: -------------------------------------------------------------------------------- 1 | import { CommentsContentType, PaginationArgs } from '@hikka/client'; 2 | 3 | export interface UseCommentThreadParams { 4 | commentReference: string; 5 | } 6 | 7 | export interface UseCommentListParams { 8 | paginationArgs?: PaginationArgs; 9 | } 10 | 11 | export interface UseContentCommentsParams { 12 | contentType: CommentsContentType; 13 | slug: string; 14 | paginationArgs?: PaginationArgs; 15 | } 16 | 17 | export interface UseLatestCommentsParams { 18 | paginationArgs?: PaginationArgs; 19 | } 20 | -------------------------------------------------------------------------------- /apps/web/src/app/(pages)/edit/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Metadata } from 'next'; 2 | import { FC, PropsWithChildren } from 'react'; 3 | 4 | import _generateMetadata from '@/utils/generate-metadata'; 5 | 6 | interface Props extends PropsWithChildren {} 7 | 8 | export const metadata: Metadata = _generateMetadata({ 9 | title: { 10 | default: 'Правки', 11 | template: 'Правки / %s / Hikka', 12 | }, 13 | }); 14 | 15 | const EditListLayout: FC = ({ children }) => { 16 | return children; 17 | }; 18 | 19 | export default EditListLayout; 20 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "prettier-plugin-tailwindcss", 4 | "@trivago/prettier-plugin-sort-imports" 5 | ], 6 | "tailwindFunctions": ["clsx"], 7 | "semi": true, 8 | "singleQuote": true, 9 | "trailingComma": "all", 10 | "tabWidth": 4, 11 | "importOrderSeparation": true, 12 | "importOrderSortSpecifiers": true, 13 | "importOrder": [ 14 | "", 15 | "^@/components/(.*)$", 16 | "^@/features/(.*)$", 17 | "^@/(.*)$", 18 | "^[./]" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /apps/web/src/features/auth/password-confirm-header.tsx: -------------------------------------------------------------------------------- 1 | import H1 from '@/components/typography/h1'; 2 | import Small from '@/components/typography/small'; 3 | 4 | const PasswordConfirmHeader = () => { 5 | return ( 6 |
    7 |

    🔓 Відновити пароль

    8 | 9 | Будь ласка, введіть новий пароль. 10 | 11 |
    12 | ); 13 | }; 14 | 15 | export default PasswordConfirmHeader; 16 | -------------------------------------------------------------------------------- /packages/client/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig({ 4 | entry: ['index.ts'], 5 | format: ['cjs', 'esm'], 6 | dts: true, 7 | splitting: false, 8 | sourcemap: true, 9 | clean: true, 10 | shims: true, 11 | minify: true, 12 | treeshake: true, 13 | tsconfig: './tsconfig.build.json', // Use build config to avoid composite issues 14 | outExtension({ format }) { 15 | return { 16 | js: format === 'cjs' ? '.js' : '.mjs', 17 | }; 18 | }, 19 | }); 20 | -------------------------------------------------------------------------------- /packages/react/types/people.ts: -------------------------------------------------------------------------------- 1 | import { QuerySearchArgs } from '@hikka/client'; 2 | 3 | export interface UsePersonInfoParams { 4 | slug: string; 5 | } 6 | 7 | export interface UsePersonAnimeParams { 8 | slug: string; 9 | } 10 | 11 | export interface UsePersonMangaParams { 12 | slug: string; 13 | } 14 | 15 | export interface UsePersonNovelParams { 16 | slug: string; 17 | } 18 | 19 | export interface UsePersonCharactersParams { 20 | slug: string; 21 | } 22 | 23 | export interface UsePeopleSearchParams { 24 | args?: QuerySearchArgs; 25 | } 26 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsKeyboardArrowUpRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsKeyboardArrowUpRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsKeyboardArrowUpRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsAddRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsAddRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsAddRounded -------------------------------------------------------------------------------- /apps/web/src/app/(pages)/(auth)/login/page.tsx: -------------------------------------------------------------------------------- 1 | import { Metadata } from 'next'; 2 | import { FC } from 'react'; 3 | 4 | import { LoginForm, LoginHeader } from '@/features/auth'; 5 | 6 | import _generateMetadata from '@/utils/generate-metadata'; 7 | 8 | export const metadata: Metadata = _generateMetadata({ 9 | title: 'Вхід', 10 | }); 11 | 12 | const LoginPage: FC = () => { 13 | return ( 14 |
    15 | 16 | 17 |
    18 | ); 19 | }; 20 | 21 | export default LoginPage; 22 | -------------------------------------------------------------------------------- /apps/web/src/app/(pages)/edit/[editId]/update/page.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react'; 2 | 3 | import { EditViewForm as EditView } from '@/features/edit'; 4 | 5 | interface Props { 6 | params: { editId: string }; 7 | } 8 | 9 | const EditUpdatePage: FC = async (props) => { 10 | const params = await props.params; 11 | 12 | const { editId } = params; 13 | 14 | return ( 15 |
    16 | 17 |
    18 | ); 19 | }; 20 | 21 | export default EditUpdatePage; 22 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/iconamoon/IconamoonCommentFill.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function IconamoonCommentFill(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default IconamoonCommentFill -------------------------------------------------------------------------------- /apps/web/src/components/icons/watch-status/dropped.tsx: -------------------------------------------------------------------------------- 1 | import { SVGProps } from 'react'; 2 | 3 | export default function IcRoundMinus(props: SVGProps) { 4 | return ( 5 | 12 | 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /packages/client/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "incremental": false, 6 | "composite": false 7 | }, 8 | "include": [ 9 | "index.ts", 10 | "client.ts", 11 | "errors.ts", 12 | "constants.ts", 13 | "modules/**/*.ts", 14 | "types/**/*.ts" 15 | ], 16 | "exclude": [ 17 | "node_modules", 18 | "dist", 19 | "**/*.test.ts", 20 | "**/*.spec.ts", 21 | "tsup.config.ts" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /packages/react/setupTests.ts: -------------------------------------------------------------------------------- 1 | import '@testing-library/jest-dom'; 2 | 3 | // Mock console.error to avoid seeing React act() warnings 4 | const originalError = console.error; 5 | beforeAll(() => { 6 | console.error = (...args) => { 7 | if ( 8 | typeof args[0] === 'string' && 9 | args[0].includes('Warning: ReactDOM.render is no longer supported') 10 | ) { 11 | return; 12 | } 13 | originalError.call(console, ...args); 14 | }; 15 | }); 16 | 17 | afterAll(() => { 18 | console.error = originalError; 19 | }); 20 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsDeleteForever.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsDeleteForever(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsDeleteForever -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsDraftRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsDraftRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsDraftRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsShortTextRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsShortTextRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsShortTextRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsInfoIRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsInfoIRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsInfoIRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsPerson.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsPerson(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsPerson -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsStack.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsStack(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsStack -------------------------------------------------------------------------------- /packages/client/types/related.ts: -------------------------------------------------------------------------------- 1 | import { AnimeResponse } from './anime'; 2 | import { ContentTypeEnum } from './common'; 3 | import { MangaResponse } from './manga'; 4 | import { NovelResponse } from './novel'; 5 | 6 | /** 7 | * Related content types 8 | */ 9 | export type RelatedContentType = 10 | | ContentTypeEnum.ANIME 11 | | ContentTypeEnum.MANGA 12 | | ContentTypeEnum.NOVEL; 13 | 14 | /** 15 | * Franchise response 16 | */ 17 | export interface FranchiseResponse { 18 | anime: AnimeResponse[]; 19 | manga: MangaResponse[]; 20 | novel: NovelResponse[]; 21 | } 22 | -------------------------------------------------------------------------------- /packages/react/core/createHikkaClient.ts: -------------------------------------------------------------------------------- 1 | import { HikkaClient, HikkaClientConfig } from '@hikka/client'; 2 | import { cache } from 'react'; 3 | 4 | /** 5 | * Creates a HikkaClient instance. 6 | * This ensures a clean client is created for each request. 7 | * 8 | * @param config - The HikkaClient config 9 | * @returns A new HikkaClient instance 10 | */ 11 | export function createHikkaClient(config?: HikkaClientConfig): HikkaClient { 12 | return new HikkaClient({ baseUrl: 'https://api.hikka.io', ...config }); 13 | } 14 | 15 | export const getHikkaClient = cache(createHikkaClient); 16 | -------------------------------------------------------------------------------- /packages/react/server/prefetch/api/genres.ts: -------------------------------------------------------------------------------- 1 | import { GenreListResponse } from '@hikka/client'; 2 | 3 | import { queryKeys } from '@/core'; 4 | import { PrefetchQueryParams, prefetchQuery } from '@/server/prefetchQuery'; 5 | 6 | /** 7 | * Prefetches all genres for server-side rendering 8 | */ 9 | export async function prefetchGenres({ 10 | ...rest 11 | }: PrefetchQueryParams = {}) { 12 | return prefetchQuery({ 13 | queryKey: queryKeys.genres.list(), 14 | queryFn: (client) => client.genres.getGenres(), 15 | ...rest, 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /packages/react/types/read.ts: -------------------------------------------------------------------------------- 1 | import { ReadContentType, ReadSearchArgs } from '@hikka/client'; 2 | 3 | export interface UseReadEntryParams { 4 | contentType: ReadContentType; 5 | slug: string; 6 | } 7 | 8 | export interface UseReadStatsParams { 9 | contentType: ReadContentType; 10 | username: string; 11 | } 12 | 13 | export interface UseReadListParams { 14 | contentType: ReadContentType; 15 | username: string; 16 | args: ReadSearchArgs; 17 | } 18 | 19 | export interface UseReadingUsersParams { 20 | contentType: ReadContentType; 21 | slug: string; 22 | } 23 | -------------------------------------------------------------------------------- /apps/web/src/app/(pages)/(auth)/signup/page.tsx: -------------------------------------------------------------------------------- 1 | import { Metadata } from 'next'; 2 | import { FC } from 'react'; 3 | 4 | import { SignupForm, SignupHeader } from '@/features/auth'; 5 | 6 | import _generateMetadata from '@/utils/generate-metadata'; 7 | 8 | export const metadata: Metadata = _generateMetadata({ 9 | title: 'Реєстрація', 10 | }); 11 | 12 | const SignupPage: FC = () => { 13 | return ( 14 |
    15 | 16 | 17 |
    18 | ); 19 | }; 20 | 21 | export default SignupPage; 22 | -------------------------------------------------------------------------------- /apps/web/src/features/common/index.ts: -------------------------------------------------------------------------------- 1 | // Core App Components 2 | export { default as AppSidebar } from './app-sidebar'; 3 | export { default as Footer } from './footer'; 4 | export { default as LoginButton } from './login-button'; 5 | export { default as Providers } from './providers'; 6 | export { default as ScrollTop } from './scroll-top'; 7 | export { default as SessionManager } from './session-manager'; 8 | 9 | // Navbar Components 10 | export { default as Navbar } from './navbar'; 11 | 12 | // Notifications Components 13 | export { default as NotificationsMenu } from './notifications-menu'; 14 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsPlayArrowRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsPlayArrowRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsPlayArrowRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsArrowDropDownRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsArrowDropDownRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsArrowDropDownRounded -------------------------------------------------------------------------------- /apps/web/src/components/typography/inline-code.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | import { cn } from '@/utils/utils'; 4 | 5 | interface Props { 6 | children: ReactNode | string; 7 | className?: string; 8 | } 9 | 10 | export default function InlineCode({ children, className }: Props) { 11 | return ( 12 | 18 | {children} 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/mdi/MdiPuzzle.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MdiPuzzle(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MdiPuzzle -------------------------------------------------------------------------------- /apps/web/src/components/icons/ant-design/AntDesignArrowLeftOutlined.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function AntDesignArrowLeftOutlined(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default AntDesignArrowLeftOutlined -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsKeyboardArrowDownRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsKeyboardArrowDownRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsKeyboardArrowDownRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsShieldRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsShieldRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsShieldRounded -------------------------------------------------------------------------------- /apps/web/src/utils/get-hikka-client-config.ts: -------------------------------------------------------------------------------- 1 | import { HikkaClientConfig } from '@hikka/client'; 2 | import { cache } from 'react'; 3 | 4 | import { getCookie } from './cookies'; 5 | 6 | export const createHikkaClientConfig = async ( 7 | config?: HikkaClientConfig, 8 | ): Promise => { 9 | return { 10 | baseUrl: process.env.API_URL || process.env.NEXT_PUBLIC_API_URL, 11 | authToken: await getCookie('auth'), 12 | ...config, 13 | }; 14 | }; 15 | 16 | export const getHikkaClientConfig = cache(createHikkaClientConfig); 17 | 18 | export default getHikkaClientConfig; 19 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/bx/BxBxlTelegram.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function BxBxlTelegram(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default BxBxlTelegram -------------------------------------------------------------------------------- /apps/web/src/components/ui/card.tsx: -------------------------------------------------------------------------------- 1 | import { ComponentPropsWithoutRef, memo } from 'react'; 2 | 3 | import { cn } from '@/utils/utils'; 4 | 5 | interface Props extends ComponentPropsWithoutRef<'div'> {} 6 | 7 | const Card = ({ children, className, ...props }: Props) => { 8 | return ( 9 |
    16 | {children} 17 |
    18 | ); 19 | }; 20 | 21 | export default memo(Card); 22 | -------------------------------------------------------------------------------- /apps/web/src/services/hooks/use-media-query.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | export function useMediaQuery(query: string) { 4 | const [value, setValue] = React.useState(false); 5 | 6 | React.useEffect(() => { 7 | function onChange(event: MediaQueryListEvent) { 8 | setValue(event.matches); 9 | } 10 | 11 | const result = matchMedia(query); 12 | result.addEventListener('change', onChange); 13 | setValue(result.matches); 14 | 15 | return () => result.removeEventListener('change', onChange); 16 | }, [query]); 17 | 18 | return value; 19 | } 20 | -------------------------------------------------------------------------------- /packages/react/client/hooks/api/genres.ts: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { GenreListResponse } from '@hikka/client'; 4 | 5 | import { QueryParams, useQuery } from '@/client/useQuery'; 6 | import { queryKeys } from '@/core'; 7 | 8 | /** 9 | * Hook for retrieving all genres 10 | */ 11 | export function useGenres({ 12 | ...rest 13 | }: QueryParams = {}) { 14 | return useQuery({ 15 | queryKey: queryKeys.genres.list(), 16 | queryFn: (client) => client.genres.getGenres(), 17 | ...rest, 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /apps/web/src/app/(pages)/(auth)/reset/page.tsx: -------------------------------------------------------------------------------- 1 | import { Metadata } from 'next'; 2 | import { FC } from 'react'; 3 | 4 | import { ForgotPasswordForm, ForgotPasswordHeader } from '@/features/auth'; 5 | 6 | import _generateMetadata from '@/utils/generate-metadata'; 7 | 8 | export const metadata: Metadata = _generateMetadata({ 9 | title: 'Відновити пароль', 10 | }); 11 | 12 | const ResetPage: FC = () => { 13 | return ( 14 |
    15 | 16 | 17 |
    18 | ); 19 | }; 20 | 21 | export default ResetPage; 22 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/ant-design/AntDesignArrowRightOutlined.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function AntDesignArrowRightOutlined(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default AntDesignArrowRightOutlined -------------------------------------------------------------------------------- /apps/web/src/features/users/userlist/components/table-view/media-cell.tsx: -------------------------------------------------------------------------------- 1 | import { AnimeMediaEnum } from '@hikka/client'; 2 | import { FC } from 'react'; 3 | 4 | import { TableCell } from '@/components/ui/table'; 5 | 6 | import { ANIME_MEDIA_TYPE } from '@/utils/constants/common'; 7 | 8 | interface Props { 9 | media_type?: AnimeMediaEnum | null; 10 | } 11 | 12 | const MediaCell: FC = ({ media_type }) => ( 13 | 14 | {media_type ? ANIME_MEDIA_TYPE[media_type].title_ua : '-'} 15 | 16 | ); 17 | 18 | export default MediaCell; 19 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsEventList.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsEventList(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsEventList -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsMoreHoriz.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsMoreHoriz(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsMoreHoriz -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsMoreVert.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsMoreVert(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsMoreVert -------------------------------------------------------------------------------- /apps/web/src/components/plate/editor/plugins/basic-blocks-kit.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { BlockquotePlugin } from '@platejs/basic-nodes/react'; 4 | import { ParagraphPlugin } from 'platejs/react'; 5 | 6 | import { BlockquoteElement } from '@/components/plate/ui/blockquote-node'; 7 | import { ParagraphElement } from '@/components/plate/ui/paragraph-node'; 8 | 9 | export const BasicBlocksKit = [ 10 | ParagraphPlugin.withComponent(ParagraphElement), 11 | BlockquotePlugin.configure({ 12 | node: { component: BlockquoteElement }, 13 | shortcuts: { toggle: { keys: 'mod+shift+period' } }, 14 | }), 15 | ]; 16 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsCloseRounded.tsx: -------------------------------------------------------------------------------- 1 | import { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsLockOpenRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsLockOpenRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsEditRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsEditRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsEditRounded -------------------------------------------------------------------------------- /apps/web/src/features/auth/index.ts: -------------------------------------------------------------------------------- 1 | export { default as ForgotPasswordForm } from './forgot-password-form'; 2 | export { default as ForgotPasswordHeader } from './forgot-password-header'; 3 | export { default as LoginForm } from './login-form'; 4 | export { default as LoginHeader } from './login-header'; 5 | export { default as OAuthLogin } from './oauth-login'; 6 | export { default as PasswordConfirmForm } from './password-confirm-form'; 7 | export { default as PasswordConfirmHeader } from './password-confirm-header'; 8 | export { default as SignupForm } from './signup-form'; 9 | export { default as SignupHeader } from './signup-header'; 10 | -------------------------------------------------------------------------------- /apps/web/src/features/modals/utility-modals/search-modal/hooks/useUserSearchList.ts: -------------------------------------------------------------------------------- 1 | import { UserResponse } from '@hikka/client'; 2 | import { useQuery } from '@hikka/react'; 3 | 4 | interface Props { 5 | value?: string; 6 | } 7 | 8 | const useUserSearchList = ({ value }: Props) => { 9 | return useQuery({ 10 | queryKey: ['user-search-list', value], 11 | queryFn: (client) => client.user.searchUsers({ query: value || '' }), 12 | options: { 13 | enabled: value !== undefined && value.length >= 3, 14 | }, 15 | }); 16 | }; 17 | 18 | export default useUserSearchList; 19 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsComputerOutlineRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsComputerOutlineRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsComputerOutlineRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsHomeRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsHomeRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsHomeRounded -------------------------------------------------------------------------------- /apps/web/src/components/plate/ui/spoiler-node.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import type { PlateElementProps } from 'platejs/react'; 4 | import { PlateElement } from 'platejs/react'; 5 | 6 | import { cn } from '@/utils/utils'; 7 | 8 | export function SpoilerElement(props: PlateElementProps) { 9 | return ( 10 | 18 | {props.children} 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsSortRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsSortRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsSortRounded -------------------------------------------------------------------------------- /packages/react/client/provider/useHikkaClient.ts: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useContext } from 'react'; 4 | 5 | import { HikkaContext } from './context'; 6 | 7 | /** 8 | * Hook to access the Hikka client from context. 9 | * Must be used within a HikkaProvider. 10 | */ 11 | export function useHikkaClient() { 12 | const context = useContext(HikkaContext); 13 | 14 | if (!context) { 15 | throw new Error( 16 | 'useHikkaClient must be used within a HikkaProvider. ' + 17 | 'Make sure you have wrapped your application with HikkaProvider.', 18 | ); 19 | } 20 | 21 | return context; 22 | } 23 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsReplyRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsReplyRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsReplyRounded -------------------------------------------------------------------------------- /apps/web/src/services/hooks/use-size.ts: -------------------------------------------------------------------------------- 1 | import useResizeObserver from '@react-hook/resize-observer'; 2 | import * as React from 'react'; 3 | import { RefObject } from 'react'; 4 | 5 | const useSize = (target: RefObject) => { 6 | const [size, setSize] = React.useState(); 7 | 8 | React.useLayoutEffect(() => { 9 | if (target.current) { 10 | setSize(target.current.getBoundingClientRect()); 11 | } 12 | }, [target]); 13 | 14 | // Where the magic happens 15 | useResizeObserver(target, (entry) => setSize(entry.contentRect)); 16 | return size; 17 | }; 18 | 19 | export default useSize; 20 | -------------------------------------------------------------------------------- /packages/react/types/anime.ts: -------------------------------------------------------------------------------- 1 | import { AnimeSearchArgs } from '@hikka/client'; 2 | 3 | export interface UseAnimeInfoParams { 4 | slug: string; 5 | } 6 | 7 | export interface UseAnimeCharactersParams { 8 | slug: string; 9 | } 10 | 11 | export interface UseAnimeEpisodesParams { 12 | slug: string; 13 | } 14 | 15 | export interface UseAnimeFranchiseParams { 16 | slug: string; 17 | } 18 | 19 | export interface UseAnimeRecommendationsParams { 20 | slug: string; 21 | } 22 | 23 | export interface UseAnimeStaffParams { 24 | slug: string; 25 | } 26 | 27 | export interface UseAnimeSearchParams { 28 | args: AnimeSearchArgs; 29 | } 30 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsAccountBox.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsAccountBox(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsAccountBox -------------------------------------------------------------------------------- /apps/web/src/components/icons/watch-status/completed.tsx: -------------------------------------------------------------------------------- 1 | import { SVGProps } from 'react'; 2 | 3 | export default function IcRoundCheck(props: SVGProps) { 4 | return ( 5 | 12 | 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/bx/BxBxlGoogle.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function BxBxlGoogle(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default BxBxlGoogle -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsArrowRightAltRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsArrowRightAltRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsArrowRightAltRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/bx/BxShareAlt.tsx: -------------------------------------------------------------------------------- 1 | import { SVGProps } from 'react' 2 | 3 | export function BxShareAlt(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default BxShareAlt -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsFavoriteRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsFavoriteRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsFavoriteRounded -------------------------------------------------------------------------------- /apps/web/src/components/plate/editor/plugins/image-group-base-kit.tsx: -------------------------------------------------------------------------------- 1 | import { createSlatePlugin } from 'platejs'; 2 | 3 | import { ImageGroupElementStatic } from '@/components/plate/ui/image-group-node-static'; 4 | 5 | import { BaseImageKit } from './image-base-kit'; 6 | 7 | export const ELEMENT_IMAGE_GROUP = 'image_group'; 8 | 9 | export const BaseImageGroupPlugin = createSlatePlugin({ 10 | key: ELEMENT_IMAGE_GROUP, 11 | node: { 12 | isElement: true, 13 | }, 14 | plugins: BaseImageKit, 15 | }); 16 | 17 | export const BaseImageGroupKit = [ 18 | ...BaseImageKit, 19 | BaseImageGroupPlugin.withComponent(ImageGroupElementStatic), 20 | ]; 21 | -------------------------------------------------------------------------------- /apps/web/src/components/plate/ui/mark-toolbar-button.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import * as React from 'react'; 4 | 5 | import { useMarkToolbarButton, useMarkToolbarButtonState } from 'platejs/react'; 6 | 7 | import { ToolbarButton } from './toolbar'; 8 | 9 | export function MarkToolbarButton({ 10 | clear, 11 | nodeType, 12 | ...props 13 | }: React.ComponentProps & { 14 | nodeType: string; 15 | clear?: string[] | string; 16 | }) { 17 | const state = useMarkToolbarButtonState({ clear, nodeType }); 18 | const { props: buttonProps } = useMarkToolbarButton(state); 19 | 20 | return ; 21 | } 22 | -------------------------------------------------------------------------------- /apps/web/src/features/people/cover.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { usePersonBySlug } from '@hikka/react'; 4 | import { useParams } from 'next/navigation'; 5 | 6 | import ContentCard from '@/components/content-card/content-card'; 7 | 8 | const Cover = () => { 9 | const params = useParams(); 10 | 11 | const { data: person } = usePersonBySlug({ slug: String(params.slug) }); 12 | 13 | if (!person) { 14 | return null; 15 | } 16 | 17 | return ( 18 |
    19 | 20 |
    21 | ); 22 | }; 23 | 24 | export default Cover; 25 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsNotificationsRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsNotificationsRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsNotificationsRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsSearchRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsSearchRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsSearchRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsLiveTvRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsLiveTvRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsLiveTvRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsClockLoader10.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsClockLoader10(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsClockLoader10 -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsImageOutlineRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsImageOutlineRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsImageOutlineRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsShieldPerson.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsShieldPerson(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsShieldPerson -------------------------------------------------------------------------------- /apps/web/src/features/modals/utility-modals/search-modal/hooks/useAnimeSearchList.ts: -------------------------------------------------------------------------------- 1 | import { AnimePaginationResponse } from '@hikka/client'; 2 | import { useQuery } from '@hikka/react'; 3 | 4 | interface Props { 5 | value?: string; 6 | } 7 | 8 | const useAnimeSearchList = ({ value }: Props) => { 9 | return useQuery({ 10 | queryKey: ['anime-search-list', value], 11 | queryFn: (client) => 12 | client.anime.searchAnimes({ query: value }, { size: 60 }), 13 | options: { 14 | enabled: value !== undefined && value.length >= 3, 15 | }, 16 | }); 17 | }; 18 | 19 | export default useAnimeSearchList; 20 | -------------------------------------------------------------------------------- /apps/web/src/features/modals/utility-modals/search-modal/hooks/useMangaSearchList.ts: -------------------------------------------------------------------------------- 1 | import { MangaPaginationResponse } from '@hikka/client'; 2 | import { useQuery } from '@hikka/react'; 3 | 4 | interface Props { 5 | value?: string; 6 | } 7 | 8 | const useMangaSearchList = ({ value }: Props) => { 9 | return useQuery({ 10 | queryKey: ['manga-search-list', value], 11 | queryFn: (client) => 12 | client.manga.searchMangas({ query: value }, { size: 60 }), 13 | options: { 14 | enabled: value !== undefined && value.length >= 3, 15 | }, 16 | }); 17 | }; 18 | 19 | export default useMangaSearchList; 20 | -------------------------------------------------------------------------------- /apps/web/src/features/modals/utility-modals/search-modal/hooks/useNovelSearchList.ts: -------------------------------------------------------------------------------- 1 | import { NovelPaginationResponse } from '@hikka/client'; 2 | import { useQuery } from '@hikka/react'; 3 | 4 | interface Props { 5 | value?: string; 6 | } 7 | 8 | const useNovelSearchList = ({ value }: Props) => { 9 | return useQuery({ 10 | queryKey: ['novel-search-list', value], 11 | queryFn: (client) => 12 | client.novel.searchNovels({ query: value }, { size: 60 }), 13 | options: { 14 | enabled: value !== undefined && value.length >= 3, 15 | }, 16 | }); 17 | }; 18 | 19 | export default useNovelSearchList; 20 | -------------------------------------------------------------------------------- /apps/web/src/utils/adapters/convert-activity/convert-favorite-activity.tsx: -------------------------------------------------------------------------------- 1 | import { HistoryTypeEnum } from '@hikka/client'; 2 | 3 | export const convertDeleteFavorite = () => { 4 | return 'Видалено з улюблених'; 5 | }; 6 | 7 | export const convertAddFavorite = () => { 8 | return 'Додано до улюблених'; 9 | }; 10 | 11 | export const createFavoriteEvents = (history_type: HistoryTypeEnum) => { 12 | const events = []; 13 | 14 | if (history_type.includes('_remove')) { 15 | events.push(convertDeleteFavorite()); 16 | } 17 | 18 | if (history_type.includes('_add')) { 19 | events.push(convertAddFavorite()); 20 | } 21 | 22 | return events; 23 | }; 24 | -------------------------------------------------------------------------------- /apps/web/src/features/articles/article-edit/article-title.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { memo } from 'react'; 4 | 5 | import { 6 | Header, 7 | HeaderContainer, 8 | HeaderTitle, 9 | } from '@/components/ui/header'; 10 | import { useArticleContext } from '@/services/providers/article-provider'; 11 | 12 | const ArticleTitle = () => { 13 | const title = useArticleContext((state) => state.title); 14 | 15 | return ( 16 |
    17 | 18 | {title || 'Нова стаття'} 19 | 20 |
    21 | ); 22 | }; 23 | 24 | export default memo(ArticleTitle); 25 | -------------------------------------------------------------------------------- /packages/client/types/follow.ts: -------------------------------------------------------------------------------- 1 | import { PaginationResponse } from './common'; 2 | import { UserResponse } from './user'; 3 | 4 | /** 5 | * Follow response 6 | */ 7 | export interface FollowResponse { 8 | follow: boolean; 9 | } 10 | 11 | /** 12 | * Parameters for follow operations 13 | */ 14 | export interface FollowParams { 15 | username: string; 16 | } 17 | 18 | /** 19 | * Follow stats response 20 | */ 21 | export interface FollowStatsResponse { 22 | following: number; 23 | followers: number; 24 | } 25 | 26 | /** 27 | * Follow list response 28 | */ 29 | export interface FollowListResponse { 30 | list: UserResponse[]; 31 | pagination: PaginationResponse; 32 | } 33 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsAnimatedImages.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsAnimatedImages(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsAnimatedImages -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsAddCommentRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsAddCommentRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsAddCommentRounded -------------------------------------------------------------------------------- /apps/web/src/features/modals/utility-modals/search-modal/hooks/usePersonSearchList.ts: -------------------------------------------------------------------------------- 1 | import { PersonSearchPaginationResponse } from '@hikka/client'; 2 | import { useQuery } from '@hikka/react'; 3 | 4 | interface Props { 5 | value?: string; 6 | } 7 | 8 | const usePersonSearchList = ({ value }: Props) => { 9 | return useQuery({ 10 | queryKey: ['person-search-list', value], 11 | queryFn: (client) => 12 | client.people.searchPeople({ query: value }, { size: 60 }), 13 | options: { 14 | enabled: value !== undefined && value.length >= 3, 15 | }, 16 | }); 17 | }; 18 | 19 | export default usePersonSearchList; 20 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsCloseSmallRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsCloseSmallRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsCloseSmallRounded -------------------------------------------------------------------------------- /apps/web/src/features/characters/cover.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useCharacterBySlug } from '@hikka/react'; 4 | import { useParams } from 'next/navigation'; 5 | 6 | import ContentCard from '@/components/content-card/content-card'; 7 | 8 | const Cover = () => { 9 | const params = useParams(); 10 | 11 | const { data: character } = useCharacterBySlug({ 12 | slug: String(params.slug), 13 | }); 14 | 15 | if (!character) { 16 | return null; 17 | } 18 | 19 | return ( 20 |
    21 | 22 |
    23 | ); 24 | }; 25 | 26 | export default Cover; 27 | -------------------------------------------------------------------------------- /packages/react/server/prefetch/api/vote.ts: -------------------------------------------------------------------------------- 1 | import { VoteResponse } from '@hikka/client'; 2 | 3 | import { queryKeys } from '@/core'; 4 | import { PrefetchQueryParams, prefetchQuery } from '@/server/prefetchQuery'; 5 | import { UseVoteStatusParams } from '@/types/vote'; 6 | 7 | /** 8 | * Hook for prefetching vote status 9 | */ 10 | export async function prefetchContentVote({ 11 | contentType, 12 | slug, 13 | ...rest 14 | }: PrefetchQueryParams & UseVoteStatusParams) { 15 | return prefetchQuery({ 16 | queryKey: queryKeys.vote.status(contentType, slug), 17 | queryFn: (client) => client.vote.getContentVote(contentType, slug), 18 | ...rest, 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /apps/web/src/app/(pages)/(content)/anime/sitemap.ts: -------------------------------------------------------------------------------- 1 | import { HikkaClient } from '@hikka/client'; 2 | import { toDate } from 'date-fns/toDate'; 3 | import { MetadataRoute } from 'next'; 4 | 5 | export const dynamic = 'force-dynamic'; 6 | 7 | const client = new HikkaClient({ 8 | baseUrl: process.env.NEXT_PUBLIC_API_URL, 9 | }); 10 | 11 | export default async function sitemap(): Promise { 12 | const res = await client.sitemap.getAnimeSitemap(); 13 | 14 | return res.map((anime) => ({ 15 | url: 'https://hikka.io/anime/' + anime.slug, 16 | lastModified: toDate(anime.updated_at * 1000), 17 | changeFrequency: 'weekly', 18 | priority: 1, 19 | })); 20 | } 21 | -------------------------------------------------------------------------------- /apps/web/src/app/(pages)/(content)/manga/sitemap.ts: -------------------------------------------------------------------------------- 1 | import { HikkaClient } from '@hikka/client'; 2 | import { toDate } from 'date-fns/toDate'; 3 | import { MetadataRoute } from 'next'; 4 | 5 | export const dynamic = 'force-dynamic'; 6 | 7 | const client = new HikkaClient({ 8 | baseUrl: process.env.NEXT_PUBLIC_API_URL, 9 | }); 10 | 11 | export default async function sitemap(): Promise { 12 | const res = await client.sitemap.getMangaSitemap(); 13 | 14 | return res.map((manga) => ({ 15 | url: 'https://hikka.io/manga/' + manga.slug, 16 | lastModified: toDate(manga.updated_at * 1000), 17 | changeFrequency: 'weekly', 18 | priority: 1, 19 | })); 20 | } 21 | -------------------------------------------------------------------------------- /apps/web/src/app/(pages)/(content)/novel/sitemap.ts: -------------------------------------------------------------------------------- 1 | import { HikkaClient } from '@hikka/client'; 2 | import { toDate } from 'date-fns/toDate'; 3 | import { MetadataRoute } from 'next'; 4 | 5 | export const dynamic = 'force-dynamic'; 6 | 7 | const client = new HikkaClient({ 8 | baseUrl: process.env.NEXT_PUBLIC_API_URL, 9 | }); 10 | 11 | export default async function sitemap(): Promise { 12 | const res = await client.sitemap.getNovelSitemap(); 13 | 14 | return res.map((novel) => ({ 15 | url: 'https://hikka.io/novel/' + novel.slug, 16 | lastModified: toDate(novel.updated_at * 1000), 17 | changeFrequency: 'weekly', 18 | priority: 1, 19 | })); 20 | } 21 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsBarChartRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsBarChartRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsBarChartRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/ph/PhTipJarFill.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function PhTipJarFill(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default PhTipJarFill -------------------------------------------------------------------------------- /apps/web/src/features/oauth/components/scope.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react'; 2 | 3 | import P from '@/components/typography/p'; 4 | import { cn } from '@/utils/utils'; 5 | 6 | interface Props { 7 | scope: Hikka.Scope; 8 | } 9 | 10 | const Scope: FC = ({ scope }) => { 11 | if (!scope) return null; 12 | 13 | return ( 14 |
    15 |
    16 | 17 |
    18 |

    {scope.title_ua}

    19 |
    20 | ); 21 | }; 22 | 23 | export default Scope; 24 | -------------------------------------------------------------------------------- /apps/web/src/services/hooks/use-on-screen.ts: -------------------------------------------------------------------------------- 1 | import { RefObject, useEffect, useMemo, useState } from 'react'; 2 | 3 | export default function useOnScreen(ref: RefObject) { 4 | const [isIntersecting, setIntersecting] = useState(false); 5 | 6 | const observer = useMemo( 7 | () => 8 | new IntersectionObserver(([entry]) => 9 | setIntersecting(entry.isIntersecting), 10 | ), 11 | [ref], 12 | ); 13 | 14 | useEffect(() => { 15 | if (ref.current) { 16 | observer.observe(ref.current); 17 | } 18 | 19 | return () => observer.disconnect(); 20 | }, []); 21 | 22 | return isIntersecting; 23 | } 24 | -------------------------------------------------------------------------------- /apps/web/src/components/content-card/content-card-skeleton.tsx: -------------------------------------------------------------------------------- 1 | interface Props {} 2 | 3 | const Component = ({}: Props) => { 4 | return ( 5 |
    6 |
    7 |
    8 |
    9 |
    10 |
    11 |
    12 |
    13 |
    14 | ); 15 | }; 16 | 17 | export default Component; 18 | -------------------------------------------------------------------------------- /packages/react/types/watch.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AnimeWatchSearchArgs, 3 | WatchArgs, 4 | WatchStatusEnum, 5 | } from '@hikka/client'; 6 | 7 | export interface UseWatchEntryParams { 8 | slug: string; 9 | } 10 | 11 | export interface UseWatchStatsParams { 12 | username: string; 13 | } 14 | 15 | export interface UseWatchListParams { 16 | username: string; 17 | args: AnimeWatchSearchArgs; 18 | } 19 | 20 | export interface UseFollowingWatchersParams { 21 | slug: string; 22 | } 23 | 24 | export interface UseCreateWatchParams { 25 | slug: string; 26 | args: WatchArgs; 27 | } 28 | 29 | export interface RandomAnimeVariables { 30 | username: string; 31 | status: WatchStatusEnum; 32 | } 33 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsKidStar.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsKidStar(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsKidStar -------------------------------------------------------------------------------- /apps/web/src/features/articles/article-view/article-author.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useArticleBySlug } from '@hikka/react'; 4 | import { useParams } from 'next/navigation'; 5 | import { FC } from 'react'; 6 | 7 | import Author from '@/components/article-item/article-author'; 8 | 9 | interface Props {} 10 | 11 | const ArticleAuthor: FC = () => { 12 | const params = useParams(); 13 | 14 | const { data: article } = useArticleBySlug({ 15 | slug: String(params.slug), 16 | }); 17 | 18 | return ( 19 | 23 | ); 24 | }; 25 | 26 | export default ArticleAuthor; 27 | -------------------------------------------------------------------------------- /apps/web/src/features/content/index.ts: -------------------------------------------------------------------------------- 1 | export { default as ContentActions } from './actions'; 2 | export { default as ContentCharacters } from './characters'; 3 | export { default as ContentStats } from './content-stats'; 4 | export { default as ContentCover } from './cover'; 5 | export { default as ContentDescription } from './description'; 6 | export { default as ContentDetails } from './details'; 7 | export { default as Franchise } from './franchise'; 8 | export { default as ContentLinks } from './links'; 9 | export { default as ContentMedia } from './media'; 10 | export { default as ContentNavbar } from './navbar'; 11 | export { default as ContentStaff } from './staff'; 12 | export { default as ContentTitle } from './title'; 13 | -------------------------------------------------------------------------------- /packages/react/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './anime'; 2 | export * from './articles'; 3 | export * from './auth'; 4 | export * from './characters'; 5 | export * from './client'; 6 | export * from './collections'; 7 | export * from './comments'; 8 | export * from './companies'; 9 | export * from './edit'; 10 | export * from './favourite'; 11 | export * from './follow'; 12 | export * from './history'; 13 | export * from './manga'; 14 | export * from './novel'; 15 | export * from './people'; 16 | export * from './read'; 17 | export * from './related'; 18 | export * from './schedule'; 19 | export * from './settings'; 20 | export * from './stats'; 21 | export * from './user'; 22 | export * from './vote'; 23 | export * from './watch'; 24 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsCheckCircleRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsCheckCircleRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsCheckCircleRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsInfoRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsInfoRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsInfoRounded -------------------------------------------------------------------------------- /apps/web/src/app/(pages)/(content)/anime/(anime-list)/page.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | HydrationBoundary, 3 | dehydrate, 4 | getQueryClient, 5 | } from '@hikka/react/core'; 6 | import { FC } from 'react'; 7 | 8 | import { AnimeList } from '@/features/anime'; 9 | 10 | interface Props { 11 | searchParams: { [key: string]: string | string[] | undefined }; 12 | } 13 | 14 | const AnimeListPage: FC = async (props) => { 15 | const queryClient = getQueryClient(); 16 | 17 | const dehydratedState = dehydrate(queryClient); 18 | 19 | return ( 20 | 21 | 22 | 23 | ); 24 | }; 25 | 26 | export default AnimeListPage; 27 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsWarningRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsWarningRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsWarningRounded -------------------------------------------------------------------------------- /apps/web/src/features/common/login-button.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import Link from 'next/link'; 4 | import { usePathname, useSearchParams } from 'next/navigation'; 5 | 6 | import { Button, ButtonProps } from '@/components/ui/button'; 7 | 8 | const LoginButton = (props: ButtonProps) => { 9 | const pathname = usePathname(); 10 | const searchParams = useSearchParams(); 11 | 12 | const currentUrl = `${pathname}${searchParams.toString() ? `?${searchParams.toString()}` : ''}`; 13 | 14 | return ( 15 | 18 | ); 19 | }; 20 | 21 | export default LoginButton; 22 | -------------------------------------------------------------------------------- /apps/web/src/features/modals/utility-modals/search-modal/hooks/useCharacterSearchList.ts: -------------------------------------------------------------------------------- 1 | import { CharactersSearchPaginationResponse } from '@hikka/client'; 2 | import { useQuery } from '@hikka/react'; 3 | 4 | interface Props { 5 | value?: string; 6 | } 7 | 8 | const useCharacterSearchList = ({ value }: Props) => { 9 | return useQuery({ 10 | queryKey: ['character-search-list', value], 11 | queryFn: (client) => 12 | client.characters.searchCharacters({ query: value }, { size: 60 }), 13 | options: { 14 | enabled: value !== undefined && value.length >= 3, 15 | }, 16 | }); 17 | }; 18 | 19 | export default useCharacterSearchList; 20 | -------------------------------------------------------------------------------- /apps/web/src/utils/cookies.ts: -------------------------------------------------------------------------------- 1 | 'use server'; 2 | 3 | import { cookies } from 'next/headers'; 4 | 5 | export async function setCookie(name: string, value: string) { 6 | (await cookies()).set(name, value, { 7 | maxAge: 30 * 24 * 60 * 60, 8 | httpOnly: process.env.COOKIE_HTTP_ONLY === 'true', 9 | sameSite: 'lax', 10 | domain: process.env.COOKIE_DOMAIN, 11 | }); 12 | } 13 | 14 | export async function deleteCookie(name: string) { 15 | return (await cookies()).delete(name); 16 | } 17 | 18 | export async function getCookie(name: string) { 19 | return (await cookies()).get(name)?.value; 20 | } 21 | 22 | export async function getCookies() { 23 | return (await cookies()).getAll().values(); 24 | } 25 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsDriveFileRenameOutlineRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsDriveFileRenameOutlineRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsDriveFileRenameOutlineRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsOpenInNewRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsOpenInNewRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsOpenInNewRounded -------------------------------------------------------------------------------- /apps/web/src/components/tailwind-indicator.tsx: -------------------------------------------------------------------------------- 1 | export function TailwindIndicator() { 2 | if (process.env.NODE_ENV === 'production') return null; 3 | 4 | return ( 5 |
    6 |
    xs
    7 |
    sm
    8 |
    md
    9 |
    lg
    10 |
    xl
    11 |
    2xl
    12 |
    13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsBookmarkFlagOutlineRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsBookmarkFlagOutlineRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsBookmarkFlagOutlineRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsLoginRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsLoginRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsLoginRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsLogoutRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsLogoutRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsLogoutRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsRefreshRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsRefreshRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsRefreshRounded -------------------------------------------------------------------------------- /apps/web/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.js", 8 | "css": "src/app/globals.css", 9 | "baseColor": "slate", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/utils/utils" 16 | }, 17 | "registries": { 18 | "plate": { 19 | "url": "https://platejs.org/r", 20 | "style": "default", 21 | "aliases": { 22 | "ui": "@/components/markdown/editor/plate-ui" 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsDynamicFeedRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsDynamicFeedRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsDynamicFeedRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsLockOpenRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsLockOpenRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsLockOpenRounded -------------------------------------------------------------------------------- /apps/web/src/features/oauth/oauth-header.tsx: -------------------------------------------------------------------------------- 1 | import Link from 'next/link'; 2 | import { FC } from 'react'; 3 | 4 | import { Header, HeaderContainer, HeaderTitle } from '@/components/ui/header'; 5 | 6 | interface Props {} 7 | 8 | const OAuthHeader: FC = () => { 9 | return ( 10 |
    11 |
    12 | 13 | Додати зʼєднання 14 | 15 |
    16 | 17 |
    18 | 19 |
    20 | ); 21 | }; 22 | 23 | export default OAuthHeader; 24 | -------------------------------------------------------------------------------- /packages/react/server/prefetch/api/related.ts: -------------------------------------------------------------------------------- 1 | import { FranchiseResponse } from '@hikka/client'; 2 | 3 | import { queryKeys } from '@/core'; 4 | import { PrefetchQueryParams, prefetchQuery } from '@/server/prefetchQuery'; 5 | import { UseFranchiseParams } from '@/types/related'; 6 | 7 | /** 8 | * Prefetches franchise information for server-side rendering 9 | */ 10 | export async function prefetchFranchise({ 11 | contentType, 12 | slug, 13 | ...rest 14 | }: PrefetchQueryParams & UseFranchiseParams) { 15 | return prefetchQuery({ 16 | queryKey: queryKeys.related.franchise(contentType, slug), 17 | queryFn: (client) => client.related.getFranchise(contentType, slug), 18 | ...rest, 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /apps/web/src/app/(pages)/(auth)/reset/[token]/page.tsx: -------------------------------------------------------------------------------- 1 | import { Metadata } from 'next'; 2 | import { FC } from 'react'; 3 | 4 | import { PasswordConfirmForm, PasswordConfirmHeader } from '@/features/auth'; 5 | 6 | import _generateMetadata from '@/utils/generate-metadata'; 7 | 8 | export const metadata: Metadata = _generateMetadata({ 9 | title: 'Відновити пароль', 10 | }); 11 | 12 | interface Props { 13 | params: { 14 | token: string; 15 | }; 16 | } 17 | 18 | const PasswordConfirmPage: FC = () => { 19 | return ( 20 |
    21 | 22 | 23 |
    24 | ); 25 | }; 26 | 27 | export default PasswordConfirmPage; 28 | -------------------------------------------------------------------------------- /apps/web/src/services/hooks/use-debounce.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | type DebounceProps = { 4 | value: T; 5 | delay?: number; 6 | } 7 | 8 | const useDebounce = ({ value, delay = 500 }: DebounceProps) => { 9 | const [debouncedValue, setDebouncedValue] = React.useState(value); 10 | 11 | React.useEffect(() => { 12 | const handler: NodeJS.Timeout = setTimeout(() => { 13 | setDebouncedValue(value); 14 | }, delay); 15 | 16 | // Cancel the timeout if value changes (also on delay change or unmount) 17 | return () => { 18 | clearTimeout(handler); 19 | }; 20 | }, [value, delay]); 21 | 22 | return debouncedValue; 23 | }; 24 | 25 | export default useDebounce; 26 | -------------------------------------------------------------------------------- /packages/client/modules/related.ts: -------------------------------------------------------------------------------- 1 | import { BaseRequestOptionsArgs } from '../types'; 2 | import { FranchiseResponse, RelatedContentType } from '../types/related'; 3 | import { BaseModule } from './base'; 4 | 5 | /** 6 | * Module for handling related content 7 | */ 8 | export class RelatedModule extends BaseModule { 9 | /** 10 | * Get franchise information for a content 11 | */ 12 | public async getFranchise( 13 | contentType: RelatedContentType, 14 | slug: string, 15 | options?: BaseRequestOptionsArgs, 16 | ): Promise { 17 | return this.client.get( 18 | `/related/${contentType}/${slug}/franchise`, 19 | options, 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/react/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules/ 3 | .yarn/* 4 | !.yarn/patches 5 | !.yarn/plugins 6 | !.yarn/releases 7 | !.yarn/sdks 8 | !.yarn/versions 9 | 10 | # Build outputs 11 | dist/ 12 | build/ 13 | lib/ 14 | 15 | # Logs 16 | logs 17 | *.log 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | 22 | # Editor directories and files 23 | .idea/ 24 | .vscode/ 25 | *.suo 26 | *.ntvs* 27 | *.njsproj 28 | *.sln 29 | *.sw? 30 | 31 | # OS specific 32 | .DS_Store 33 | Thumbs.db 34 | 35 | # Environment variables 36 | .env 37 | .env.local 38 | .env.development.local 39 | .env.test.local 40 | .env.production.local 41 | 42 | # TypeScript 43 | *.tsbuildinfo 44 | 45 | # Coverage directory used by tools like istanbul 46 | coverage/ 47 | .coverage/ -------------------------------------------------------------------------------- /apps/web/src/app/(pages)/(content)/manga/(manga-list)/page.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | HydrationBoundary, 3 | dehydrate, 4 | getQueryClient, 5 | } from '@hikka/react/core'; 6 | import { FC } from 'react'; 7 | 8 | import { MangaList } from '@/features/manga'; 9 | 10 | interface Props { 11 | searchParams: Record; 12 | } 13 | 14 | const MangaListPage: FC = async (props) => { 15 | const queryClient = getQueryClient(); 16 | 17 | // await prefetchMangaCatalog(dataKeys); 18 | 19 | const dehydratedState = dehydrate(queryClient); 20 | 21 | return ( 22 | 23 | 24 | 25 | ); 26 | }; 27 | 28 | export default MangaListPage; 29 | -------------------------------------------------------------------------------- /apps/web/src/app/(pages)/(content)/novel/(novel-list)/page.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | HydrationBoundary, 3 | dehydrate, 4 | getQueryClient, 5 | } from '@hikka/react/core'; 6 | import { FC } from 'react'; 7 | 8 | import { NovelList } from '@/features/novel'; 9 | 10 | interface Props { 11 | searchParams: Record; 12 | } 13 | 14 | const NovelListPage: FC = async (props) => { 15 | const queryClient = getQueryClient(); 16 | 17 | // await prefetchNovelCatalog(dataKeys); 18 | 19 | const dehydratedState = dehydrate(queryClient); 20 | 21 | return ( 22 | 23 | 24 | 25 | ); 26 | }; 27 | 28 | export default NovelListPage; 29 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsZoomOutRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsZoomOutRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsZoomOutRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/watch-status/planned.tsx: -------------------------------------------------------------------------------- 1 | import { SVGProps } from 'react'; 2 | 3 | export default function MaterialSymbolsAddRounded( 4 | props: SVGProps, 5 | ) { 6 | return ( 7 | 14 | 18 | 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /apps/web/src/components/plate/ui/link-node-static.tsx: -------------------------------------------------------------------------------- 1 | import { getLinkAttributes } from '@platejs/link'; 2 | import type { TLinkElement } from 'platejs'; 3 | import type { SlateElementProps } from 'platejs/static'; 4 | import { SlateElement } from 'platejs/static'; 5 | 6 | import Link from '@/components/typography/link'; 7 | 8 | export function LinkElementStatic(props: SlateElementProps) { 9 | return ( 10 | 18 | {props.children} 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /packages/client/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules/ 3 | .yarn/* 4 | !.yarn/patches 5 | !.yarn/plugins 6 | !.yarn/releases 7 | !.yarn/sdks 8 | !.yarn/versions 9 | 10 | # Build outputs 11 | dist/ 12 | build/ 13 | lib/ 14 | 15 | # Logs 16 | logs 17 | *.log 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | 22 | # Editor directories and files 23 | .idea/ 24 | .vscode/ 25 | *.suo 26 | *.ntvs* 27 | *.njsproj 28 | *.sln 29 | *.sw? 30 | 31 | # OS specific 32 | .DS_Store 33 | Thumbs.db 34 | 35 | # Environment variables 36 | .env 37 | .env.local 38 | .env.development.local 39 | .env.test.local 40 | .env.production.local 41 | 42 | # TypeScript 43 | *.tsbuildinfo 44 | 45 | # Coverage directory used by tools like istanbul 46 | coverage/ 47 | .coverage/ -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsPublishRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsPublishRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsPublishRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsUploadRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsUploadRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsUploadRounded -------------------------------------------------------------------------------- /packages/react/server/prefetch/api/settings.ts: -------------------------------------------------------------------------------- 1 | import { IgnoredNotificationsResponse } from '@hikka/client'; 2 | 3 | import { queryKeys } from '@/core'; 4 | import { PrefetchQueryParams, prefetchQuery } from '@/server/prefetchQuery'; 5 | import { UseIgnoredNotificationsParams } from '@/types/settings'; 6 | 7 | /** 8 | * Function for prefetching ignored notification types 9 | */ 10 | export async function prefetchIgnoredNotifications({ 11 | ...rest 12 | }: PrefetchQueryParams & 13 | UseIgnoredNotificationsParams = {}) { 14 | return prefetchQuery({ 15 | queryKey: queryKeys.settings.ignoredNotifications(), 16 | queryFn: (client) => client.settings.getIgnoredNotifications(), 17 | ...rest, 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsWarningOutlineRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsWarningOutlineRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsWarningOutlineRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/bx/BxBxsDonateHeart.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function BxBxsDonateHeart(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default BxBxsDonateHeart -------------------------------------------------------------------------------- /apps/web/src/components/snowfall-manager.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import Snowfall from 'react-snowfall'; 4 | 5 | import { useSettingsStore } from '@/services/stores/settings-store'; 6 | 7 | const SnowfallManager = () => { 8 | const settings = useSettingsStore(); 9 | 10 | if (!settings.snowflakes) { 11 | return null; 12 | } 13 | 14 | return ( 15 | 25 | ); 26 | }; 27 | 28 | export default SnowfallManager; 29 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsEventListRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsEventListRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsEventListRounded -------------------------------------------------------------------------------- /apps/web/src/features/edit/components/edit-list/edit-skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { range } from '@antfu/utils'; 2 | 3 | import Block from '@/components/ui/block'; 4 | import { Table, TableBody } from '@/components/ui/table'; 5 | 6 | import EditHead from './edit-head'; 7 | import EntryTableRowSkeleton from './entry-table-row-skeleton'; 8 | 9 | const EditSkeleton = () => { 10 | return ( 11 | 12 | 13 | 14 | 15 | {range(1, 20).map((v) => ( 16 | 17 | ))} 18 | 19 |
    20 |
    21 | ); 22 | }; 23 | 24 | export default EditSkeleton; 25 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsHourglassEmptyRounded.tsx: -------------------------------------------------------------------------------- 1 | import { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsAddRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsAddRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsFlagCircleRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsFlagCircleRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsFlagCircleRounded -------------------------------------------------------------------------------- /apps/web/src/components/character-card.tsx: -------------------------------------------------------------------------------- 1 | import { CharacterResponse, ContentTypeEnum } from '@hikka/client'; 2 | import { FC } from 'react'; 3 | 4 | import ContentCard, { ContentCardProps } from './content-card/content-card'; 5 | 6 | interface Props extends ContentCardProps { 7 | character: CharacterResponse; 8 | } 9 | 10 | const CharacterCard: FC = ({ character, ...props }) => { 11 | return ( 12 | 21 | ); 22 | }; 23 | 24 | export default CharacterCard; 25 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsImageNotSupportedOutlineRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsImageNotSupportedOutlineRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsImageNotSupportedOutlineRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsLockOpenRightOutlineRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsLockOpenRightOutlineRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsLockOpenRightOutlineRounded -------------------------------------------------------------------------------- /packages/react/client/hooks/api/related.ts: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { FranchiseResponse } from '@hikka/client'; 4 | 5 | import { QueryParams, useQuery } from '@/client/useQuery'; 6 | import { queryKeys } from '@/core'; 7 | import { UseFranchiseParams } from '@/types/related'; 8 | 9 | /** 10 | * Hook for retrieving franchise data for anime, manga, or novel 11 | */ 12 | export function useFranchise({ 13 | contentType, 14 | slug, 15 | ...rest 16 | }: UseFranchiseParams & QueryParams) { 17 | return useQuery({ 18 | queryKey: queryKeys.related.franchise(contentType, slug), 19 | queryFn: (client) => client.related.getFranchise(contentType, slug), 20 | ...rest, 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsLibraryMusicRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsLibraryMusicRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsLibraryMusicRounded -------------------------------------------------------------------------------- /apps/web/src/components/plate/ui/link-toolbar-button.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { 4 | useLinkToolbarButton, 5 | useLinkToolbarButtonState, 6 | } from '@platejs/link/react'; 7 | import { Link } from 'lucide-react'; 8 | import * as React from 'react'; 9 | 10 | import { ToolbarButton } from './toolbar'; 11 | 12 | export function LinkToolbarButton( 13 | props: React.ComponentProps, 14 | ) { 15 | const state = useLinkToolbarButtonState(); 16 | const { props: buttonProps } = useLinkToolbarButton(state); 17 | 18 | return ( 19 | 25 | 26 | 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /apps/web/src/features/auth/login-header.tsx: -------------------------------------------------------------------------------- 1 | import Link from 'next/link'; 2 | 3 | import H1 from '@/components/typography/h1'; 4 | import Small from '@/components/typography/small'; 5 | 6 | const LoginHeader = () => { 7 | return ( 8 |
    9 |

    👋 З поверненням!

    10 | 11 | Не маєте аккаунту?{' '} 12 | 16 | Зареєструйтесь зараз 17 | 18 | 19 |
    20 | ); 21 | }; 22 | 23 | export default LoginHeader; 24 | -------------------------------------------------------------------------------- /apps/web/src/features/auth/signup-header.tsx: -------------------------------------------------------------------------------- 1 | import Link from 'next/link'; 2 | 3 | import H1 from '@/components/typography/h1'; 4 | import Small from '@/components/typography/small'; 5 | 6 | const SignupHeader = () => { 7 | return ( 8 |
    9 |

    ✌️ Раді познайомитись!

    10 | 11 | Вже маєте аккаунт?{' '} 12 | 16 | Увійдіть зараз 17 | 18 | 19 |
    20 | ); 21 | }; 22 | 23 | export default SignupHeader; 24 | -------------------------------------------------------------------------------- /packages/react/client/hooks/api/upload.ts: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { UploadTypeEnum } from '@hikka/client'; 4 | 5 | import { createMutation } from '@/client/useMutation'; 6 | import { queryKeys } from '@/core'; 7 | 8 | /** 9 | * Upload image variables type 10 | */ 11 | type UploadImageVariables = { 12 | uploadType: UploadTypeEnum; 13 | file: File | Blob; 14 | }; 15 | 16 | /** 17 | * Hook for uploading an image 18 | */ 19 | export const useCreateImageUpload = createMutation({ 20 | mutationFn: (client, args: UploadImageVariables) => 21 | client.upload.createImageUpload(args.uploadType, args.file), 22 | invalidateQueries: (args: UploadImageVariables) => 23 | args.uploadType !== UploadTypeEnum.ATTACHMENT 24 | ? [queryKeys.user.all] 25 | : [], 26 | }); 27 | -------------------------------------------------------------------------------- /apps/web/src/app/(pages)/edit/[editId]/page.tsx: -------------------------------------------------------------------------------- 1 | import { ContentTypeEnum } from '@hikka/client'; 2 | import { FC } from 'react'; 3 | 4 | import { CommentList as Comments } from "@/features/comments"; 5 | import { EditActions as Actions, EditViewForm as EditView } from '@/features/edit'; 6 | 7 | interface Props { 8 | params: { editId: string }; 9 | } 10 | 11 | const EditPage: FC = async (props) => { 12 | const params = await props.params; 13 | 14 | const { editId } = params; 15 | 16 | return ( 17 |
    18 | 19 | 20 | 21 |
    22 | ); 23 | }; 24 | 25 | export default EditPage; 26 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsFeatureSearch.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsFeatureSearch(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsFeatureSearch -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsLinkRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsLinkRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsLinkRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsVisibilityOutline.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsVisibilityOutline(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsVisibilityOutline -------------------------------------------------------------------------------- /apps/web/src/components/icons/ant-design/AntDesignArrowDownOutlined.tsx: -------------------------------------------------------------------------------- 1 | import { SVGProps } from 'react'; 2 | 3 | export function AntDesignArrowDownOutlined(props: SVGProps) { 4 | return ( 5 | 12 | 16 | 17 | ); 18 | } 19 | export default AntDesignArrowDownOutlined; 20 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsGridViewRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsGridViewRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsGridViewRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsPersonAddRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsPersonAddRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsPersonAddRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsStarRateOutlineRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsStarRateOutlineRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsStarRateOutlineRounded -------------------------------------------------------------------------------- /apps/web/src/components/navigation/sub-nav.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { PropsWithChildren, useEffect, useState } from 'react'; 4 | import { createPortal } from 'react-dom'; 5 | 6 | import { useMediaQuery } from '@/services/hooks/use-media-query'; 7 | 8 | interface Props extends PropsWithChildren {} 9 | 10 | const Component = ({ children }: Props) => { 11 | const [isMounted, setIsMounted] = useState(false); 12 | const isDesktop = useMediaQuery('(min-width: 768px)'); 13 | 14 | useEffect(() => { 15 | setIsMounted(true); 16 | }, []); 17 | 18 | if (isMounted && !isDesktop) { 19 | return createPortal( 20 | <>{children}, 21 | document.getElementById('subbar-mobile')!, 22 | ); 23 | } 24 | 25 | return null; 26 | }; 27 | 28 | export default Component; 29 | -------------------------------------------------------------------------------- /apps/web/src/components/plate/editor/static-kit.tsx: -------------------------------------------------------------------------------- 1 | import { BaseBasicBlocksKit } from './plugins/basic-blocks-base-kit'; 2 | import { BaseBasicMarksKit } from './plugins/basic-marks-base-kit'; 3 | import { BaseImageGroupKit } from './plugins/image-group-base-kit'; 4 | import { BaseLinkKit } from './plugins/link-base-kit'; 5 | import { BaseListKit } from './plugins/list-classic-base-kit'; 6 | import { MarkdownKit } from './plugins/markdown-kit'; 7 | import { BaseSpoilerKit } from './plugins/spoiler-base-kit'; 8 | import { BaseVideoKit } from './plugins/video-base-kit'; 9 | 10 | export const StaticKit = [ 11 | ...BaseBasicBlocksKit, 12 | ...BaseLinkKit, 13 | ...BaseSpoilerKit, 14 | ...BaseVideoKit, 15 | ...BaseImageGroupKit, 16 | ...BaseBasicMarksKit, 17 | ...BaseListKit, 18 | ...MarkdownKit, 19 | ]; 20 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsDeleteForeverRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsDeleteForeverRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsDeleteForeverRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsHeartMinusRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsHeartMinusRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsHeartMinusRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/ant-design/AntDesignClearOutlined.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function AntDesignClearOutlined(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default AntDesignClearOutlined -------------------------------------------------------------------------------- /apps/web/src/features/content/hooks/use-staff.ts: -------------------------------------------------------------------------------- 1 | import { ContentTypeEnum } from '@hikka/client'; 2 | 3 | import { CONTENT_CONFIG } from '@/utils/constants/common'; 4 | 5 | interface StaffProps { 6 | content_type: 7 | | ContentTypeEnum.ANIME 8 | | ContentTypeEnum.MANGA 9 | | ContentTypeEnum.NOVEL; 10 | slug: string; 11 | } 12 | 13 | export const useStaff = ({ content_type, slug }: StaffProps) => { 14 | if (content_type === ContentTypeEnum.ANIME) { 15 | return CONTENT_CONFIG.anime.useStaff(slug); 16 | } 17 | 18 | let query = CONTENT_CONFIG[content_type].useInfo(slug); 19 | 20 | return { 21 | list: query.data?.authors, 22 | fetchNextPage: undefined, 23 | hasNextPage: false, 24 | isFetchingNextPage: false, 25 | ref: undefined, 26 | }; 27 | }; 28 | -------------------------------------------------------------------------------- /packages/client/types/companies.ts: -------------------------------------------------------------------------------- 1 | import { PaginationResponse } from './common'; 2 | 3 | /** 4 | * Company response 5 | */ 6 | export interface CompanyResponse { 7 | name_ua: string | null; 8 | name_en: string | null; 9 | name: string; 10 | description: string | null; 11 | slug: string; 12 | type: CompanyTypeEnum; 13 | } 14 | /** 15 | * Company type enum 16 | */ 17 | export enum CompanyTypeEnum { 18 | PRODUCER = 'producer', 19 | STUDIO = 'studio', 20 | } 21 | 22 | /** 23 | * Companies search arguments 24 | */ 25 | export interface CompaniesSearchArgs { 26 | query?: string; 27 | type?: CompanyTypeEnum; 28 | } 29 | 30 | /** 31 | * Companies list response 32 | */ 33 | export interface CompaniesPaginationResponse { 34 | list: CompanyResponse[]; 35 | pagination: PaginationResponse; 36 | } 37 | -------------------------------------------------------------------------------- /apps/web/src/components/comments/comments.tsx: -------------------------------------------------------------------------------- 1 | import { CommentResponse, CommentsContentType } from '@hikka/client'; 2 | import { FC } from 'react'; 3 | 4 | import Comment from './comment'; 5 | 6 | interface Props { 7 | comments: CommentResponse[]; 8 | slug: string; 9 | content_type: CommentsContentType; 10 | } 11 | 12 | const Comments: FC = ({ comments, slug, content_type }) => { 13 | return ( 14 |
    15 | {comments.map((comment) => ( 16 | 22 | ))} 23 |
    24 | ); 25 | }; 26 | 27 | export default Comments; 28 | -------------------------------------------------------------------------------- /apps/web/src/features/users/user-profile/user-statistics.tsx: -------------------------------------------------------------------------------- 1 | import Block from '@/components/ui/block'; 2 | import { Header, HeaderContainer, HeaderTitle } from '@/components/ui/header'; 3 | 4 | import ActivityStats from './components/user-statistics/activity-stats'; 5 | import WatchhourStats from './components/user-statistics/watchhour-stats'; 6 | 7 | const UserStatistics = () => { 8 | return ( 9 | 10 |
    11 | 12 | Статистика 13 | 14 |
    15 | 16 | 17 | 18 | 19 |
    20 | ); 21 | }; 22 | 23 | export default UserStatistics; 24 | -------------------------------------------------------------------------------- /packages/client/types/schedule.ts: -------------------------------------------------------------------------------- 1 | import { AnimeInfoResponse } from './anime'; 2 | import { ContentStatusEnum, PaginationResponse, SeasonEnum } from './common'; 3 | 4 | /** 5 | * Anime schedule arguments 6 | */ 7 | export interface AnimeScheduleArgs { 8 | airing_season?: (SeasonEnum | number)[] | null; 9 | rating?: string[]; 10 | status?: ContentStatusEnum[]; 11 | only_watch?: boolean; 12 | } 13 | 14 | /** 15 | * Anime schedule response 16 | */ 17 | export interface AnimeScheduleResponse { 18 | anime: AnimeInfoResponse; 19 | time_left: number; 20 | airing_at: number; 21 | episode: number; 22 | } 23 | 24 | /** 25 | * Paginated anime schedule response 26 | */ 27 | export interface AnimeScheduleResponsePaginationResponse { 28 | list: AnimeScheduleResponse[]; 29 | pagination: PaginationResponse; 30 | } 31 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsErrorCircleRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsErrorCircleRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsErrorCircleRounded -------------------------------------------------------------------------------- /packages/client/modules/stats.ts: -------------------------------------------------------------------------------- 1 | import { DEFAULT_PAGINATION } from '../constants'; 2 | import { BaseRequestOptionsArgs, PaginationArgs } from '../types'; 3 | import { EditsTopPaginationResponse } from '../types/stats'; 4 | import { BaseModule } from './base'; 5 | 6 | /** 7 | * Module for handling statistics 8 | */ 9 | export class StatsModule extends BaseModule { 10 | /** 11 | * Get top editors list with statistics 12 | */ 13 | public async getTopEditorsList( 14 | { page, size }: PaginationArgs, 15 | options?: BaseRequestOptionsArgs, 16 | ): Promise { 17 | return this.client.get('/stats/edits/top', { 18 | ...DEFAULT_PAGINATION, 19 | page, 20 | size, 21 | ...options, 22 | }); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /apps/web/src/app/(pages)/edit/content/page.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | HydrationBoundary, 3 | dehydrate, 4 | getQueryClient, 5 | } from '@hikka/react/core'; 6 | import { Metadata } from 'next'; 7 | 8 | import { EditContentList as ContentList } from '@/features/edit'; 9 | 10 | import _generateMetadata from '@/utils/generate-metadata'; 11 | 12 | export async function generateMetadata(): Promise { 13 | return _generateMetadata({ 14 | title: `Контент`, 15 | }); 16 | } 17 | 18 | const ContentPage = async () => { 19 | const queryClient = await getQueryClient(); 20 | 21 | const dehydratedState = dehydrate(queryClient); 22 | 23 | return ( 24 | 25 | 26 | 27 | ); 28 | }; 29 | 30 | export default ContentPage; 31 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsNotificationImportantRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsNotificationImportantRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsNotificationImportantRounded -------------------------------------------------------------------------------- /apps/web/src/features/edit/edit-actions/close-action.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useCloseEdit } from '@hikka/react'; 4 | import { useParams } from 'next/navigation'; 5 | import { FC } from 'react'; 6 | 7 | import { Button } from '@/components/ui/button'; 8 | 9 | interface Props {} 10 | 11 | const CloseAction: FC = () => { 12 | const params = useParams(); 13 | const closeEditMutation = useCloseEdit(); 14 | 15 | const handleClick = () => { 16 | closeEditMutation.mutate(Number(params.editId)); 17 | }; 18 | 19 | return ( 20 | 28 | ); 29 | }; 30 | 31 | export default CloseAction; 32 | -------------------------------------------------------------------------------- /apps/web/src/features/filters/hooks/use-change-param.ts: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { usePathname, useRouter, useSearchParams } from 'next/navigation'; 4 | 5 | import createQueryString from '@/utils/create-query-string'; 6 | 7 | const useChangeParam = () => { 8 | const router = useRouter(); 9 | const pathname = usePathname(); 10 | const searchParams = useSearchParams()!; 11 | 12 | const handleChangeParam = ( 13 | name: string, 14 | value: string | string[] | boolean, 15 | ) => { 16 | const query = createQueryString( 17 | name, 18 | value, 19 | createQueryString('page', '1', new URLSearchParams(searchParams)), 20 | ); 21 | router.replace(`${pathname}?${query}`); 22 | }; 23 | 24 | return handleChangeParam; 25 | }; 26 | 27 | export default useChangeParam; 28 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsNightlightOutlineRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsNightlightOutlineRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsNightlightOutlineRounded -------------------------------------------------------------------------------- /apps/web/src/features/edit/edit-actions/accept-action.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useAcceptEdit } from '@hikka/react'; 4 | import { useParams } from 'next/navigation'; 5 | import { FC } from 'react'; 6 | 7 | import { Button } from '@/components/ui/button'; 8 | 9 | interface Props {} 10 | 11 | const AcceptAction: FC = () => { 12 | const params = useParams(); 13 | const acceptEditMutation = useAcceptEdit(); 14 | 15 | const handleClick = () => { 16 | acceptEditMutation.mutate(Number(params.editId)); 17 | }; 18 | 19 | return ( 20 | 28 | ); 29 | }; 30 | 31 | export default AcceptAction; 32 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsDragIndicator.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsDragIndicator(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsDragIndicator -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsNewsmodeRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsNewsmodeRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsNewsmodeRounded -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsZoomInRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsZoomInRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsZoomInRounded -------------------------------------------------------------------------------- /apps/web/src/features/edit/components/edit-list/edit-head.tsx: -------------------------------------------------------------------------------- 1 | import { TableHead, TableHeader, TableRow } from '@/components/ui/table'; 2 | 3 | const EditHead = () => { 4 | return ( 5 | 6 | 7 | # 8 | Автор 9 | Контент 10 | 11 | Зміни 12 | 13 | 14 | Статус 15 | 16 | 17 | 18 | ); 19 | }; 20 | 21 | export default EditHead; 22 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsCustomTypographyRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsCustomTypographyRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsCustomTypographyRounded -------------------------------------------------------------------------------- /apps/web/src/features/auth/forgot-password-header.tsx: -------------------------------------------------------------------------------- 1 | import Link from 'next/link'; 2 | 3 | import H1 from '@/components/typography/h1'; 4 | import Small from '@/components/typography/small'; 5 | 6 | const ForgotPasswordHeader = () => { 7 | return ( 8 |
    9 |

    🔐 Відновити пароль

    10 | 11 | Будь ласка, введіть дані для отримання листа відновлення.{' '} 12 | 16 | Повернутись до входу 17 | 18 | 19 |
    20 | ); 21 | }; 22 | 23 | export default ForgotPasswordHeader; 24 | -------------------------------------------------------------------------------- /packages/client/modules/index.ts: -------------------------------------------------------------------------------- 1 | // Export all modules 2 | export * from './anime'; 3 | export * from './articles'; 4 | export * from './auth'; 5 | export * from './base'; 6 | export * from './characters'; 7 | export * from './client'; 8 | export * from './collections'; 9 | export * from './comments'; 10 | export * from './companies'; 11 | export * from './edit'; 12 | export * from './favourite'; 13 | export * from './follow'; 14 | export * from './genres'; 15 | export * from './history'; 16 | export * from './manga'; 17 | export * from './notifications'; 18 | export * from './novel'; 19 | export * from './people'; 20 | export * from './read'; 21 | export * from './related'; 22 | export * from './schedule'; 23 | export * from './settings'; 24 | export * from './stats'; 25 | export * from './upload'; 26 | export * from './user'; 27 | export * from './vote'; 28 | export * from './watch'; 29 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsPerson2OutlineRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsPerson2OutlineRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsPerson2OutlineRounded -------------------------------------------------------------------------------- /packages/client/modules/base.ts: -------------------------------------------------------------------------------- 1 | import { HikkaClient } from '../client'; 2 | 3 | /** 4 | * Base class for all API modules 5 | * 6 | * Naming conventions for methods: 7 | * - get[Resource]BySlug(slug) - Get a single resource by its slug 8 | * - get[Resource]ById(id) - Get a single resource by its ID or reference 9 | * - get[Resource]List() - Get a list of resources (usually paginated) 10 | * - search[Resource]s(args) - Search for resources with criteria 11 | * - create[Resource](args) - Create a new resource 12 | * - update[Resource](id/slug, args) - Update an existing resource 13 | * - delete[Resource](id/slug) - Delete a resource 14 | * - get[Resource][Relation](slug) - Get related resources 15 | */ 16 | export abstract class BaseModule { 17 | protected client: HikkaClient; 18 | 19 | constructor(client: HikkaClient) { 20 | this.client = client; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /apps/web/src/features/articles/article-view/article-document.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useArticleBySlug } from '@hikka/react'; 4 | import { useParams } from 'next/navigation'; 5 | import { FC } from 'react'; 6 | 7 | import { StaticViewer } from '@/components/plate/editor/static-viewer'; 8 | 9 | interface Props {} 10 | 11 | const ArticleDocument: FC = () => { 12 | const params = useParams(); 13 | 14 | const { data: article } = useArticleBySlug({ 15 | slug: String(params.slug), 16 | }); 17 | 18 | if (!article) { 19 | return null; 20 | } 21 | 22 | const document = 23 | article.document[0].type === 'preview' 24 | ? [...article.document[0].children, ...article.document.slice(1)] 25 | : article.document; 26 | 27 | return ; 28 | }; 29 | 30 | export default ArticleDocument; 31 | -------------------------------------------------------------------------------- /apps/web/src/components/icons/material-symbols/MaterialSymbolsCalendarClockRounded.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export function MaterialSymbolsCalendarClockRounded(props: SVGProps) { 4 | return ( 5 | 6 | ) 7 | } 8 | export default MaterialSymbolsCalendarClockRounded -------------------------------------------------------------------------------- /apps/web/src/components/ui/label.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import * as LabelPrimitive from '@radix-ui/react-label'; 4 | import { type VariantProps, cva } from 'class-variance-authority'; 5 | import * as React from 'react'; 6 | 7 | import { cn } from '@/utils/utils'; 8 | 9 | const labelVariants = cva( 10 | 'text-sm font-medium leading-tight peer-disabled:cursor-not-allowed peer-disabled:opacity-70', 11 | ); 12 | 13 | const Label = React.forwardRef< 14 | React.ElementRef, 15 | React.ComponentPropsWithoutRef & 16 | VariantProps 17 | >(({ className, ...props }, ref) => ( 18 | 23 | )); 24 | Label.displayName = LabelPrimitive.Root.displayName; 25 | 26 | export { Label }; 27 | -------------------------------------------------------------------------------- /apps/web/src/features/articles/article-view/article-tags.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useArticleBySlug } from '@hikka/react'; 4 | import { useParams } from 'next/navigation'; 5 | import { FC } from 'react'; 6 | 7 | import { Badge } from '@/components/ui/badge'; 8 | 9 | interface Props {} 10 | 11 | const ArticleTags: FC = () => { 12 | const params = useParams(); 13 | 14 | const { data: article } = useArticleBySlug({ 15 | slug: String(params.slug), 16 | }); 17 | 18 | if (!article?.tags || article.tags.length === 0) return null; 19 | 20 | return ( 21 |
    22 | {article?.tags.map((tag) => ( 23 | 24 | {tag.name} 25 | 26 | ))} 27 |
    28 | ); 29 | }; 30 | 31 | export default ArticleTags; 32 | -------------------------------------------------------------------------------- /packages/react/client/hooks/utils/useTitleUtils.ts: -------------------------------------------------------------------------------- 1 | import { useCallback } from 'react'; 2 | 3 | import { useHikkaClient } from '@/client/provider'; 4 | import { addDeepTitleProperties, addTitleProperty } from '@/utils'; 5 | 6 | export function useTitleUtils() { 7 | const { defaultOptions } = useHikkaClient(); 8 | 9 | const _addTitleProperty = useCallback( 10 | (obj: any) => { 11 | return addTitleProperty(obj, defaultOptions?.title); 12 | }, 13 | [defaultOptions?.title], 14 | ); 15 | 16 | const _addDeepTitleProperties = useCallback( 17 | (obj: any) => { 18 | return addDeepTitleProperties(obj, defaultOptions?.title); 19 | }, 20 | [defaultOptions?.title], 21 | ); 22 | 23 | return { 24 | addTitleProperty: _addTitleProperty, 25 | addDeepTitleProperties: _addDeepTitleProperties, 26 | }; 27 | } 28 | --------------------------------------------------------------------------------