-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
30 changed files
with
1,424 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
{ | ||
"name": "@loglib/ui", | ||
"version": "0.0.1", | ||
"description": "", | ||
"main": "./dist/index.js", | ||
"types": "./dist/index.d.ts", | ||
"scripts": { | ||
"test": "vitest run", | ||
"dev": "tsup --watch", | ||
"build": "tsup", | ||
"typecheck": "tsc --noEmit", | ||
"lint": "eslint . --ext .ts" | ||
}, | ||
"files": [ | ||
"dist", | ||
"package.json", | ||
"LICENSE", | ||
"README.md" | ||
], | ||
"keywords": [], | ||
"author": "", | ||
"license": "ISC", | ||
"exports": { | ||
".": { | ||
"require": "./dist/index.js", | ||
"import": "./dist/index.mjs" | ||
}, | ||
"./dist/index.css": "./dist/index.css" | ||
}, | ||
"devDependencies": { | ||
"@types/react": "^18.2.0", | ||
"next": "^13.4.1", | ||
"react": "link:@formkit/auto-animate/react", | ||
"react-dom": "^18.2.0" | ||
}, | ||
"peerDependencies": { | ||
"next": "^13.4.1", | ||
"react": "^18.2.0", | ||
"react-dom": "^18.2.0" | ||
}, | ||
"dependencies": { | ||
"@loglib/core": "^0.0.1", | ||
"@radix-ui/react-avatar": "^1.0.2", | ||
"@radix-ui/react-dialog": "^1.0.3", | ||
"@radix-ui/react-dropdown-menu": "^2.0.4", | ||
"@radix-ui/react-label": "^2.0.1", | ||
"@radix-ui/react-popover": "^1.0.5", | ||
"@radix-ui/react-select": "^1.2.1", | ||
"@radix-ui/react-separator": "^1.0.2", | ||
"@radix-ui/react-slot": "^1.0.1", | ||
"@radix-ui/react-tabs": "^1.0.3", | ||
"@tanstack/react-table": "^8.9.1", | ||
"@types/lodash": "^4.14.194", | ||
"add": "^2.0.6", | ||
"autoprefixer": "^10.4.14", | ||
"avatar": "^0.1.0", | ||
"class-variance-authority": "^0.6.0", | ||
"clsx": "^1.2.1", | ||
"cmdk": "^0.2.0", | ||
"date-fns": "^2.30.0", | ||
"framer-motion": "^10.12.12", | ||
"lodash": "^4.17.21", | ||
"lucide-react": "^0.220.0", | ||
"pnpx": "^0.0.1", | ||
"react-day-picker": "^8.7.1", | ||
"recharts": "^2.6.2", | ||
"shadcn-ui": "^0.1.3", | ||
"smart-array-filter": "^4.0.2", | ||
"tailwind-merge": "^1.12.0", | ||
"tailwindcss": "^3.3.2", | ||
"tailwindcss-animate": "^1.0.5" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
type StringOperator = "is" | "isNot" | "contains" | "notContains"; | ||
type NumberOperator = "lte" | "gte" | "lt" | "gt" | "is" | "isNot"; | ||
type DateOperator = "lte" | "gte" | "lt" | "gt" | "is" | "isNot"; | ||
type ArrayOperator = "contains" | "notContains"; | ||
|
||
type OperatorType<T> = T extends string ? StringOperator : T extends number ? NumberOperator : T extends Date ? DateOperator : T extends Array<any> ? ArrayOperator : never; | ||
|
||
|
||
interface FilterFunction<T, S extends keyof T = keyof T> { | ||
where: <U extends T[S]>(key: S, operator: OperatorType<U>, value: T[keyof T]) => FilterFunction<T>; | ||
or: () => FilterFunction<T>; | ||
and: () => FilterFunction<T>; | ||
execute: () => T[]; | ||
sort: (key: keyof T, desc?: boolean) => FilterFunction<T>; | ||
limit: (count: number) => FilterFunction<T>; | ||
} | ||
type Primitive = string | number | boolean | null | undefined | Date | Array<null | number | string> | ||
|
||
const filterRoot = <T extends Record<S, Primitive>, S extends keyof T>( | ||
data: T[], | ||
key: S, | ||
operator: OperatorType<T[S]>, | ||
value: T[S] | ||
): T[] => { | ||
return data.filter((item) => { | ||
switch (operator) { | ||
case "is": | ||
return item[key] === value; | ||
case "isNot": | ||
return item[key] !== value; | ||
case "contains": | ||
const a = item[key] as Array<string>; | ||
return a.includes(value as string); | ||
case "notContains": | ||
const b = item[key] as Array<string>; | ||
return !b.includes(value as string); | ||
case "gt": | ||
return item[key] > value; | ||
case "lt": | ||
return item[key] < value; | ||
case "gte": | ||
return item[key] >= value; | ||
case "lte": | ||
return item[key] <= value; | ||
default: | ||
return true; | ||
} | ||
}); | ||
}; | ||
|
||
const filter = <T extends Record<S, T[S]>, S extends keyof T>(data: T[]) => { | ||
let andFilters: ((data: T[]) => T[])[] = []; | ||
const orFilters: ((data: T[]) => T[])[] = []; | ||
let limitCount: number | undefined; | ||
|
||
const execute = (): T[] => { | ||
let result = data; | ||
|
||
if (andFilters.length > 0) { | ||
for (const filterFn of andFilters) { | ||
result = filterFn(result); | ||
} | ||
} | ||
|
||
if (orFilters.length > 0) { | ||
const orResults: T[][] = []; | ||
for (const filterFn of orFilters) { | ||
const filtered = filterFn(result); | ||
if (filtered.length > 0) { | ||
orResults.push(filtered); | ||
} | ||
} | ||
if (orResults.length > 0) { | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment | ||
result = [].concat(...orResults); | ||
} | ||
} | ||
|
||
if (limitCount !== undefined && result.length > limitCount) { | ||
result = result.slice(0, limitCount); | ||
} | ||
return result; | ||
}; | ||
|
||
const limit = (count: number): FilterFunction<T> => { | ||
limitCount = count; | ||
return { | ||
execute, | ||
where, | ||
or, | ||
and, | ||
sort, | ||
limit, | ||
}; | ||
}; | ||
|
||
|
||
const sort = (key: keyof T, desc?: boolean): FilterFunction<T> => { | ||
//sort by key | ||
const sorted = data.sort((a, b) => { | ||
if (a[key] < b[key]) { | ||
return -1; | ||
} | ||
if (a[key] > b[key]) { | ||
return 1; | ||
} | ||
return 0; | ||
}); | ||
if (desc) { | ||
sorted.reverse(); | ||
} | ||
return { | ||
execute, | ||
where, | ||
or, | ||
and, | ||
sort, | ||
limit | ||
} | ||
}; | ||
|
||
const where = <U extends T[S]>(key: S, operator: OperatorType<U>, value: T[S]): FilterFunction<T> => { | ||
andFilters.push((data) => filterRoot(data, key, operator, value)); | ||
return { | ||
where, | ||
execute, | ||
or, | ||
and, | ||
sort, | ||
limit | ||
}; | ||
}; | ||
|
||
|
||
const and = (...filters: { key: keyof T; operator: OperatorType<T[S]>; value: T[keyof T] }[]): FilterFunction<T> => { | ||
orFilters.push((data) => { | ||
let result = data; | ||
for (const filter of filters) { | ||
result = filterRoot(result, filter.key, filter.operator, filter.value); | ||
} | ||
return result; | ||
}); | ||
return { | ||
where, | ||
execute, | ||
or, | ||
and, | ||
sort, | ||
limit | ||
}; | ||
}; | ||
|
||
const or = (): FilterFunction<T> => { | ||
const currentAndFilters = andFilters; | ||
andFilters = []; | ||
orFilters.push((data) => { | ||
let result = data; | ||
for (const filterFn of currentAndFilters) { | ||
result = filterFn(result); | ||
} | ||
return result; | ||
}); | ||
return { | ||
where, | ||
execute, | ||
or, | ||
and, | ||
sort, | ||
limit | ||
}; | ||
}; | ||
return { | ||
where | ||
}; | ||
}; | ||
export { filter }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
|
||
import { User } from "@loglib/core" | ||
import { filter } from "./filter" | ||
|
||
|
||
const unqiueUsers = (data: User[],) => { | ||
filter(data).where("createdAt", "gte", new Date(new Date().getDate() - 1)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
"use client"; | ||
import { | ||
Asterisk, MapPin, | ||
MonitorSmartphone, | ||
PanelTop | ||
} from "lucide-react"; | ||
import { Card } from "./ui/card"; | ||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "./ui/tabs"; | ||
import React from "react"; | ||
import { PagesComponent } from "./PagesComponent"; | ||
import { LocationsComponent } from "./LocationsComponent"; | ||
import { DeviceComponent } from "./DeviceComponent"; | ||
import { RefComponent } from "./RefComponent"; | ||
import { refs } from "../data/refs"; | ||
import { devices } from "../data/devices"; | ||
import { locations } from "../data/locations"; | ||
import { pageViews } from "../data/pageViews"; | ||
|
||
export function BasicAnalytics() { | ||
return ( | ||
<Card className="col-span-3"> | ||
<Tabs defaultValue="pages"> | ||
<TabsList className="w-full space-x-2 justify-start"> | ||
<TabsTrigger value="pages" className=" space-x-2 "> | ||
<PanelTop size={16} /> | ||
<p>Pages</p> | ||
</TabsTrigger> | ||
<TabsTrigger value="ref" className=" space-x-2"> | ||
<Asterisk size={16} /> | ||
<p>Referees</p> | ||
</TabsTrigger> | ||
<TabsTrigger value="device" className=" space-x-2"> | ||
<MonitorSmartphone size={16} /> | ||
<p>Devices</p> | ||
</TabsTrigger> | ||
<TabsTrigger | ||
value="locations" | ||
className=" space-x-2" | ||
> | ||
<MapPin size={16} /> | ||
<p>Locations</p> | ||
</TabsTrigger> | ||
</TabsList> | ||
|
||
<TabsContent value="pages"> | ||
<PagesComponent pageViews={pageViews} /> | ||
</TabsContent> | ||
<TabsContent value="ref"> | ||
<RefComponent refs={refs} /> | ||
</TabsContent> | ||
<TabsContent value="device"> | ||
<DeviceComponent devices={devices} /> | ||
</TabsContent> | ||
<TabsContent value="locations"> | ||
<LocationsComponent locations={locations} /> | ||
</TabsContent> | ||
</Tabs> | ||
</Card> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import React from "react"; | ||
|
||
const DetailValue = ({ | ||
keyName, | ||
value, | ||
}: { | ||
keyName: string; | ||
value: number | string; | ||
}) => { | ||
return ( | ||
<div className="p-2 flex justify-between sm:grid grid-cols-2 sm:grid-cols-3 "> | ||
<dt className="font-semibold capitalize text-slate-600">{keyName}</dt> | ||
<dd className="sm:col-span-2 text-slate-500">{value}</dd> | ||
</div> | ||
); | ||
}; | ||
|
||
export default DetailValue; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
"use client"; | ||
import { CardContent } from "./ui/card"; | ||
import React from "react"; | ||
import { | ||
Table, | ||
TableBody, | ||
TableCaption, | ||
TableCell, | ||
TableHead, | ||
TableHeader, | ||
TableRow, | ||
} from "./ui/table"; | ||
|
||
export function DeviceComponent({ devices } : { devices : DevicesType[]} ) { | ||
return ( | ||
<CardContent> | ||
<Table> | ||
<TableCaption> | ||
Your devices and how many times they are visited {":)"} | ||
</TableCaption> | ||
<TableHeader> | ||
<TableRow> | ||
<TableHead>Device</TableHead> | ||
<TableHead className="text-right">Views</TableHead> | ||
</TableRow> | ||
</TableHeader> | ||
<TableBody> | ||
{devices.map((device,i) => ( | ||
<TableRow key={i}> | ||
<TableCell>{device.deviceName}</TableCell> | ||
<TableCell className="text-right">{device.value}</TableCell> | ||
</TableRow> | ||
))} | ||
</TableBody> | ||
</Table> | ||
</CardContent> | ||
); | ||
} | ||
|
||
export type DevicesType = { | ||
deviceName: string; | ||
value: number; | ||
}; |
Oops, something went wrong.