feat: showing description on image page in frontend
This commit is contained in:
@ -262,6 +262,7 @@ func (m UserModel) GetUserImages(ctx context.Context, userId uuid.UUID) ([]UserI
|
|||||||
UserImages.AllColumns,
|
UserImages.AllColumns,
|
||||||
Image.ID,
|
Image.ID,
|
||||||
Image.ImageName,
|
Image.ImageName,
|
||||||
|
Image.Description,
|
||||||
).
|
).
|
||||||
FROM(UserImages.INNER_JOIN(Image, Image.ID.EQ(UserImages.ImageID))).
|
FROM(UserImages.INNER_JOIN(Image, Image.ID.EQ(UserImages.ImageID))).
|
||||||
WHERE(UserImages.UserID.EQ(UUID(userId)))
|
WHERE(UserImages.UserID.EQ(UUID(userId)))
|
||||||
|
@ -3,7 +3,6 @@ import type { UserImage } from "../../network";
|
|||||||
import { SearchCardContact } from "./SearchCardContact";
|
import { SearchCardContact } from "./SearchCardContact";
|
||||||
import { SearchCardEvent } from "./SearchCardEvent";
|
import { SearchCardEvent } from "./SearchCardEvent";
|
||||||
import { SearchCardLocation } from "./SearchCardLocation";
|
import { SearchCardLocation } from "./SearchCardLocation";
|
||||||
import { SearchCardNote } from "./SearchCardNote";
|
|
||||||
|
|
||||||
const UnwrappedSearchCard = (props: { item: UserImage }) => {
|
const UnwrappedSearchCard = (props: { item: UserImage }) => {
|
||||||
const { item } = props;
|
const { item } = props;
|
||||||
@ -13,8 +12,6 @@ const UnwrappedSearchCard = (props: { item: UserImage }) => {
|
|||||||
return <SearchCardLocation item={item} />;
|
return <SearchCardLocation item={item} />;
|
||||||
case "event":
|
case "event":
|
||||||
return <SearchCardEvent item={item} />;
|
return <SearchCardEvent item={item} />;
|
||||||
case "note":
|
|
||||||
return <SearchCardNote item={item} />;
|
|
||||||
case "contact":
|
case "contact":
|
||||||
return <SearchCardContact item={item} />;
|
return <SearchCardContact item={item} />;
|
||||||
default:
|
default:
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
import SolidjsMarkdown from "solidjs-markdown";
|
|
||||||
|
|
||||||
import { IconNote } from "@tabler/icons-solidjs";
|
|
||||||
import type { UserImage } from "../../network";
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
item: Extract<UserImage, { type: "note" }>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const SearchCardNote = ({ item }: Props) => {
|
|
||||||
const { data } = item;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div class="h-full inset-0 p-3 bg-green-50">
|
|
||||||
<div class="flex mb-1 items-center gap-1">
|
|
||||||
<IconNote size={14} class="text-neutral-500" />
|
|
||||||
<p class="text-xs text-neutral-500">Note</p>
|
|
||||||
</div>
|
|
||||||
<p class="text-sm text-neutral-900 font-bold mb-1">
|
|
||||||
{data.Name.length > 0 ? data.Name : "Unknown 🐞"}
|
|
||||||
</p>
|
|
||||||
<p class="text-xs text-neutral-700">
|
|
||||||
<SolidjsMarkdown>{data.Content}</SolidjsMarkdown>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,30 +0,0 @@
|
|||||||
import { Separator } from "@kobalte/core/separator";
|
|
||||||
|
|
||||||
import { IconReceipt } from "@tabler/icons-solidjs";
|
|
||||||
import type { Receipt } from "../../network/types";
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
item: Receipt;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const SearchCardReceipt = ({ item }: Props) => {
|
|
||||||
const { data } = item;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div class="h-full inset-0 p-3 bg-yellow-50">
|
|
||||||
<div class="grid grid-cols-[auto_20px] gap-1 mb-1">
|
|
||||||
<p class="text-sm text-neutral-900 font-bold">
|
|
||||||
{data.orderNumber} - {data.vendor}
|
|
||||||
</p>
|
|
||||||
<IconReceipt size={20} class="text-neutral-500 mt-1" />
|
|
||||||
</div>
|
|
||||||
<p class="text-xs text-neutral-500">
|
|
||||||
{data.shippingAddress.address}
|
|
||||||
</p>
|
|
||||||
<Separator class="my-2" />
|
|
||||||
<p class="text-xs text-neutral-500 line-clamp-2 overflow-hidden">
|
|
||||||
{data.amount} {data.currency}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,26 +0,0 @@
|
|||||||
import { Separator } from "@kobalte/core/separator";
|
|
||||||
|
|
||||||
import { IconLink } from "@tabler/icons-solidjs";
|
|
||||||
import type { Website } from "../../network/types";
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
item: Website;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const SearchCardWebsite = ({ item }: Props) => {
|
|
||||||
const { data } = item;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div class="h-full inset-0 p-3 bg-blue-50">
|
|
||||||
<div class="grid grid-cols-[auto_20px] gap-1 mb-1">
|
|
||||||
<p class="text-sm text-neutral-900 font-bold">{data.title}</p>
|
|
||||||
<IconLink size={20} class="text-neutral-500 mt-1" />
|
|
||||||
</div>
|
|
||||||
<p class="text-xs text-neutral-500">{data.url}</p>
|
|
||||||
<Separator class="my-2" />
|
|
||||||
<p class="text-xs text-neutral-500 line-clamp-2 overflow-hidden">
|
|
||||||
{data.description}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
@ -104,7 +104,6 @@ export const SearchImageContextProvider: Component<ParentProps> = (props) => {
|
|||||||
contact: [],
|
contact: [],
|
||||||
event: [],
|
event: [],
|
||||||
location: [],
|
location: [],
|
||||||
note: [],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const category of data()?.ImageProperties ?? []) {
|
for (const category of data()?.ImageProperties ?? []) {
|
||||||
|
@ -22,7 +22,7 @@ type BaseRequestParams = Partial<{
|
|||||||
}>;
|
}>;
|
||||||
|
|
||||||
// export const base = "https://haystack.johncosta.tech";
|
// export const base = "https://haystack.johncosta.tech";
|
||||||
export const base = "http://192.168.1.199:3040";
|
export const base = "http://localhost:3040";
|
||||||
|
|
||||||
const getBaseRequest = ({ path, body, method }: BaseRequestParams): Request => {
|
const getBaseRequest = ({ path, body, method }: BaseRequestParams): Request => {
|
||||||
return new Request(`${base}/${path}`, {
|
return new Request(`${base}/${path}`, {
|
||||||
@ -118,15 +118,6 @@ const eventValidator = strictObject({
|
|||||||
Images: array(pipe(string(), uuid())),
|
Images: array(pipe(string(), uuid())),
|
||||||
});
|
});
|
||||||
|
|
||||||
const noteValidator = strictObject({
|
|
||||||
ID: pipe(string(), uuid()),
|
|
||||||
CreatedAt: pipe(string()),
|
|
||||||
Name: string(),
|
|
||||||
Description: nullable(string()),
|
|
||||||
Content: string(),
|
|
||||||
Images: array(pipe(string(), uuid())),
|
|
||||||
});
|
|
||||||
|
|
||||||
const locationDataType = strictObject({
|
const locationDataType = strictObject({
|
||||||
type: literal("location"),
|
type: literal("location"),
|
||||||
data: locationValidator,
|
data: locationValidator,
|
||||||
@ -137,11 +128,6 @@ const eventDataType = strictObject({
|
|||||||
data: eventValidator,
|
data: eventValidator,
|
||||||
});
|
});
|
||||||
|
|
||||||
const noteDataType = strictObject({
|
|
||||||
type: literal("note"),
|
|
||||||
data: noteValidator,
|
|
||||||
});
|
|
||||||
|
|
||||||
const contactDataType = strictObject({
|
const contactDataType = strictObject({
|
||||||
type: literal("contact"),
|
type: literal("contact"),
|
||||||
data: contactValidator,
|
data: contactValidator,
|
||||||
@ -150,7 +136,6 @@ const contactDataType = strictObject({
|
|||||||
const dataTypeValidator = variant("type", [
|
const dataTypeValidator = variant("type", [
|
||||||
locationDataType,
|
locationDataType,
|
||||||
eventDataType,
|
eventDataType,
|
||||||
noteDataType,
|
|
||||||
contactDataType,
|
contactDataType,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -164,6 +149,7 @@ const userImageValidator = strictObject({
|
|||||||
Image: strictObject({
|
Image: strictObject({
|
||||||
ID: pipe(string(), uuid()),
|
ID: pipe(string(), uuid()),
|
||||||
ImageName: string(),
|
ImageName: string(),
|
||||||
|
Description: string(),
|
||||||
Image: null_(),
|
Image: null_(),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
@ -175,6 +161,7 @@ const userProcessingImageValidator = strictObject({
|
|||||||
Image: strictObject({
|
Image: strictObject({
|
||||||
ID: pipe(string(), uuid()),
|
ID: pipe(string(), uuid()),
|
||||||
ImageName: string(),
|
ImageName: string(),
|
||||||
|
Description: string(),
|
||||||
Image: null_(),
|
Image: null_(),
|
||||||
}),
|
}),
|
||||||
Status: union([
|
Status: union([
|
||||||
|
@ -1,436 +0,0 @@
|
|||||||
import type { DataArray, DataItem } from "./types";
|
|
||||||
|
|
||||||
const getRawData = (item: DataItem) => {
|
|
||||||
return Object.values(item.data).join(" ");
|
|
||||||
};
|
|
||||||
|
|
||||||
export const sampleData: DataArray = [
|
|
||||||
{
|
|
||||||
id: "1",
|
|
||||||
type: "Event",
|
|
||||||
get rawData() {
|
|
||||||
return getRawData(this);
|
|
||||||
},
|
|
||||||
get title() {
|
|
||||||
return this.data.title;
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
title: "Startup Mixer",
|
|
||||||
dateTime: {
|
|
||||||
start: "2025-06-01T19:00:00+01:00",
|
|
||||||
end: "2025-06-01T23:00:00+01:00",
|
|
||||||
},
|
|
||||||
location: "The Kings Arms, 27 Ropemaker St, London EC2Y 9LY",
|
|
||||||
description:
|
|
||||||
"Casual networking event for tech entrepreneurs and investors in London.",
|
|
||||||
organizer: {
|
|
||||||
name: "London Startup Network",
|
|
||||||
email: "events@londonstartupnetwork.co.uk",
|
|
||||||
},
|
|
||||||
attendees: ["Alex Smith", "Sofia Rodriguez"],
|
|
||||||
category: "Networking",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "2",
|
|
||||||
type: "Contact",
|
|
||||||
get rawData() {
|
|
||||||
return getRawData(this);
|
|
||||||
},
|
|
||||||
get title() {
|
|
||||||
return this.data.name;
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
name: "João Silva",
|
|
||||||
phoneNumber: "+351 912 345 678",
|
|
||||||
emailAddress: "joao.silva@example.pt",
|
|
||||||
address: "Rua do Carmo 12, 1200-161 Lisboa, Portugal",
|
|
||||||
organization: "PortoTech Solutions",
|
|
||||||
title: "Marketing Manager",
|
|
||||||
notes: "Met at Web Summit Lisbon 2024",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "3",
|
|
||||||
type: "Location",
|
|
||||||
get rawData() {
|
|
||||||
return getRawData(this);
|
|
||||||
},
|
|
||||||
get title() {
|
|
||||||
return this.data.name;
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
name: "Barman Dictat",
|
|
||||||
address: "14 Khreshchatyk St., Kyiv, Ukraine",
|
|
||||||
category: "Bar",
|
|
||||||
description:
|
|
||||||
"Stylish cocktail bar in the heart of Kyiv with an extensive menu of craft cocktails and a sophisticated atmosphere",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "4",
|
|
||||||
type: "Note",
|
|
||||||
get rawData() {
|
|
||||||
return getRawData(this);
|
|
||||||
},
|
|
||||||
get title() {
|
|
||||||
return this.data.title;
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
title: "Q2 2025 Marketing Strategy",
|
|
||||||
keywords: ["strategy", "digital marketing", "Q2", "2025"],
|
|
||||||
content:
|
|
||||||
"## Executive Summary\n\nOur Q2 2025 marketing strategy focuses on expanding our digital presence and increasing customer engagement across all platforms. We will leverage AI-driven personalization to enhance user experience and implement a multi-channel approach to reach our target demographics more effectively.\n\n### Key Objectives\n\n1. Increase website traffic by 30% through SEO optimization and content marketing.\n2. Boost social media engagement rates by 25% using interactive campaigns and influencer partnerships.\n3. Implement a new customer loyalty program to improve retention rates by 15%.\n\nBy aligning our marketing efforts with emerging trends and customer preferences, we aim to solidify our market position and drive sustainable growth throughout Q2 and beyond.",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "5",
|
|
||||||
type: "Website",
|
|
||||||
get rawData() {
|
|
||||||
return getRawData(this);
|
|
||||||
},
|
|
||||||
get title() {
|
|
||||||
return this.data.title;
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
url: "https://www.attio.com",
|
|
||||||
title: "Attio",
|
|
||||||
description:
|
|
||||||
"Attio is the AI-native CRM that builds, scales and grows your company to the next level.",
|
|
||||||
category: "SaaS",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "6",
|
|
||||||
type: "Receipt",
|
|
||||||
get rawData() {
|
|
||||||
return getRawData(this);
|
|
||||||
},
|
|
||||||
get title() {
|
|
||||||
return `${this.data.orderNumber} - ${this.data.vendor}`;
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
receiptDate: "2025-03-12T20:15:30+01:00",
|
|
||||||
orderNumber: "ORD12345",
|
|
||||||
amount: 49.99,
|
|
||||||
currency: "GBP",
|
|
||||||
vendor: "Zara Online Store",
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
name: "Slim Fit Dress Shirt",
|
|
||||||
quantity: 1,
|
|
||||||
price: 49.99,
|
|
||||||
currency: "GBP",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
paymentMethod: "Visa",
|
|
||||||
shippingAddress: {
|
|
||||||
name: "Alex Smith",
|
|
||||||
address: "123 High St, London, EC2A 3AZ",
|
|
||||||
},
|
|
||||||
category: "Online Shopping",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "7",
|
|
||||||
type: "Event",
|
|
||||||
get rawData() {
|
|
||||||
return getRawData(this);
|
|
||||||
},
|
|
||||||
get title() {
|
|
||||||
return this.data.title;
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
title: "AI in Healthcare Summit",
|
|
||||||
dateTime: {
|
|
||||||
start: "2025-07-15T09:00:00+01:00",
|
|
||||||
end: "2025-07-15T17:00:00+01:00",
|
|
||||||
},
|
|
||||||
location:
|
|
||||||
"Royal College of Physicians, 11 St Andrews Pl, London NW1 4LE",
|
|
||||||
description:
|
|
||||||
"Annual conference exploring the latest developments in AI applications for healthcare",
|
|
||||||
organizer: {
|
|
||||||
name: "HealthTech Alliance",
|
|
||||||
email: "events@healthtechalliance.org",
|
|
||||||
},
|
|
||||||
attendees: [
|
|
||||||
"Dr. Sarah Chen",
|
|
||||||
"Prof. James Wilson",
|
|
||||||
"Dr. Maria Santos",
|
|
||||||
],
|
|
||||||
category: "Conference",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "8",
|
|
||||||
type: "Contact",
|
|
||||||
get rawData() {
|
|
||||||
return getRawData(this);
|
|
||||||
},
|
|
||||||
get title() {
|
|
||||||
return this.data.name;
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
name: "Emma Schmidt",
|
|
||||||
phoneNumber: "+49 30 12345678",
|
|
||||||
emailAddress: "e.schmidt@techberlin.de",
|
|
||||||
address: "Friedrichstraße 123, 10117 Berlin, Germany",
|
|
||||||
organization: "TechBerlin GmbH",
|
|
||||||
title: "Chief Technology Officer",
|
|
||||||
notes: "Key contact for Berlin tech scene, met at TechFest 2024",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "9",
|
|
||||||
type: "Location",
|
|
||||||
get rawData() {
|
|
||||||
return getRawData(this);
|
|
||||||
},
|
|
||||||
get title() {
|
|
||||||
return this.data.name;
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
name: "Digital Nomad Hub",
|
|
||||||
address: "Calle Princesa 25, 08001 Barcelona, Spain",
|
|
||||||
category: "Coworking Space",
|
|
||||||
description:
|
|
||||||
"Modern coworking space with high-speed internet, meeting rooms, and a vibrant community of international remote workers",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "10",
|
|
||||||
type: "Website",
|
|
||||||
get rawData() {
|
|
||||||
return getRawData(this);
|
|
||||||
},
|
|
||||||
get title() {
|
|
||||||
return this.data.title;
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
url: "https://www.techcrunch.com",
|
|
||||||
title: "TechCrunch",
|
|
||||||
description:
|
|
||||||
"Leading technology media platform covering startups, tech news, and venture capital",
|
|
||||||
category: "Tech News",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "11",
|
|
||||||
type: "Note",
|
|
||||||
get rawData() {
|
|
||||||
return getRawData(this);
|
|
||||||
},
|
|
||||||
get title() {
|
|
||||||
return this.data.title;
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
title: "Product Roadmap 2025",
|
|
||||||
keywords: ["product development", "strategy", "features", "2025"],
|
|
||||||
content:
|
|
||||||
"## Overview\n\nPriority features for 2025:\n\n1. AI-powered customer insights dashboard\n2. Integration with major CRM platforms\n3. Mobile app redesign\n4. Enhanced analytics suite\n\n### Timeline\n- Q1: Research and planning\n- Q2: Development phase 1\n- Q3: Beta testing\n- Q4: Full release",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "12",
|
|
||||||
type: "Receipt",
|
|
||||||
get rawData() {
|
|
||||||
return getRawData(this);
|
|
||||||
},
|
|
||||||
get title() {
|
|
||||||
return `${this.data.orderNumber} - ${this.data.vendor}`;
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
receiptDate: "2025-03-15T13:45:00+01:00",
|
|
||||||
orderNumber: "INV789012",
|
|
||||||
amount: 1299.99,
|
|
||||||
currency: "EUR",
|
|
||||||
vendor: "Apple Store",
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
name: "MacBook Air M3",
|
|
||||||
quantity: 1,
|
|
||||||
price: 1299.99,
|
|
||||||
currency: "EUR",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
paymentMethod: "MasterCard",
|
|
||||||
shippingAddress: {
|
|
||||||
name: "Emma Schmidt",
|
|
||||||
address: "Friedrichstraße 123, 10117 Berlin, Germany",
|
|
||||||
},
|
|
||||||
category: "Electronics",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "13",
|
|
||||||
type: "Event",
|
|
||||||
get rawData() {
|
|
||||||
return getRawData(this);
|
|
||||||
},
|
|
||||||
get title() {
|
|
||||||
return this.data.title;
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
title: "Sustainable Tech Workshop",
|
|
||||||
dateTime: {
|
|
||||||
start: "2025-08-20T14:00:00+02:00",
|
|
||||||
end: "2025-08-20T17:00:00+02:00",
|
|
||||||
},
|
|
||||||
location: "GreenTech Hub, Prinsengracht 150, Amsterdam",
|
|
||||||
description:
|
|
||||||
"Workshop on implementing sustainable practices in tech companies",
|
|
||||||
organizer: {
|
|
||||||
name: "Green Digital Alliance",
|
|
||||||
email: "workshops@greendigital.org",
|
|
||||||
},
|
|
||||||
attendees: ["Lisa van der Berg", "Mark Johnson"],
|
|
||||||
category: "Workshop",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "14",
|
|
||||||
type: "Contact",
|
|
||||||
get rawData() {
|
|
||||||
return getRawData(this);
|
|
||||||
},
|
|
||||||
get title() {
|
|
||||||
return this.data.name;
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
name: "Akiko Tanaka",
|
|
||||||
phoneNumber: "+81 3 1234 5678",
|
|
||||||
emailAddress: "a.tanaka@tokyotech.jp",
|
|
||||||
address: "2-1-1 Marunouchi, Chiyoda-ku, Tokyo 100-0005",
|
|
||||||
organization: "Tokyo Tech Ventures",
|
|
||||||
title: "Investment Director",
|
|
||||||
notes: "Specialist in Asia-Pacific tech investments",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "15",
|
|
||||||
type: "Location",
|
|
||||||
get rawData() {
|
|
||||||
return getRawData(this);
|
|
||||||
},
|
|
||||||
get title() {
|
|
||||||
return this.data.name;
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
name: "Innovation Center Stockholm",
|
|
||||||
address: "Regeringsgatan 65, 111 56 Stockholm, Sweden",
|
|
||||||
category: "Tech Hub",
|
|
||||||
description:
|
|
||||||
"Leading innovation center in Scandinavia, hosting startups and tech events",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "16",
|
|
||||||
type: "Website",
|
|
||||||
get rawData() {
|
|
||||||
return getRawData(this);
|
|
||||||
},
|
|
||||||
get title() {
|
|
||||||
return this.data.title;
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
url: "https://www.github.com",
|
|
||||||
title: "GitHub",
|
|
||||||
description: "World's leading software development platform",
|
|
||||||
category: "Development Tools",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "17",
|
|
||||||
type: "Note",
|
|
||||||
get rawData() {
|
|
||||||
return getRawData(this);
|
|
||||||
},
|
|
||||||
get title() {
|
|
||||||
return this.data.title;
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
title: "Team Structure Reorganization",
|
|
||||||
keywords: ["organization", "teams", "structure", "management"],
|
|
||||||
content:
|
|
||||||
"## Proposed Changes\n\n1. Create dedicated AI/ML team\n2. Merge frontend and mobile teams\n3. Establish DevOps center of excellence\n\n### Timeline\nGradual implementation over Q3 2025\n\n### Expected Outcomes\n- Improved efficiency\n- Better resource allocation\n- Faster delivery cycles",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "18",
|
|
||||||
type: "Receipt",
|
|
||||||
get rawData() {
|
|
||||||
return getRawData(this);
|
|
||||||
},
|
|
||||||
get title() {
|
|
||||||
return `${this.data.orderNumber} - ${this.data.vendor}`;
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
receiptDate: "2025-03-18T10:30:00+01:00",
|
|
||||||
orderNumber: "BOK456789",
|
|
||||||
amount: 850.0,
|
|
||||||
currency: "USD",
|
|
||||||
vendor: "Hilton Hotels",
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
name: "Executive Suite - 2 nights",
|
|
||||||
quantity: 1,
|
|
||||||
price: 850.0,
|
|
||||||
currency: "USD",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
paymentMethod: "American Express",
|
|
||||||
shippingAddress: {
|
|
||||||
name: "Akiko Tanaka",
|
|
||||||
address:
|
|
||||||
"Hilton San Francisco, 333 O'Farrell St, San Francisco, CA 94102",
|
|
||||||
},
|
|
||||||
category: "Travel",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "19",
|
|
||||||
type: "Event",
|
|
||||||
get rawData() {
|
|
||||||
return getRawData(this);
|
|
||||||
},
|
|
||||||
get title() {
|
|
||||||
return this.data.title;
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
title: "Web3 Developer Conference",
|
|
||||||
dateTime: {
|
|
||||||
start: "2025-09-10T09:00:00-07:00",
|
|
||||||
end: "2025-09-12T17:00:00-07:00",
|
|
||||||
},
|
|
||||||
location: "Moscone Center, 747 Howard St, San Francisco, CA 94103",
|
|
||||||
description:
|
|
||||||
"Three-day conference focusing on blockchain, DeFi, and Web3 development",
|
|
||||||
organizer: {
|
|
||||||
name: "Web3 Alliance",
|
|
||||||
email: "conference@web3alliance.org",
|
|
||||||
},
|
|
||||||
attendees: ["Vitalik B.", "Charles H.", "Gavin W."],
|
|
||||||
category: "Conference",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "20",
|
|
||||||
type: "Contact",
|
|
||||||
get rawData() {
|
|
||||||
return getRawData(this);
|
|
||||||
},
|
|
||||||
get title() {
|
|
||||||
return this.data.name;
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
name: "Rachel Chen",
|
|
||||||
phoneNumber: "+1 415 555 0123",
|
|
||||||
emailAddress: "rachel.chen@siliconvc.com",
|
|
||||||
address: "525 Market St, San Francisco, CA 94105",
|
|
||||||
organization: "Silicon Valley Capital",
|
|
||||||
title: "Partner",
|
|
||||||
notes: "Specializes in Series A/B investments in AI and ML startups",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
@ -1,106 +0,0 @@
|
|||||||
interface DateTime {
|
|
||||||
start: string;
|
|
||||||
end: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Address {
|
|
||||||
name: string;
|
|
||||||
address: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Organizer {
|
|
||||||
name: string;
|
|
||||||
email: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ReceiptItem {
|
|
||||||
name: string;
|
|
||||||
quantity: number;
|
|
||||||
price: number;
|
|
||||||
currency: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DataItemType<T extends string, D> {
|
|
||||||
id: string;
|
|
||||||
title: string;
|
|
||||||
type: T;
|
|
||||||
rawData: string;
|
|
||||||
data: D;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface EventData {
|
|
||||||
title: string;
|
|
||||||
dateTime: DateTime;
|
|
||||||
location: string;
|
|
||||||
description: string;
|
|
||||||
organizer: Organizer;
|
|
||||||
attendees: string[];
|
|
||||||
category: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ContactData {
|
|
||||||
name: string;
|
|
||||||
phoneNumber: string;
|
|
||||||
emailAddress: string;
|
|
||||||
address: string;
|
|
||||||
organization: string;
|
|
||||||
title: string;
|
|
||||||
notes: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface LocationData {
|
|
||||||
name: string;
|
|
||||||
address: string;
|
|
||||||
category: string;
|
|
||||||
description: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface NoteData {
|
|
||||||
title: string;
|
|
||||||
keywords: string[];
|
|
||||||
content: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface WebsiteData {
|
|
||||||
url: string;
|
|
||||||
title: string;
|
|
||||||
description: string;
|
|
||||||
category: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ReceiptData {
|
|
||||||
receiptDate: string;
|
|
||||||
orderNumber: string;
|
|
||||||
amount: number;
|
|
||||||
currency: string;
|
|
||||||
vendor: string;
|
|
||||||
items: ReceiptItem[];
|
|
||||||
paymentMethod: string;
|
|
||||||
shippingAddress: Address;
|
|
||||||
category: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type Event = DataItemType<"Event", EventData>;
|
|
||||||
type Contact = DataItemType<"Contact", ContactData>;
|
|
||||||
type Location = DataItemType<"Location", LocationData>;
|
|
||||||
type Note = DataItemType<"Note", NoteData>;
|
|
||||||
type Website = DataItemType<"Website", WebsiteData>;
|
|
||||||
type Receipt = DataItemType<"Receipt", ReceiptData>;
|
|
||||||
|
|
||||||
type DataItem = Event | Contact | Location | Note | Website | Receipt;
|
|
||||||
type DataArray = DataItem[];
|
|
||||||
|
|
||||||
export type {
|
|
||||||
DateTime,
|
|
||||||
Address,
|
|
||||||
Organizer,
|
|
||||||
ReceiptItem,
|
|
||||||
Event,
|
|
||||||
Contact,
|
|
||||||
Location,
|
|
||||||
Note,
|
|
||||||
Website,
|
|
||||||
Receipt,
|
|
||||||
DataItem,
|
|
||||||
DataArray,
|
|
||||||
};
|
|
@ -14,7 +14,6 @@ const CategoryColor: Record<
|
|||||||
contact: "bg-orange-50",
|
contact: "bg-orange-50",
|
||||||
location: "bg-red-50",
|
location: "bg-red-50",
|
||||||
event: "bg-purple-50",
|
event: "bg-purple-50",
|
||||||
note: "bg-green-50",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const colors = [
|
const colors = [
|
||||||
|
@ -1,14 +1,21 @@
|
|||||||
import { ImageComponent } from "@components/image";
|
import { ImageComponent } from "@components/image";
|
||||||
import { SearchCard } from "@components/search-card/SearchCard";
|
import { SearchCard } from "@components/search-card/SearchCard";
|
||||||
import { useSearchImageContext } from "@contexts/SearchImageContext";
|
import { useSearchImageContext } from "@contexts/SearchImageContext";
|
||||||
import { base, UserImage } from "@network/index";
|
import { UserImage } from "@network/index";
|
||||||
import { useParams } from "@solidjs/router";
|
import { useParams } from "@solidjs/router";
|
||||||
import { For, Show, type Component } from "solid-js";
|
import { createEffect, For, Show, type Component } from "solid-js";
|
||||||
|
import SolidjsMarkdown from "solidjs-markdown";
|
||||||
|
|
||||||
export const ImagePage: Component = () => {
|
export const ImagePage: Component = () => {
|
||||||
const { imageId } = useParams<{ imageId: string }>();
|
const { imageId } = useParams<{ imageId: string }>();
|
||||||
|
|
||||||
const { imagesWithProperties } = useSearchImageContext();
|
const { imagesWithProperties, userImages } = useSearchImageContext();
|
||||||
|
|
||||||
|
const image = () => userImages().find((i) => i.ImageID === imageId);
|
||||||
|
|
||||||
|
createEffect(() => {
|
||||||
|
console.log(userImages());
|
||||||
|
});
|
||||||
|
|
||||||
const imageProperties = (): UserImage[] | undefined =>
|
const imageProperties = (): UserImage[] | undefined =>
|
||||||
Object.entries(imagesWithProperties()).find(([id]) => id === imageId)?.[1];
|
Object.entries(imagesWithProperties()).find(([id]) => id === imageId)?.[1];
|
||||||
@ -18,6 +25,10 @@ export const ImagePage: Component = () => {
|
|||||||
<div class="w-full bg-white rounded-xl p-4">
|
<div class="w-full bg-white rounded-xl p-4">
|
||||||
<ImageComponent ID={imageId} />
|
<ImageComponent ID={imageId} />
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<h2 class="font-bold text-xl">Description</h2>
|
||||||
|
<SolidjsMarkdown>{image()?.Image.Description}</SolidjsMarkdown>
|
||||||
|
</div>
|
||||||
<div class="w-full grid grid-cols-3 gap-2 grid-flow-row-dense p-4 bg-white rounded-xl">
|
<div class="w-full grid grid-cols-3 gap-2 grid-flow-row-dense p-4 bg-white rounded-xl">
|
||||||
<Show when={imageProperties()}>
|
<Show when={imageProperties()}>
|
||||||
{(image) => (
|
{(image) => (
|
||||||
|
Reference in New Issue
Block a user